Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Mon, 08 Apr 2013 10:55:12 -0700
changeset 139726 861f3c6327a4705c7d4d6d3353ac2ce40b171ea5
parent 139725 225be6d5e41b408dbd44d769d38dac09492b350a (current diff)
parent 138888 b0d84238095938e638497cd1b02bc7005f1abdfb (diff)
child 139727 f536d418c3d2f245553251746931fdd0cb3b6f38
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to s-c.
browser/metro/base/content/LoginManagerChild.js
browser/metro/base/content/bindings/pageaction.xml
browser/metro/base/content/pages/fullscreen-video.xhtml
browser/metro/base/content/video.js
browser/metro/components/LoginManager.js
browser/metro/components/LoginManagerPrompter.idl
content/html/content/src/nsHTMLSelectElement.cpp
content/html/content/src/nsHTMLSelectElement.h
content/svg/content/src/DOMSVGTransform.cpp
content/svg/content/src/DOMSVGTransform.h
content/svg/content/src/nsSVGFilters.cpp
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_EventTarget-dispatchEvent.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-comparePoint.html.json
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_ChildNode-remove.js
dom/interfaces/core/nsIDOMDOMLocator.idl
layout/forms/test/test_bug36619.html
mach
media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_locks.c
media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_locks.h
media/webrtc/signaling/src/sipcc/cpr/darwin/cpr_darwin_locks.c
media/webrtc/signaling/src/sipcc/cpr/darwin/cpr_darwin_locks.h
media/webrtc/signaling/src/sipcc/cpr/linux/cpr_linux_locks.c
media/webrtc/signaling/src/sipcc/cpr/linux/cpr_linux_locks.h
mobile/android/base/MenuButton.java
mobile/android/base/TabsButton.java
mobile/android/base/resources/drawable-large-land-v11/tabs_button.xml
mobile/android/base/resources/drawable/menu_button.xml
mobile/android/base/resources/drawable/tabs_button.xml
parser/htmlparser/tests/crashtests/460706-1.xhtml
--- a/CLOBBER
+++ b/CLOBBER
@@ -10,13 +10,11 @@
 #                  O   <-- Users coming from both parents need to Clobber
 #               /     \
 #          O               O
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
-#  *** Important! ***
-#  If changing this file you must manually clobber immediately before landing,
-#  (due to bug 837323), using: https://secure.pub.build.mozilla.org/clobberer/
+# Modifying this file will now automatically clobber the buildbot machines \o/
 #
-Bug 737100 broke Windows builds.
+Bug 858014 broke Windows builds.
--- a/accessible/build/nsAccessibilityFactory.cpp
+++ b/accessible/build/nsAccessibilityFactory.cpp
@@ -27,24 +27,24 @@ NS_ConstructAccessibilityService(nsISupp
     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find correct interface");
     NS_RELEASE(accessibility);
     return rv;
 }
 
 NS_DEFINE_NAMED_CID(NS_ACCESSIBILITY_SERVICE_CID);
 
 static const mozilla::Module::CIDEntry kA11yCIDs[] = {
-    { &kNS_ACCESSIBILITY_SERVICE_CID, false, NULL, NS_ConstructAccessibilityService },
-    { NULL }
+    { &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, NS_ConstructAccessibilityService },
+    { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kA11yContracts[] = {
     { "@mozilla.org/accessibilityService;1", &kNS_ACCESSIBILITY_SERVICE_CID },
     { "@mozilla.org/accessibleRetrieval;1", &kNS_ACCESSIBILITY_SERVICE_CID },
-    { NULL }
+    { nullptr }
 };
 
 static const mozilla::Module kA11yModule = {
     mozilla::Module::kVersion,
     kA11yCIDs,
     kA11yContracts
 };
 
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -93,37 +93,37 @@ static GType GetAtkTypeForMai(MaiInterfa
   }
   return G_TYPE_INVALID;
 }
 
 static const char* kNonUserInputEvent = ":system";
     
 static const GInterfaceInfo atk_if_infos[] = {
     {(GInterfaceInitFunc)componentInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL}, 
+     (GInterfaceFinalizeFunc) nullptr, nullptr}, 
     {(GInterfaceInitFunc)actionInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)valueInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)editableTextInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)hypertextInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)hyperlinkImplInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)selectionInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)tableInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)textInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)documentInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL},
+     (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)imageInterfaceInitCB,
-     (GInterfaceFinalizeFunc) NULL, NULL}
+     (GInterfaceFinalizeFunc) nullptr, nullptr}
 };
 
 /**
  * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
  */
 struct MaiAtkObject
 {
   AtkObject parent;
@@ -192,37 +192,37 @@ static AtkRelationSet*     refRelationSe
   gboolean state_set);
   static void                VisibleDataChangedCB(AtkObject *aAtkObj);
 */
 G_END_DECLS
 
 static GType GetMaiAtkType(uint16_t interfacesBits);
 static const char * GetUniqueMaiAtkTypeName(uint16_t interfacesBits);
 
-static gpointer parent_class = NULL;
+static gpointer parent_class = nullptr;
 
 static GQuark quark_mai_hyperlink = 0;
 
 GType
 mai_atk_object_get_type(void)
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
             sizeof(MaiAtkObjectClass),
-            (GBaseInitFunc)NULL,
-            (GBaseFinalizeFunc)NULL,
+            (GBaseInitFunc)nullptr,
+            (GBaseFinalizeFunc)nullptr,
             (GClassInitFunc)classInitCB,
-            (GClassFinalizeFunc)NULL,
-            NULL, /* class data */
+            (GClassFinalizeFunc)nullptr,
+            nullptr, /* class data */
             sizeof(MaiAtkObject), /* instance size */
             0, /* nb preallocs */
-            (GInstanceInitFunc)NULL,
-            NULL /* value table */
+            (GInstanceInitFunc)nullptr,
+            nullptr /* value table */
         };
 
         type = g_type_register_static(ATK_TYPE_OBJECT,
                                       "MaiAtkObject", &tinfo, GTypeFlags(0));
         quark_mai_hyperlink = g_quark_from_static_string("MaiHyperlink");
     }
     return type;
 }
@@ -305,17 +305,17 @@ AccessibleWrap::GetNativeInterface(void*
             // nsIAccessible plain text leaves
             return NS_ERROR_FAILURE;
         }
 
         GType type = GetMaiAtkType(CreateMaiInterfaces());
         NS_ENSURE_TRUE(type, NS_ERROR_FAILURE);
         mAtkObject =
             reinterpret_cast<AtkObject *>
-                            (g_object_new(type, NULL));
+                            (g_object_new(type, nullptr));
         NS_ENSURE_TRUE(mAtkObject, NS_ERROR_OUT_OF_MEMORY);
 
         atk_object_initialize(mAtkObject, this);
         mAtkObject->role = ATK_ROLE_INVALID;
         mAtkObject->layer = ATK_LAYER_INVALID;
     }
 
     *aOutAccessible = mAtkObject;
@@ -396,25 +396,25 @@ AccessibleWrap::CreateMaiInterfaces(void
 }
 
 static GType
 GetMaiAtkType(uint16_t interfacesBits)
 {
     GType type;
     static const GTypeInfo tinfo = {
         sizeof(MaiAtkObjectClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) NULL,
-        (GClassFinalizeFunc) NULL,
-        NULL, /* class data */
+        (GBaseInitFunc) nullptr,
+        (GBaseFinalizeFunc) nullptr,
+        (GClassInitFunc) nullptr,
+        (GClassFinalizeFunc) nullptr,
+        nullptr, /* class data */
         sizeof(MaiAtkObject), /* instance size */
         0, /* nb preallocs */
-        (GInstanceInitFunc) NULL,
-        NULL /* value table */
+        (GInstanceInitFunc) nullptr,
+        nullptr /* value table */
     };
 
     /*
      * The members we use to register GTypes are GetAtkTypeForMai
      * and atk_if_infos, which are constant values to each MaiInterface
      * So we can reuse the registered GType when having
      * the same MaiInterface types.
      */
@@ -492,73 +492,73 @@ classInitCB(AtkObjectClass *aClass)
 
     gobject_class->finalize = finalizeCB;
 
     mai_atk_object_signals [ACTIVATE] =
     g_signal_new ("activate",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [CREATE] =
     g_signal_new ("create",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [DEACTIVATE] =
     g_signal_new ("deactivate",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [DESTROY] =
     g_signal_new ("destroy",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [MAXIMIZE] =
     g_signal_new ("maximize",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [MINIMIZE] =
     g_signal_new ("minimize",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [RESIZE] =
     g_signal_new ("resize",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
     mai_atk_object_signals [RESTORE] =
     g_signal_new ("restore",
                   MAI_TYPE_ATK_OBJECT,
                   G_SIGNAL_RUN_LAST,
                   0, /* default signal handler */
-                  NULL, NULL,
+                  nullptr, nullptr,
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
 
 }
 
 void
 initializeCB(AtkObject *aAtkObj, gpointer aData)
 {
@@ -612,17 +612,17 @@ getNameCB(AtkObject* aAtkObj)
 
 const gchar *
 getDescriptionCB(AtkObject *aAtkObj)
 {
     AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
     if (!accWrap || accWrap->IsDefunct())
         return nullptr;
 
-    /* nsIAccessible is responsible for the non-NULL description */
+    /* nsIAccessible is responsible for the non-nullptr description */
     nsAutoString uniDesc;
     accWrap->Description(uniDesc);
 
     NS_ConvertUTF8toUTF16 objDesc(aAtkObj->description);
     if (!uniDesc.Equals(objDesc))
         atk_object_set_description(aAtkObj,
                                    NS_ConvertUTF16toUTF8(uniDesc).get());
 
@@ -1214,23 +1214,23 @@ AccessibleWrap::FireAtkTextChangedEvent(
         eHaveNewAtkTextSignals : eNoNewAtkSignals;
 
   if (gAvailableAtkSignals == eNoNewAtkSignals) {
     // XXX remove this code and the gHaveNewTextSignals check when we can
     // stop supporting old atk since it doesn't really work anyway
     // see bug 619002
     signal_name = g_strconcat(isInserted ? "text_changed::insert" :
                               "text_changed::delete",
-                              isFromUserInput ? "" : kNonUserInputEvent, NULL);
+                              isFromUserInput ? "" : kNonUserInputEvent, nullptr);
     g_signal_emit_by_name(aObject, signal_name, start, length);
   } else {
     nsAutoString text;
     event->GetModifiedText(text);
     signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
-                              isFromUserInput ? "" : "::system", NULL);
+                              isFromUserInput ? "" : "::system", nullptr);
     g_signal_emit_by_name(aObject, signal_name, start, length,
                           NS_ConvertUTF16toUTF8(text).get());
   }
 
   g_free(signal_name);
   return NS_OK;
 }
 
@@ -1239,14 +1239,14 @@ AccessibleWrap::FireAtkShowHideEvent(Acc
                                      AtkObject* aObject, bool aIsAdded)
 {
     int32_t indexInParent = getIndexInParentCB(aObject);
     AtkObject *parentObject = getParentCB(aObject);
     NS_ENSURE_STATE(parentObject);
 
     bool isFromUserInput = aEvent->IsFromUserInput();
     char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" :  "children_changed::remove",
-                                    isFromUserInput ? "" : kNonUserInputEvent, NULL);
-    g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, NULL);
+                                    isFromUserInput ? "" : kNonUserInputEvent, nullptr);
+    g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, nullptr);
     g_free(signal_name);
 
     return NS_OK;
 }
--- a/accessible/src/atk/ApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/ApplicationAccessibleWrap.cpp
@@ -64,17 +64,17 @@ toplevel_event_watcher(GSignalInvocation
     } else {
 
       // Deattach the dialog accessible
       Accessible* windowAcc =
         reinterpret_cast<Accessible*>
                         (g_object_get_qdata(G_OBJECT(child), sQuark_gecko_acc_obj));
       if (windowAcc) {
         GetAccService()->RemoveNativeRootAccessible(windowAcc);
-        g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj, NULL);
+        g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj, nullptr);
       }
 
     }
   }
 
   return TRUE;
 }
 
@@ -92,17 +92,17 @@ ApplicationAccessibleWrap::Name(nsString
 NS_IMETHODIMP
 ApplicationAccessibleWrap::GetNativeInterface(void** aOutAccessible)
 {
     *aOutAccessible = nullptr;
 
     if (!mAtkObject) {
         mAtkObject =
             reinterpret_cast<AtkObject *>
-                            (g_object_new(MAI_TYPE_ATK_OBJECT, NULL));
+                            (g_object_new(MAI_TYPE_ATK_OBJECT, nullptr));
         NS_ENSURE_TRUE(mAtkObject, NS_ERROR_OUT_OF_MEMORY);
 
         atk_object_initialize(mAtkObject, this);
         mAtkObject->role = ATK_ROLE_INVALID;
         mAtkObject->layer = ATK_LAYER_INVALID;
     }
 
     *aOutAccessible = mAtkObject;
@@ -114,17 +114,17 @@ struct AtkRootAccessibleAddedEvent {
   AtkObject *root_accessible;
   uint32_t index;
 };
 
 gboolean fireRootAccessibleAddedCB(gpointer data)
 {
     AtkRootAccessibleAddedEvent* eventData = (AtkRootAccessibleAddedEvent*)data;
     g_signal_emit_by_name(eventData->app_accessible, "children_changed::add",
-                          eventData->index, eventData->root_accessible, NULL);
+                          eventData->index, eventData->root_accessible, nullptr);
     g_object_unref(eventData->app_accessible);
     g_object_unref(eventData->root_accessible);
     free(data);
 
     return FALSE;
 }
 
 bool
@@ -155,15 +155,15 @@ ApplicationAccessibleWrap::InsertChildAt
 }
 
 bool
 ApplicationAccessibleWrap::RemoveChild(Accessible* aChild)
 {
   int32_t index = aChild->IndexInParent();
 
   AtkObject* atkAccessible = AccessibleWrap::GetAtkObject(aChild);
-  atk_object_set_parent(atkAccessible, NULL);
+  atk_object_set_parent(atkAccessible, nullptr);
   g_signal_emit_by_name(mAtkObject, "children_changed::remove", index,
-                        atkAccessible, NULL);
+                        atkAccessible, nullptr);
 
   return ApplicationAccessible::RemoveChild(aChild);
 }
 
--- a/accessible/src/atk/AtkSocketAccessible.cpp
+++ b/accessible/src/atk/AtkSocketAccessible.cpp
@@ -8,17 +8,17 @@
 #include "AtkSocketAccessible.h"
 
 #include "InterfaceInitFuncs.h"
 #include "nsMai.h"
 #include "mozilla/Likely.h"
 
 using namespace mozilla::a11y;
 
-AtkSocketEmbedType AtkSocketAccessible::g_atk_socket_embed = NULL;
+AtkSocketEmbedType AtkSocketAccessible::g_atk_socket_embed = nullptr;
 GType AtkSocketAccessible::g_atk_socket_type = G_TYPE_INVALID;
 const char* AtkSocketAccessible::sATKSocketEmbedSymbol = "atk_socket_embed";
 const char* AtkSocketAccessible::sATKSocketGetTypeSymbol = "atk_socket_get_type";
 
 bool AtkSocketAccessible::gCanEmbed = FALSE;
 
 extern "C" void mai_atk_component_iface_init(AtkComponentIface* aIface);
 extern "C" GType mai_atk_socket_get_type(void);
@@ -64,21 +64,21 @@ mai_atk_socket_class_init(MaiAtkSocketCl
 void
 mai_atk_socket_init(MaiAtkSocket* aAcc)
 {
 }
 
 static AtkObject*
 mai_atk_socket_new(AccessibleWrap* aAccWrap)
 {
-  NS_ENSURE_TRUE(aAccWrap, NULL);
+  NS_ENSURE_TRUE(aAccWrap, nullptr);
 
   MaiAtkSocket* acc = nullptr;
-  acc = static_cast<MaiAtkSocket*>(g_object_new(MAI_TYPE_ATK_SOCKET, NULL));
-  NS_ENSURE_TRUE(acc, NULL);
+  acc = static_cast<MaiAtkSocket*>(g_object_new(MAI_TYPE_ATK_SOCKET, nullptr));
+  NS_ENSURE_TRUE(acc, nullptr);
 
   acc->accWrap = aAccWrap;
   return ATK_OBJECT(acc);
 }
 
 extern "C" {
 static AtkObject*
 RefAccessibleAtPoint(AtkComponent* aComponent, gint aX, gint aY,
--- a/accessible/src/atk/Platform.cpp
+++ b/accessible/src/atk/Platform.cpp
@@ -48,28 +48,28 @@ struct GnomeAccessibilityModule
     const char *initName;
     GnomeAccessibilityInit init;
     const char *shutdownName;
     GnomeAccessibilityShutdown shutdown;
 };
 
 static GnomeAccessibilityModule sAtkBridge = {
 #ifdef AIX
-    "libatk-bridge.a(libatk-bridge.so.0)", NULL,
+    "libatk-bridge.a(libatk-bridge.so.0)", nullptr,
 #else
-    "libatk-bridge.so", NULL,
+    "libatk-bridge.so", nullptr,
 #endif
-    "gnome_accessibility_module_init", NULL,
-    "gnome_accessibility_module_shutdown", NULL
+    "gnome_accessibility_module_init", nullptr,
+    "gnome_accessibility_module_shutdown", nullptr
 };
 
 static GnomeAccessibilityModule sGail = {
-    "libgail.so", NULL,
-    "gnome_accessibility_module_init", NULL,
-    "gnome_accessibility_module_shutdown", NULL
+    "libgail.so", nullptr,
+    "gnome_accessibility_module_init", nullptr,
+    "gnome_accessibility_module_shutdown", nullptr
 };
 
 static nsresult
 LoadGtkModule(GnomeAccessibilityModule& aModule)
 {
     NS_ENSURE_ARG(aModule.libName);
 
     if (!(aModule.lib = PR_LoadLibrary(aModule.libName))) {
@@ -107,17 +107,17 @@ LoadGtkModule(GnomeAccessibilityModule& 
     //we have loaded the library, try to get the function ptrs
     if (!(aModule.init = PR_FindFunctionSymbol(aModule.lib,
                                                aModule.initName)) ||
         !(aModule.shutdown = PR_FindFunctionSymbol(aModule.lib,
                                                    aModule.shutdownName))) {
 
         //fail, :(
         PR_UnloadLibrary(aModule.lib);
-        aModule.lib = NULL;
+        aModule.lib = nullptr;
         return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
 
 void
 a11y::PlatformInit()
 {
@@ -160,22 +160,22 @@ a11y::PlatformInit()
   }
 
   if (!sToplevel_event_hook_added) {
     sToplevel_event_hook_added = true;
     sToplevel_show_hook =
       g_signal_add_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW),
                                  0, toplevel_event_watcher,
                                  reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW),
-                                 NULL);
+                                 nullptr);
     sToplevel_hide_hook =
       g_signal_add_emission_hook(g_signal_lookup("hide", GTK_TYPE_WINDOW), 0,
                                  toplevel_event_watcher,
                                  reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_HIDE),
-                                 NULL);
+                                 nullptr);
   }
 }
 
 void
 a11y::PlatformShutdown()
 {
     if (sToplevel_event_hook_added) {
       sToplevel_event_hook_added = false;
@@ -186,30 +186,30 @@ a11y::PlatformShutdown()
     }
 
     if (sAtkBridge.lib) {
         // Do not shutdown/unload atk-bridge,
         // an exit function registered will take care of it
         // if (sAtkBridge.shutdown)
         //     (*sAtkBridge.shutdown)();
         // PR_UnloadLibrary(sAtkBridge.lib);
-        sAtkBridge.lib = NULL;
-        sAtkBridge.init = NULL;
-        sAtkBridge.shutdown = NULL;
+        sAtkBridge.lib = nullptr;
+        sAtkBridge.init = nullptr;
+        sAtkBridge.shutdown = nullptr;
     }
     if (sGail.lib) {
         // Do not shutdown gail because
         // 1) Maybe it's not init-ed by us. e.g. GtkEmbed
         // 2) We need it to avoid assert in spi_atk_tidy_windows
         // if (sGail.shutdown)
         //   (*sGail.shutdown)();
         // PR_UnloadLibrary(sGail.lib);
-        sGail.lib = NULL;
-        sGail.init = NULL;
-        sGail.shutdown = NULL;
+        sGail.lib = nullptr;
+        sGail.init = nullptr;
+        sGail.shutdown = nullptr;
     }
     // if (sATKLib) {
     //     PR_UnloadLibrary(sATKLib);
     //     sATKLib = nullptr;
     // }
 }
 
   static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
--- a/accessible/src/atk/UtilInterface.cpp
+++ b/accessible/src/atk/UtilInterface.cpp
@@ -37,17 +37,17 @@ struct MaiUtilListenerInfo
   gulong hook_id;
   // For window create/destory/minimize/maximize/restore/activate/deactivate
   // events, we'll chain gail_util's add/remove_global_event_listener.
   // So we store the listenerid returned by gail's add_global_event_listener
   // in this structure to call gail's remove_global_event_listener later.
   guint gail_listenerid;
 };
 
-static GHashTable* sListener_list = NULL;
+static GHashTable* sListener_list = nullptr;
 static gint sListener_idx = 1;
 
 extern "C" {
 static guint
 add_listener (GSignalEmissionHook listener,
               const gchar *object_type,
               const gchar *signal,
               const gchar *hook_data,
@@ -124,17 +124,17 @@ mai_util_remove_global_event_listener(gu
 {
     if (remove_listener > 0) {
         MaiUtilListenerInfo *listener_info;
         gint tmp_idx = remove_listener;
 
         listener_info = (MaiUtilListenerInfo *)
             g_hash_table_lookup(sListener_list, &tmp_idx);
 
-        if (listener_info != NULL) {
+        if (listener_info != nullptr) {
             if (gail_remove_global_event_listener &&
                 listener_info->gail_listenerid) {
               gail_remove_global_event_listener(listener_info->gail_listenerid);
             }
 
             /* Hook id of 0 and signal id of 0 are invalid */
             if (listener_info->hook_id != 0 && listener_info->signal_id != 0) {
                 /* Remove the emission hook */
@@ -173,17 +173,17 @@ atk_key_event_from_gdk_event_key (GdkEve
     case GDK_KEY_PRESS:
         event->type = ATK_KEY_EVENT_PRESS;
         break;
     case GDK_KEY_RELEASE:
         event->type = ATK_KEY_EVENT_RELEASE;
         break;
     default:
         g_assert_not_reached ();
-        return NULL;
+        return nullptr;
     }
     event->state = key->state;
     event->keyval = key->keyval;
     event->length = key->length;
     if (key->string && key->string [0] &&
         (key->state & GDK_CONTROL_MASK ||
          g_unichar_isgraph (g_utf8_get_char (key->string)))) {
         event->string = key->string;
@@ -221,27 +221,27 @@ notify_hf(gpointer key, gpointer value, 
 
 static void
 insert_hf(gpointer key, gpointer value, gpointer data)
 {
     GHashTable *new_table = (GHashTable *) data;
     g_hash_table_insert (new_table, key, value);
 }
 
-static GHashTable* sKey_listener_list = NULL;
+static GHashTable* sKey_listener_list = nullptr;
 
 static gint
 mai_key_snooper(GtkWidget *the_widget, GdkEventKey *event, gpointer func_data)
 {
     /* notify each AtkKeySnoopFunc in turn... */
 
     MaiKeyEventInfo *info = g_new0(MaiKeyEventInfo, 1);
     gint consumed = 0;
     if (sKey_listener_list) {
-        GHashTable *new_hash = g_hash_table_new(NULL, NULL);
+        GHashTable *new_hash = g_hash_table_new(nullptr, nullptr);
         g_hash_table_foreach (sKey_listener_list, insert_hf, new_hash);
         info->key_event = atk_key_event_from_gdk_event_key (event);
         info->func_data = func_data;
         consumed = g_hash_table_foreach_steal (new_hash, notify_hf, info);
         g_hash_table_destroy (new_hash);
         g_free(info->key_event);
     }
     g_free(info);
@@ -255,17 +255,17 @@ mai_util_add_key_event_listener (AtkKeyS
                                  gpointer data)
 {
   if (MOZ_UNLIKELY(!listener))
     return 0;
 
     static guint key=0;
 
     if (!sKey_listener_list) {
-        sKey_listener_list = g_hash_table_new(NULL, NULL);
+        sKey_listener_list = g_hash_table_new(nullptr, nullptr);
         sKey_snooper_id = gtk_key_snooper_install(mai_key_snooper, data);
     }
     AtkKeySnoopFuncPointer atkKeySnoop;
     atkKeySnoop.func_ptr = listener;
     g_hash_table_insert(sKey_listener_list, GUINT_TO_POINTER (key++),
                         atkKeySnoop.data);
     return key;
 }
@@ -363,42 +363,42 @@ UtilInterfaceInit(MaiUtilClass* klass)
     atk_class->remove_global_event_listener =
         mai_util_remove_global_event_listener;
     atk_class->add_key_event_listener = mai_util_add_key_event_listener;
     atk_class->remove_key_event_listener = mai_util_remove_key_event_listener;
     atk_class->get_root = mai_util_get_root;
     atk_class->get_toolkit_name = mai_util_get_toolkit_name;
     atk_class->get_toolkit_version = mai_util_get_toolkit_version;
 
-    sListener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
+    sListener_list = g_hash_table_new_full(g_int_hash, g_int_equal, nullptr,
                                            _listener_info_destroy);
     // Keep track of added/removed windows.
     AtkObject *root = atk_get_root ();
-    g_signal_connect (root, "children-changed::add", (GCallback) window_added, NULL);
-    g_signal_connect (root, "children-changed::remove", (GCallback) window_removed, NULL);
+    g_signal_connect (root, "children-changed::add", (GCallback) window_added, nullptr);
+    g_signal_connect (root, "children-changed::remove", (GCallback) window_removed, nullptr);
 }
 }
 
 GType
 mai_util_get_type()
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
             sizeof(MaiUtilClass),
-            (GBaseInitFunc) NULL, /* base init */
-            (GBaseFinalizeFunc) NULL, /* base finalize */
+            (GBaseInitFunc) nullptr, /* base init */
+            (GBaseFinalizeFunc) nullptr, /* base finalize */
             (GClassInitFunc) UtilInterfaceInit, /* class init */
-            (GClassFinalizeFunc) NULL, /* class finalize */
-            NULL, /* class data */
+            (GClassFinalizeFunc) nullptr, /* class finalize */
+            nullptr, /* class data */
             sizeof(MaiUtil), /* instance size */
             0, /* nb preallocs */
-            (GInstanceInitFunc) NULL, /* instance init */
-            NULL /* value table */
+            (GInstanceInitFunc) nullptr, /* instance init */
+            nullptr /* value table */
         };
 
         type = g_type_register_static(ATK_TYPE_UTIL,
                                       "MaiUtil", &tinfo, GTypeFlags(0));
     }
     return type;
 }
 
--- a/accessible/src/atk/nsMaiHyperlink.cpp
+++ b/accessible/src/atk/nsMaiHyperlink.cpp
@@ -55,37 +55,37 @@ static void finalizeCB(GObject *aObj);
 static gchar *getUriCB(AtkHyperlink *aLink, gint aLinkIndex);
 static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
 static gint getEndIndexCB(AtkHyperlink *aLink);
 static gint getStartIndexCB(AtkHyperlink *aLink);
 static gboolean isValidCB(AtkHyperlink *aLink);
 static gint getAnchorCountCB(AtkHyperlink *aLink);
 G_END_DECLS
 
-static gpointer parent_class = NULL;
+static gpointer parent_class = nullptr;
 static Accessible*
 get_accessible_hyperlink(AtkHyperlink *aHyperlink);
 
 GType
 mai_atk_hyperlink_get_type(void)
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
             sizeof(MaiAtkHyperlinkClass),
-            (GBaseInitFunc)NULL,
-            (GBaseFinalizeFunc)NULL,
+            (GBaseInitFunc)nullptr,
+            (GBaseFinalizeFunc)nullptr,
             (GClassInitFunc)classInitCB,
-            (GClassFinalizeFunc)NULL,
-            NULL, /* class data */
+            (GClassFinalizeFunc)nullptr,
+            nullptr, /* class data */
             sizeof(MaiAtkHyperlink), /* instance size */
             0, /* nb preallocs */
-            (GInstanceInitFunc)NULL,
-            NULL /* value table */
+            (GInstanceInitFunc)nullptr,
+            nullptr /* value table */
         };
 
         type = g_type_register_static(ATK_TYPE_HYPERLINK,
                                       "MaiAtkHyperlink",
                                       &tinfo, GTypeFlags(0));
     }
     return type;
 }
@@ -112,17 +112,17 @@ MaiHyperlink::GetAtkHyperlink(void)
   if (mMaiAtkHyperlink)
     return mMaiAtkHyperlink;
 
   if (!mHyperlink->IsLink())
     return nullptr;
 
     mMaiAtkHyperlink =
         reinterpret_cast<AtkHyperlink *>
-                        (g_object_new(mai_atk_hyperlink_get_type(), NULL));
+                        (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
     NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
     NS_ENSURE_TRUE(mMaiAtkHyperlink, nullptr);
 
     /* be sure to initialize it with "this" */
     MaiHyperlink::Initialize(mMaiAtkHyperlink, this);
 
     return mMaiAtkHyperlink;
 }
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -108,17 +108,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::COLUMNHEADER,
     kUseMapRole,
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     eTableCell,
     kNoReqStates,
     eARIASelectable,
-    eARIAReadonly
+    eARIAReadonlyOrEditableIfDefined
   },
   { // combobox
     &nsGkAtoms::combobox,
     roles::COMBOBOX,
     kUseMapRole,
     eNoValue,
     eOpenCloseAction,
     eNoLiveAttr,
@@ -448,17 +448,17 @@ static nsRoleMapEntry sWAIRoleMaps[] =
     roles::ROWHEADER,
     kUseMapRole,
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     eTableCell,
     kNoReqStates,
     eARIASelectable,
-    eARIAReadonly
+    eARIAReadonlyOrEditableIfDefined
   },
   { // scrollbar
     &nsGkAtoms::scrollbar,
     roles::SCROLLBAR,
     kUseMapRole,
     eHasValueMinMax,
     eNoAction,
     eNoLiveAttr,
--- a/accessible/src/base/nsAccCache.h
+++ b/accessible/src/base/nsAccCache.h
@@ -16,17 +16,17 @@
 
 /**
  * Shutdown and removes the accessible from cache.
  */
 template <class T>
 static PLDHashOperator
 ClearCacheEntry(const void* aKey, nsRefPtr<T>& aAccessible, void* aUserArg)
 {
-  NS_ASSERTION(aAccessible, "Calling ClearCacheEntry with a NULL pointer!");
+  NS_ASSERTION(aAccessible, "Calling ClearCacheEntry with a nullptr pointer!");
   if (aAccessible)
     aAccessible->Shutdown();
 
   return PL_DHASH_REMOVE;
 }
 
 /**
  * Clear the cache and shutdown the accessibles.
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -838,17 +838,17 @@ Accessible::ChildAtPoint(int32_t aX, int
   if (!foundFrame || !(content = foundFrame->GetContent()))
     return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
   DocAccessible* contentDocAcc = GetAccService()->
     GetDocAccessible(content->OwnerDoc());
 
-  // contentDocAcc in some circumstances can be NULL. See bug 729861
+  // contentDocAcc in some circumstances can be nullptr. See bug 729861
   NS_ASSERTION(contentDocAcc, "could not get the document accessible");
   if (!contentDocAcc)
     return fallbackAnswer;
 
   Accessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
   if (!accessible)
     return fallbackAnswer;
 
@@ -1596,17 +1596,19 @@ Accessible::ApplyARIAState(uint64_t* aSt
   *aState |= mRoleMapEntry->state;
 
   if (aria::MapToState(mRoleMapEntry->attributeMap1, element, aState) &&
       aria::MapToState(mRoleMapEntry->attributeMap2, element, aState))
     aria::MapToState(mRoleMapEntry->attributeMap3, element, aState);
 
   // ARIA gridcell inherits editable/readonly states from the grid until it's
   // overridden.
-  if (mRoleMapEntry->Is(nsGkAtoms::gridcell) &&
+  if ((mRoleMapEntry->Is(nsGkAtoms::gridcell) ||
+       mRoleMapEntry->Is(nsGkAtoms::columnheader) ||
+       mRoleMapEntry->Is(nsGkAtoms::rowheader)) &&
       !(*aState & (states::READONLY | states::EDITABLE))) {
     const TableCellAccessible* cell = AsTableCell();
     if (cell) {
       TableAccessible* table = cell->Table();
       if (table) {
         Accessible* grid = table->AsAccessible();
         uint64_t gridState = 0;
         grid->ApplyARIAState(&gridState);
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -516,16 +516,18 @@ public:
   virtual TableAccessible* AsTable() { return nullptr; }
 
   virtual TableCellAccessible* AsTableCell() { return nullptr; }
   const TableCellAccessible* AsTableCell() const
     { return const_cast<Accessible*>(this)->AsTableCell(); }
 
   bool IsTableRow() const { return HasGenericType(eTableRow); }
 
+  bool IsTextField() const { return mType == eHTMLTextFieldType; }
+
   bool IsTextLeaf() const { return mType == eTextLeafType; }
   TextLeafAccessible* AsTextLeaf();
 
   bool IsXULLabel() const { return mType == eXULLabelType; }
   XULLabelAccessible* AsXULLabel();
 
   bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
 
--- a/accessible/src/generic/HyperTextAccessible.cpp
+++ b/accessible/src/generic/HyperTextAccessible.cpp
@@ -2141,16 +2141,22 @@ HyperTextAccessible::ContentToRenderedOf
                                              uint32_t* aRenderedOffset)
 {
   if (!aFrame) {
     // Current frame not rendered -- this can happen if text is set on
     // something with display: none
     *aRenderedOffset = 0;
     return NS_OK;
   }
+
+  if (IsTextField()) {
+    *aRenderedOffset = aContentOffset;
+    return NS_OK;
+  }
+
   NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame,
                "Need text frame for offset conversion");
   NS_ASSERTION(aFrame->GetPrevContinuation() == nullptr,
                "Call on primary frame only");
 
   gfxSkipChars skipChars;
   gfxSkipCharsIterator iter;
   // Only get info up to original offset, we know that will be larger than skipped offset
@@ -2165,16 +2171,21 @@ HyperTextAccessible::ContentToRenderedOf
 
   return NS_OK;
 }
 
 nsresult
 HyperTextAccessible::RenderedToContentOffset(nsIFrame* aFrame, uint32_t aRenderedOffset,
                                              int32_t* aContentOffset)
 {
+  if (IsTextField()) {
+    *aContentOffset = aRenderedOffset;
+    return NS_OK;
+  }
+
   *aContentOffset = 0;
   NS_ENSURE_TRUE(aFrame, NS_ERROR_FAILURE);
 
   NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame,
                "Need text frame for offset conversion");
   NS_ASSERTION(aFrame->GetPrevContinuation() == nullptr,
                "Call on primary frame only");
 
--- a/accessible/src/generic/HyperTextAccessible.h
+++ b/accessible/src/generic/HyperTextAccessible.h
@@ -55,22 +55,22 @@ public:
   virtual uint64_t NativeState();
 
   virtual void InvalidateChildren();
   virtual bool RemoveChild(Accessible* aAccessible);
 
   // HyperTextAccessible (static helper method)
 
   // Convert content offset to rendered text offset  
-  static nsresult ContentToRenderedOffset(nsIFrame *aFrame, int32_t aContentOffset,
-                                          uint32_t *aRenderedOffset);
+  nsresult ContentToRenderedOffset(nsIFrame *aFrame, int32_t aContentOffset,
+                                   uint32_t *aRenderedOffset);
   
   // Convert rendered text offset to content offset
-  static nsresult RenderedToContentOffset(nsIFrame *aFrame, uint32_t aRenderedOffset,
-                                          int32_t *aContentOffset);
+  nsresult RenderedToContentOffset(nsIFrame *aFrame, uint32_t aRenderedOffset,
+                                   int32_t *aContentOffset);
 
   //////////////////////////////////////////////////////////////////////////////
   // HyperLinkAccessible
 
   /**
    * Return link count within this hypertext accessible.
    */
   uint32_t GetLinkCount()
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -23,35 +23,37 @@
 #include "XULTreeAccessible.h"
 #endif
 
 #include "mozilla/dom/Element.h"
 
 #include "nsIAccessibleRelation.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
-#include "nsIDOMEventTarget.h"
+#include "mozilla/dom/EventTarget.h"
 #include "nsIDOMDataContainerEvent.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDocument.h"
 #include "nsEventListenerManager.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIServiceManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsReadableUtils.h"
 #include "nsFocusManager.h"
+#include "nsDOMEvent.h"
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #include "nsIXULWindow.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::a11y;
+using namespace mozilla::dom;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED1(RootAccessible, DocAccessible, nsIAccessibleDocument)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/destructor
@@ -176,21 +178,21 @@ const char* const kEventTypes[] = {
   "DOMMenuItemInactive",
   "DOMMenuBarActive",
   "DOMMenuBarInactive"
 };
 
 nsresult
 RootAccessible::AddEventListeners()
 {
-  // nsIDOMEventTarget interface allows to register event listeners to
+  // EventTarget interface allows to register event listeners to
   // receive untrusted events (synthetic events generated by untrusted code).
   // For example, XBL bindings implementations for elements that are hosted in
   // non chrome document fire untrusted events.
-  nsCOMPtr<nsIDOMEventTarget> nstarget(do_QueryInterface(mDocumentNode));
+  nsCOMPtr<EventTarget> nstarget = mDocumentNode;
 
   if (nstarget) {
     for (const char* const* e = kEventTypes,
                    * const* e_end = ArrayEnd(kEventTypes);
          e < e_end; ++e) {
       nsresult rv = nstarget->AddEventListener(NS_ConvertASCIItoUTF16(*e),
                                                this, true, true, 2);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -198,17 +200,17 @@ RootAccessible::AddEventListeners()
   }
 
   return DocAccessible::AddEventListeners();
 }
 
 nsresult
 RootAccessible::RemoveEventListeners()
 {
-  nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocumentNode));
+  nsCOMPtr<EventTarget> target = mDocumentNode;
   if (target) { 
     for (const char* const* e = kEventTypes,
                    * const* e_end = ArrayEnd(kEventTypes);
          e < e_end; ++e) {
       nsresult rv = target->RemoveEventListener(NS_ConvertASCIItoUTF16(*e), this, true);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
@@ -229,19 +231,18 @@ RootAccessible::DocumentActivated(DocAcc
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIDOMEventListener
 
 NS_IMETHODIMP
 RootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
 {
   MOZ_ASSERT(aDOMEvent);
-  nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
-  aDOMEvent->GetOriginalTarget(getter_AddRefs(DOMEventTarget));
-  nsCOMPtr<nsINode> origTargetNode(do_QueryInterface(DOMEventTarget));
+  nsDOMEvent* event = aDOMEvent->InternalDOMEvent();
+  nsCOMPtr<nsINode> origTargetNode = do_QueryInterface(event->GetOriginalTarget());
   if (!origTargetNode)
     return NS_OK;
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDOMEvents)) {
     nsAutoString eventType;
     aDOMEvent->GetType(eventType);
     logging::DOMEvent("handled", origTargetNode, eventType);
@@ -262,19 +263,18 @@ RootAccessible::HandleEvent(nsIDOMEvent*
   return NS_OK;
 }
 
 // RootAccessible protected
 void
 RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent)
 {
   MOZ_ASSERT(aDOMEvent);
-  nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
-  aDOMEvent->GetOriginalTarget(getter_AddRefs(DOMEventTarget));
-  nsCOMPtr<nsINode> origTargetNode(do_QueryInterface(DOMEventTarget));
+  nsDOMEvent* event = aDOMEvent->InternalDOMEvent();
+  nsCOMPtr<nsINode> origTargetNode = do_QueryInterface(event->GetOriginalTarget());
 
   nsAutoString eventType;
   aDOMEvent->GetType(eventType);
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDOMEvents))
     logging::DOMEvent("processed", origTargetNode, eventType);
 #endif
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -295,16 +295,17 @@ HTMLButtonAccessible::IsWidget() const
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTextFieldAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLTextFieldAccessible::
   HTMLTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
+  mType = eHTMLTextFieldType;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED2(HTMLTextFieldAccessible,
                              Accessible,                             
                              nsIAccessibleText,
                              nsIAccessibleEditableText)
 
 role
--- a/accessible/src/jsat/Presentation.jsm
+++ b/accessible/src/jsat/Presentation.jsm
@@ -6,17 +6,16 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 Cu.import('resource://gre/modules/accessibility/UtteranceGenerator.jsm');
-Cu.import('resource://gre/modules/Geometry.jsm');
 
 this.EXPORTED_SYMBOLS = ['Presentation'];
 
 /**
  * The interface for all presenter classes. A presenter could be, for example,
  * a speech output module, or a visual cursor indicator.
  */
 function Presenter() {}
@@ -24,17 +23,17 @@ function Presenter() {}
 Presenter.prototype = {
   /**
    * The type of presenter. Used for matching it with the appropriate output method.
    */
   type: 'Base',
 
   /**
    * The virtual cursor's position changed.
-   * @param {PresenterContext} aContext the context object for the new pivot
+   * @param {PivotContext} aContext the context object for the new pivot
    *   position.
    * @param {int} aReason the reason for the pivot change.
    *   See nsIAccessiblePivot.
    */
   pivotChanged: function pivotChanged(aContext, aReason) {},
 
   /**
    * An object's action has been invoked.
@@ -67,19 +66,19 @@ Presenter.prototype = {
    *    state changed, or null if the tab has no associated document yet.
    * @param {string} aPageState the state name for the tab, valid states are:
    *    'newtab', 'loading', 'newdoc', 'loaded', 'stopped', and 'reload'.
    */
   tabStateChanged: function tabStateChanged(aDocObj, aPageState) {},
 
   /**
    * The current tab has changed.
-   * @param {PresenterContext} aDocContext context object for tab's
+   * @param {PivotContext} aDocContext context object for tab's
    *   document.
-   * @param {PresenterContext} aVCContext context object for tab's current
+   * @param {PivotContext} aVCContext context object for tab's current
    *   virtual cursor position.
    */
   tabSelected: function tabSelected(aDocContext, aVCContext) {},
 
   /**
    * The viewport has changed, either a scroll, pan, zoom, or
    *    landscape/portrait toggle.
    * @param {Window} aWindow window of viewport that changed.
@@ -110,17 +109,17 @@ VisualPresenter.prototype = {
 
   /**
    * The padding in pixels between the object and the highlight border.
    */
   BORDER_PADDING: 2,
 
   viewportChanged: function VisualPresenter_viewportChanged(aWindow) {
     if (this._currentAccessible) {
-      let context = new PresenterContext(this._currentAccessible);
+      let context = new PivotContext(this._currentAccessible);
       return {
         type: this.type,
         details: {
           method: 'showBounds',
           bounds: context.bounds,
           padding: this.BORDER_PADDING
         }
       };
@@ -213,36 +212,19 @@ AndroidPresenter.prototype = {
       this.ANDROID_VIEW_FOCUSED;
 
     if (isExploreByTouch) {
       // This isn't really used by TalkBack so this is a half-hearted attempt
       // for now.
       androidEvents.push({eventType: this.ANDROID_VIEW_HOVER_EXIT, text: []});
     }
 
-    let output = [];
-
-    aContext.newAncestry.forEach(
-      function(acc) {
-        output.push.apply(output, UtteranceGenerator.genForObject(acc));
-      }
-    );
-
-    output.push.apply(output,
-                      UtteranceGenerator.genForObject(aContext.accessible));
-
-    aContext.subtreePreorder.forEach(
-      function(acc) {
-        output.push.apply(output, UtteranceGenerator.genForObject(acc));
-      }
-    );
-
     androidEvents.push({eventType: (isExploreByTouch) ?
                           this.ANDROID_VIEW_HOVER_ENTER : focusEventType,
-                        text: output,
+                        text: UtteranceGenerator.genForContext(aContext),
                         bounds: aContext.bounds});
     return {
       type: this.type,
       details: androidEvents
     };
   },
 
   actionInvoked: function AndroidPresenter_actionInvoked(aObject, aActionName) {
@@ -337,39 +319,24 @@ SpeechPresenter.prototype = {
   __proto__: Presenter.prototype,
 
   type: 'Speech',
 
   pivotChanged: function SpeechPresenter_pivotChanged(aContext, aReason) {
     if (!aContext.accessible)
       return null;
 
-    let output = [];
-
-    aContext.newAncestry.forEach(
-      function(acc) {
-        output.push.apply(output, UtteranceGenerator.genForObject(acc));
-      }
-    );
-
-    output.push.apply(output,
-                      UtteranceGenerator.genForObject(aContext.accessible));
-
-    aContext.subtreePreorder.forEach(
-      function(acc) {
-        output.push.apply(output, UtteranceGenerator.genForObject(acc));
-      }
-    );
-
     return {
       type: this.type,
       details: {
         actions: [
           {method: 'playEarcon', data: 'tick', options: {}},
-          {method: 'speak', data: output.join(' '), options: {enqueue: true}}
+          {method: 'speak',
+            data: UtteranceGenerator.genForContext(aContext).join(' '),
+            options: {enqueue: true}}
         ]
       }
     };
   }
 };
 
 /**
  * A haptic presenter
@@ -384,130 +351,16 @@ HapticPresenter.prototype = {
 
   PIVOT_CHANGE_PATTHERN: [20],
 
   pivotChanged: function HapticPresenter_pivotChanged(aContext, aReason) {
     return { type: this.type, details: { pattern: this.PIVOT_CHANGE_PATTHERN } };
   }
 };
 
-/**
- * PresenterContext: An object that generates and caches context information
- * for a given accessible and its relationship with another accessible.
- */
-this.PresenterContext = function PresenterContext(aAccessible, aOldAccessible) {
-  this._accessible = aAccessible;
-  this._oldAccessible =
-    this._isDefunct(aOldAccessible) ? null : aOldAccessible;
-}
-
-PresenterContext.prototype = {
-  get accessible() {
-    return this._accessible;
-  },
-
-  get oldAccessible() {
-    return this._oldAccessible;
-  },
-
-  /*
-   * This is a list of the accessible's ancestry up to the common ancestor
-   * of the accessible and the old accessible. It is useful for giving the
-   * user context as to where they are in the heirarchy.
-   */
-  get newAncestry() {
-    if (!this._newAncestry) {
-      let newLineage = [];
-      let oldLineage = [];
-
-      let parent = this._accessible;
-      while (parent && (parent = parent.parent))
-        newLineage.push(parent);
-
-      parent = this._oldAccessible;
-      while (parent && (parent = parent.parent))
-        oldLineage.push(parent);
-
-      this._newAncestry = [];
-
-      while (true) {
-        let newAncestor = newLineage.pop();
-        let oldAncestor = oldLineage.pop();
-
-        if (newAncestor == undefined)
-          break;
-
-        if (newAncestor != oldAncestor)
-          this._newAncestry.push(newAncestor);
-      }
-
-    }
-
-    return this._newAncestry;
-  },
-
-  /*
-   * This is a flattened list of the accessible's subtree in preorder.
-   * It only includes the accessible's visible chidren.
-   */
-  get subtreePreorder() {
-    function traversePreorder(aAccessible) {
-      let list = [];
-      let child = aAccessible.firstChild;
-      while (child) {
-        let state = {};
-        child.getState(state, {});
-
-        if (!(state.value & Ci.nsIAccessibleStates.STATE_INVISIBLE)) {
-          list.push(child);
-          list.push.apply(list, traversePreorder(child));
-        }
-
-        child = child.nextSibling;
-      }
-      return list;
-    }
-
-    if (!this._subtreePreOrder)
-      this._subtreePreOrder = traversePreorder(this._accessible);
-
-    return this._subtreePreOrder;
-  },
-
-  get bounds() {
-    if (!this._bounds) {
-      let objX = {}, objY = {}, objW = {}, objH = {};
-
-      this._accessible.getBounds(objX, objY, objW, objH);
-
-      // XXX: OOP content provides a screen offset of 0, while in-process provides a real
-      // offset. Removing the offset and using content-relative coords normalizes this.
-      let docX = {}, docY = {};
-      let docRoot = this._accessible.rootDocument.
-        QueryInterface(Ci.nsIAccessible);
-      docRoot.getBounds(docX, docY, {}, {});
-
-      this._bounds = new Rect(objX.value, objY.value, objW.value, objH.value).
-        translate(-docX.value, -docY.value);
-    }
-
-    return this._bounds.clone();
-  },
-
-  _isDefunct: function _isDefunct(aAccessible) {
-    try {
-      let extstate = {};
-      aAccessible.getState({}, extstate);
-      return !!(aAccessible.value & Ci.nsIAccessibleStates.EXT_STATE_DEFUNCT);
-    } catch (x) {
-      return true;
-    }
-  }
-};
-
 this.Presentation = {
   get presenters() {
     delete this.presenters;
     this.presenters = [new VisualPresenter()];
 
     if (Utils.MozBuildApp == 'b2g') {
       this.presenters.push(new SpeechPresenter());
       this.presenters.push(new HapticPresenter());
@@ -516,17 +369,17 @@ this.Presentation = {
     }
 
     return this.presenters;
   },
 
   pivotChanged: function Presentation_pivotChanged(aPosition,
                                                    aOldPosition,
                                                    aReason) {
-    let context = new PresenterContext(aPosition, aOldPosition);
+    let context = new PivotContext(aPosition, aOldPosition);
     return [p.pivotChanged(context, aReason)
               for each (p in this.presenters)];
   },
 
   actionInvoked: function Presentation_actionInvoked(aObject, aActionName) {
     return [p.actionInvoked(aObject, aActionName)
               for each (p in this.presenters)];
   },
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -4,18 +4,19 @@
 
 'use strict';
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/Geometry.jsm');
 
-this.EXPORTED_SYMBOLS = ['Utils', 'Logger'];
+this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext'];
 
 this.Utils = {
   _buildAppMap: {
     '{3c2e2abc-06d4-11e1-ac3b-374f68613e61}': 'b2g',
     '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'browser',
     '{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'mobile/android',
     '{a23983c0-fd0e-11dc-95ff-0800200c9a66}': 'mobile/xul'
   },
@@ -262,8 +263,137 @@ this.Logger = {
       indentStr += ' ';
     this.log(aLogLevel, indentStr,
              this.accessibleToString(aAccessible),
              '(' + this.statesToString(aAccessible) + ')');
     for (var i=0; i < aAccessible.childCount; i++)
       this._dumpTreeInternal(aLogLevel, aAccessible.getChildAt(i), aIndent + 1);
     }
 };
+
+/**
+ * PivotContext: An object that generates and caches context information
+ * for a given accessible and its relationship with another accessible.
+ */
+this.PivotContext = function PivotContext(aAccessible, aOldAccessible) {
+  this._accessible = aAccessible;
+  this._oldAccessible =
+    this._isDefunct(aOldAccessible) ? null : aOldAccessible;
+}
+
+PivotContext.prototype = {
+  get accessible() {
+    return this._accessible;
+  },
+
+  get oldAccessible() {
+    return this._oldAccessible;
+  },
+
+  /*
+   * This is a list of the accessible's ancestry up to the common ancestor
+   * of the accessible and the old accessible. It is useful for giving the
+   * user context as to where they are in the heirarchy.
+   */
+  get newAncestry() {
+    if (!this._newAncestry) {
+      let newLineage = [];
+      let oldLineage = [];
+
+      let parent = this._accessible;
+      while (parent && (parent = parent.parent))
+        newLineage.push(parent);
+
+      parent = this._oldAccessible;
+      while (parent && (parent = parent.parent))
+        oldLineage.push(parent);
+
+      this._newAncestry = [];
+
+      while (true) {
+        let newAncestor = newLineage.pop();
+        let oldAncestor = oldLineage.pop();
+
+        if (newAncestor == undefined)
+          break;
+
+        if (newAncestor != oldAncestor)
+          this._newAncestry.push(newAncestor);
+      }
+
+    }
+
+    return this._newAncestry;
+  },
+
+  /*
+   * Traverse the accessible's subtree in pre or post order.
+   * It only includes the accessible's visible chidren.
+   */
+  _traverse: function _traverse(aAccessible, preorder) {
+    let list = [];
+    let child = aAccessible.firstChild;
+    while (child) {
+      let state = {};
+      child.getState(state, {});
+      if (!(state.value & Ci.nsIAccessibleStates.STATE_INVISIBLE)) {
+        let traversed = _traverse(child, preorder);
+        // Prepend or append a child, based on traverse order.
+        traversed[preorder ? "unshift" : "push"](child);
+        list.push.apply(list, traversed);
+      }
+      child = child.nextSibling;
+    }
+    return list;
+  },
+
+  /*
+   * This is a flattened list of the accessible's subtree in preorder.
+   * It only includes the accessible's visible chidren.
+   */
+  get subtreePreorder() {
+    if (!this._subtreePreOrder)
+      this._subtreePreOrder = this._traverse(this._accessible, true);
+
+    return this._subtreePreOrder;
+  },
+
+  /*
+   * This is a flattened list of the accessible's subtree in postorder.
+   * It only includes the accessible's visible chidren.
+   */
+  get subtreePostorder() {
+    if (!this._subtreePostOrder)
+      this._subtreePostOrder = this._traverse(this._accessible, false);
+
+    return this._subtreePostOrder;
+  },
+
+  get bounds() {
+    if (!this._bounds) {
+      let objX = {}, objY = {}, objW = {}, objH = {};
+
+      this._accessible.getBounds(objX, objY, objW, objH);
+
+      // XXX: OOP content provides a screen offset of 0, while in-process provides a real
+      // offset. Removing the offset and using content-relative coords normalizes this.
+      let docX = {}, docY = {};
+      let docRoot = this._accessible.rootDocument.
+        QueryInterface(Ci.nsIAccessible);
+      docRoot.getBounds(docX, docY, {}, {});
+
+      this._bounds = new Rect(objX.value, objY.value, objW.value, objH.value).
+        translate(-docX.value, -docY.value);
+    }
+
+    return this._bounds.clone();
+  },
+
+  _isDefunct: function _isDefunct(aAccessible) {
+    try {
+      let extstate = {};
+      aAccessible.getState({}, extstate);
+      return !!(aAccessible.value & Ci.nsIAccessibleStates.EXT_STATE_DEFUNCT);
+    } catch (x) {
+      return true;
+    }
+  }
+};
\ No newline at end of file
--- a/accessible/src/jsat/UtteranceGenerator.jsm
+++ b/accessible/src/jsat/UtteranceGenerator.jsm
@@ -8,16 +8,33 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
 const INCLUDE_CUSTOM = 0x04;
 
+const UTTERANCE_DESC_FIRST = 0;
+
+// Read and observe changes to a setting for utterance order.
+let gUtteranceOrder;
+let prefsBranch = Cc['@mozilla.org/preferences-service;1']
+  .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.');
+let observeUtterance = function observeUtterance(aSubject, aTopic, aData) {
+  try {
+    gUtteranceOrder = prefsBranch.getIntPref('utterance');
+  } catch (x) {
+    gUtteranceOrder = UTTERANCE_DESC_FIRST;
+  }
+};
+// Set initial gUtteranceOrder.
+observeUtterance();
+prefsBranch.addObserver('utterance', observeUtterance, false);
+
 var gStringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
   getService(Ci.nsIStringBundleService).
   createBundle('chrome://global/locale/AccessFu.properties');
 
 
 this.EXPORTED_SYMBOLS = ['UtteranceGenerator'];
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
@@ -50,16 +67,45 @@ this.UtteranceGenerator = {
     switch: 'switchAction',
     click: 'clickAction',
     collapse: 'collapseAction',
     expand: 'expandAction',
     activate: 'activateAction',
     cycle: 'cycleAction'
   },
 
+  /**
+   * Generates an utterance for a PivotContext.
+   * @param {PivotContext} aContext object that generates and caches
+   *    context information for a given accessible and its relationship with
+   *    another accessible.
+   * @return {Array} An array of strings. Depending on the utterance order,
+   *    the strings describe the context for an accessible object either
+   *    starting from the accessible's ancestry or accessible's subtree.
+   */
+  genForContext: function genForContext(aContext) {
+    let utterance = [];
+    let addUtterance = function addUtterance(aAccessible) {
+      utterance.push.apply(utterance,
+        UtteranceGenerator.genForObject(aAccessible));
+    };
+
+    if (gUtteranceOrder === UTTERANCE_DESC_FIRST) {
+      aContext.newAncestry.forEach(addUtterance);
+      addUtterance(aContext.accessible);
+      aContext.subtreePreorder.forEach(addUtterance);
+    } else {
+      aContext.subtreePostorder.forEach(addUtterance);
+      addUtterance(aContext.accessible);
+      aContext.newAncestry.reverse().forEach(addUtterance);
+    }
+
+    return utterance;
+  },
+
 
   /**
    * Generates an utterance for an object.
    * @param {nsIAccessible} aAccessible accessible object to generate utterance
    *    for.
    * @return {Array} Two string array. The first string describes the object
    *    and its states. The second string is the object's name. Whether the
    *    object's description or it's role is included is determined by
@@ -208,65 +254,57 @@ this.UtteranceGenerator = {
       if (aFlags & INCLUDE_DESC) {
         let desc = this._getLocalizedStates(aStates);
         let roleStr = this._getLocalizedRole(aRoleStr);
         if (roleStr)
           desc.push(roleStr);
         utterance.push(desc.join(' '));
       }
 
-      let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
-      if (name)
-        utterance.push(name);
+      this._addName(utterance, aAccessible, aFlags);
 
       return utterance;
     },
 
     entry: function entry(aAccessible, aRoleStr, aStates, aFlags) {
       let utterance = [];
       let desc = this._getLocalizedStates(aStates);
       desc.push(this._getLocalizedRole(
                   (aStates.ext & Ci.nsIAccessibleStates.EXT_STATE_MULTI_LINE) ?
                     'textarea' : 'entry'));
 
       utterance.push(desc.join(' '));
 
-      let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
-      if (name)
-        utterance.push(name);
+      this._addName(utterance, aAccessible, aFlags);
 
       return utterance;
     },
 
     heading: function heading(aAccessible, aRoleStr, aStates, aFlags) {
-      let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
       let level = {};
       aAccessible.groupPosition(level, {}, {});
       let utterance =
         [gStringBundle.formatStringFromName('headingLevel', [level.value], 1)];
 
-      if (name)
-        utterance.push(name);
+      this._addName(utterance, aAccessible, aFlags);
 
       return utterance;
     },
 
     listitem: function listitem(aAccessible, aRoleStr, aStates, aFlags) {
-      let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
       let itemno = {};
       let itemof = {};
       aAccessible.groupPosition({}, itemof, itemno);
       let utterance = [];
       if (itemno.value == 1) // Start of list
         utterance.push(gStringBundle.GetStringFromName('listStart'));
       else if (itemno.value == itemof.value) // last item
         utterance.push(gStringBundle.GetStringFromName('listEnd'));
 
-      if (name)
-        utterance.push(name);
+      this._addName(utterance, aAccessible, aFlags);
 
       return utterance;
     },
 
     list: function list(aAccessible, aRoleStr, aStates, aFlags) {
       return this._getListUtterance
         (aAccessible, aRoleStr, aFlags, aAccessible.childCount);
     },
@@ -274,23 +312,31 @@ this.UtteranceGenerator = {
     definitionlist: function definitionlist(aAccessible, aRoleStr, aStates, aFlags) {
       return this._getListUtterance
         (aAccessible, aRoleStr, aFlags, aAccessible.childCount / 2);
     },
 
     application: function application(aAccessible, aRoleStr, aStates, aFlags) {
       // Don't utter location of applications, it gets tiring.
       if (aAccessible.name != aAccessible.DOMNode.location)
-        return this.objectUtteranceFunctions.defaultFunc(
-          aAccessible, aRoleStr, aStates, aFlags);
+        return this.objectUtteranceFunctions.defaultFunc.apply(this,
+          [aAccessible, aRoleStr, aStates, aFlags]);
 
       return [];
     }
   },
 
+  _addName: function _addName(utterance, aAccessible, aFlags) {
+    let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
+    if (name) {
+      utterance[gUtteranceOrder === UTTERANCE_DESC_FIRST ?
+        "push" : "unshift"](name);
+    }
+  },
+
   _getLocalizedRole: function _getLocalizedRole(aRoleStr) {
     try {
       return gStringBundle.GetStringFromName(aRoleStr.replace(' ', ''));
     } catch (x) {
       return '';
     }
   },
 
@@ -320,23 +366,21 @@ this.UtteranceGenerator = {
     if (aStates.base & Ci.nsIAccessibleStates.STATE_TRAVERSED) {
       stateUtterances.push(gStringBundle.GetStringFromName('stateTraversed'));
     }
 
     return stateUtterances;
   },
 
   _getListUtterance: function _getListUtterance(aAccessible, aRoleStr, aFlags, aItemCount) {
-    let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : '';
     let desc = [];
     let roleStr = this._getLocalizedRole(aRoleStr);
     if (roleStr)
       desc.push(roleStr);
     desc.push
       (gStringBundle.formatStringFromName('listItemCount', [aItemCount], 1));
     let utterance = [desc.join(' ')];
 
-    if (name)
-      utterance.push(name);
+    this._addName(utterance, aAccessible, aFlags);
 
     return utterance;
   }
 };
--- a/accessible/src/windows/ia2/ia2AccessibleAction.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleAction.cpp
@@ -13,17 +13,17 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleAction::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleAction == iid) {
     *ppv = static_cast<IAccessibleAction*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return E_NOINTERFACE;
@@ -67,17 +67,17 @@ ia2AccessibleAction::doAction(long aActi
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aDescription = NULL;
+  *aDescription = nullptr;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString description;
   uint8_t index = static_cast<uint8_t>(aActionIndex);
   nsresult rv = acc->GetActionDescription(index, description);
@@ -98,17 +98,17 @@ STDMETHODIMP
 ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
                                   BSTR **aKeyBinding,
                                   long *aNumBinding)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aKeyBinding)
     return E_INVALIDARG;
-  *aKeyBinding = NULL;
+  *aKeyBinding = nullptr;
 
   if (!aNumBinding)
     return E_INVALIDARG;
   *aNumBinding = 0;
 
   if (aActionIndex != 0 || aNumMaxBinding < 1)
     return E_INVALIDARG;
 
@@ -144,17 +144,17 @@ ia2AccessibleAction::get_keyBinding(long
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aName = NULL;
+  *aName = nullptr;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
   uint8_t index = static_cast<uint8_t>(aActionIndex);
   nsresult rv = acc->GetActionName(index, name);
@@ -170,14 +170,14 @@ ia2AccessibleAction::get_name(long aActi
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aLocalizedName = NULL;
+  *aLocalizedName = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
--- a/accessible/src/windows/ia2/ia2AccessibleComponent.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleComponent.cpp
@@ -16,17 +16,17 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleComponent::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleComponent == iid) {
     *ppv = static_cast<IAccessibleComponent*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return E_NOINTERFACE;
--- a/accessible/src/windows/ia2/ia2AccessibleHyperlink.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleHyperlink.cpp
@@ -13,17 +13,17 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleHyperlink::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleHyperlink == iid) {
     if (!static_cast<AccessibleWrap*>(this)->IsLink())
       return E_NOINTERFACE;
 
     *ppv = static_cast<IAccessibleHyperlink*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
@@ -51,17 +51,17 @@ ia2AccessibleHyperlink::get_anchor(long 
   if (!thisObj->IsLink())
     return S_FALSE;
 
   AccessibleWrap* anchor =
     static_cast<AccessibleWrap*>(thisObj->AnchorAt(aIndex));
   if (!anchor)
     return S_FALSE;
 
-  void* instancePtr = NULL;
+  void* instancePtr = nullptr;
   HRESULT result = anchor->QueryInterface(IID_IUnknown, &instancePtr);
   if (FAILED(result))
     return result;
 
   IUnknown* unknownPtr = static_cast<IUnknown*>(instancePtr);
   aAnchor->ppunkVal = &unknownPtr;
   aAnchor->vt = VT_UNKNOWN;
   return S_OK;
--- a/accessible/src/windows/ia2/ia2AccessibleHypertext.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleHypertext.cpp
@@ -33,17 +33,17 @@ ia2AccessibleHypertext::get_nHyperlinks(
 }
 
 STDMETHODIMP
 ia2AccessibleHypertext::get_hyperlink(long aLinkIndex,
                                       IAccessibleHyperlink** aHyperlink)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aHyperlink = NULL;
+  *aHyperlink = nullptr;
 
   HyperTextAccessibleWrap* hyperText = static_cast<HyperTextAccessibleWrap*>(this);
   if (hyperText->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* hyperLink = hyperText->GetLinkAt(aLinkIndex);
   if (!hyperLink)
     return E_FAIL;
--- a/accessible/src/windows/ia2/ia2AccessibleImage.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleImage.cpp
@@ -21,17 +21,17 @@
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleImage::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleImage == iid) {
     *ppv = static_cast<IAccessibleImage*>(this);
     (static_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return E_NOINTERFACE;
@@ -39,17 +39,17 @@ ia2AccessibleImage::QueryInterface(REFII
 
 // IAccessibleImage
 
 STDMETHODIMP
 ia2AccessibleImage::get_description(BSTR* aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aDescription = NULL;
+  *aDescription = nullptr;
 
   ImageAccessibleWrap* acc = static_cast<ImageAccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString description;
   nsresult rv = acc->GetName(description);
   if (NS_FAILED(rv))
--- a/accessible/src/windows/ia2/ia2AccessibleRelation.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleRelation.cpp
@@ -27,17 +27,17 @@ ia2AccessibleRelation::ia2AccessibleRela
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleRelation::QueryInterface(REFIID iid, void** ppv)
 {
   if (!ppv)
     return E_INVALIDARG;
 
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleRelation == iid || IID_IUnknown == iid) {
     *ppv = static_cast<IAccessibleRelation*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return E_NOINTERFACE;
@@ -65,17 +65,17 @@ ia2AccessibleRelation::Release()
 STDMETHODIMP
 ia2AccessibleRelation::get_relationType(BSTR *aRelationType)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aRelationType)
     return E_INVALIDARG;
 
-  *aRelationType = NULL;
+  *aRelationType = nullptr;
 
   switch (mType) {
     case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
       *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLED_BY);
       break;
     case nsIAccessibleRelation::RELATION_CONTROLLER_FOR:
       *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLER_FOR);
       break;
@@ -130,17 +130,17 @@ ia2AccessibleRelation::get_relationType(
 STDMETHODIMP
 ia2AccessibleRelation::get_localizedRelationType(BSTR *aLocalizedRelationType)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aLocalizedRelationType)
     return E_INVALIDARG;
 
-  *aLocalizedRelationType = NULL;
+  *aLocalizedRelationType = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleRelation::get_nTargets(long *aNTargets)
 {
--- a/accessible/src/windows/ia2/ia2AccessibleTable.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleTable.cpp
@@ -20,17 +20,17 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleTable::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleTable == iid) {
     statistics::IAccessibleTableUsed();
     *ppv = static_cast<IAccessibleTable*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
@@ -53,17 +53,17 @@ ia2AccessibleTable::get_accessibleAt(lon
   return get_cellAt(aRowIdx, aColIdx, aAccessible);
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_caption(IUnknown** aAccessible)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aAccessible = NULL;
+  *aAccessible = nullptr;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   AccessibleWrap* caption = static_cast<AccessibleWrap*>(mTable->Caption());
   if (!caption)
     return S_FALSE;
 
   (*aAccessible = static_cast<IAccessible*>(caption))->AddRef();
@@ -93,17 +93,17 @@ ia2AccessibleTable::get_childIndex(long 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnDescription(long aColIdx, BSTR* aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aDescription = NULL;
+  *aDescription = nullptr;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= mTable->ColCount())
     return E_INVALIDARG;
 
   nsAutoString descr;
   mTable->ColDescription(aColIdx, descr);
@@ -138,17 +138,17 @@ ia2AccessibleTable::get_columnExtentAt(l
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnHeader(IAccessibleTable** aAccessibleTable,
                                     long* aStartingRowIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aAccessibleTable = NULL;
+  *aAccessibleTable = nullptr;
   *aStartingRowIndex = -1;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_columnIndex(long aCellIdx, long* aColIdx)
@@ -236,17 +236,17 @@ ia2AccessibleTable::get_nSelectedRows(lo
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowDescription(long aRowIdx, BSTR* aDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aDescription = NULL;
+  *aDescription = nullptr;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= mTable->RowCount())
     return E_INVALIDARG;
 
   nsAutoString descr;
   mTable->RowDescription(aRowIdx, descr);
@@ -280,17 +280,17 @@ ia2AccessibleTable::get_rowExtentAt(long
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowHeader(IAccessibleTable** aAccessibleTable,
                                   long* aStartingColumnIndex)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aAccessibleTable = NULL;
+  *aAccessibleTable = nullptr;
   *aStartingColumnIndex = -1;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_rowIndex(long aCellIdx, long* aRowIdx)
@@ -312,17 +312,17 @@ ia2AccessibleTable::get_rowIndex(long aC
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedChildren(long aMaxChildren, long** aChildren,
                                          long* aNChildren)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aChildren = NULL;
+  *aChildren = nullptr;
   *aNChildren = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<uint32_t, 30> cellIndices;
   mTable->SelectedCellIndices(&cellIndices);
 
   uint32_t maxCells = cellIndices.Length();
@@ -365,17 +365,17 @@ ia2AccessibleTable::get_summary(IUnknown
 {
   A11Y_TRYBLOCK_BEGIN
 
   // Neither html:table nor xul:tree nor ARIA grid/tree have an ability to
   // link an accessible object to specify a summary. There is closes method
   // in nsIAccessibleTable::summary to get a summary as a string which is not
   // mapped directly to IAccessible2.
 
-  *aAccessible = NULL;
+  *aAccessible = nullptr;
   return S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_isColumnSelected(long aColIdx, boolean* aIsSelected)
 {
@@ -544,17 +544,17 @@ ia2AccessibleTable::get_modelChange(IA2T
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessibleTable2
 
 STDMETHODIMP
 ia2AccessibleTable::get_cellAt(long aRowIdx, long aColIdx, IUnknown** aCell)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aCell = NULL;
+  *aCell = nullptr;
 
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   AccessibleWrap* cell =
     static_cast<AccessibleWrap*>(mTable->CellAt(aRowIdx, aColIdx));
   if (!cell)
     return E_INVALIDARG;
@@ -580,17 +580,17 @@ ia2AccessibleTable::get_nSelectedCells(l
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedCells(IUnknown*** aCells, long* aNSelectedCells)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aCells = NULL;
+  *aCells = nullptr;
   *aNSelectedCells = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<Accessible*, 30> cells;
   mTable->SelectedCells(&cells);
   if (cells.IsEmpty())
     return S_FALSE;
@@ -613,17 +613,17 @@ ia2AccessibleTable::get_selectedCells(IU
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedColumns(long** aColumns, long* aNColumns)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aColumns = NULL;
+  *aColumns = nullptr;
   *aNColumns = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<uint32_t, 30> colIndices;
   mTable->SelectedColIndices(&colIndices);
 
   uint32_t maxCols = colIndices.Length();
@@ -640,17 +640,17 @@ ia2AccessibleTable::get_selectedColumns(
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleTable::get_selectedRows(long** aRows, long* aNRows)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aRows = NULL;
+  *aRows = nullptr;
   *aNRows = 0;
   if (!mTable)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<uint32_t, 30> rowIndices;
   mTable->SelectedRowIndices(&rowIndices);
 
   uint32_t maxRows = rowIndices.Length();
--- a/accessible/src/windows/ia2/ia2AccessibleTableCell.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleTableCell.cpp
@@ -20,17 +20,17 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleTableCell::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleTableCell == iid) {
     *ppv = static_cast<IAccessibleTableCell*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return E_NOINTERFACE;
@@ -39,17 +39,17 @@ ia2AccessibleTableCell::QueryInterface(R
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessibleTableCell
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_table(IUnknown** aTable)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aTable = NULL;
+  *aTable = nullptr;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   TableAccessible* table = mTableCell->Table();
   if (!table)
     return E_FAIL;
 
   AccessibleWrap* wrap = static_cast<AccessibleWrap*>(table->AsAccessible());
@@ -77,17 +77,17 @@ ia2AccessibleTableCell::get_columnExtent
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_columnHeaderCells(IUnknown*** aCellAccessibles,
                                               long* aNColumnHeaderCells)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aCellAccessibles = NULL;
+  *aCellAccessibles = nullptr;
   *aNColumnHeaderCells = 0;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<Accessible*, 10> cells;
   mTableCell->ColHeaderCells(&cells);
 
   *aNColumnHeaderCells = cells.Length();
@@ -140,17 +140,17 @@ ia2AccessibleTableCell::get_rowExtent(lo
 }
 
 STDMETHODIMP
 ia2AccessibleTableCell::get_rowHeaderCells(IUnknown*** aCellAccessibles,
                                            long* aNRowHeaderCells)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aCellAccessibles = NULL;
+  *aCellAccessibles = nullptr;
   *aNRowHeaderCells = 0;
   if (!mTableCell)
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoTArray<Accessible*, 10> cells;
   mTableCell->RowHeaderCells(&cells);
 
   *aNRowHeaderCells = cells.Length();
--- a/accessible/src/windows/ia2/ia2AccessibleText.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleText.cpp
@@ -39,17 +39,17 @@ ia2AccessibleText::get_attributes(long a
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aStartOffset || !aEndOffset || !aTextAttributes)
     return E_INVALIDARG;
 
   *aStartOffset = 0;
   *aEndOffset = 0;
-  *aTextAttributes = NULL;
+  *aTextAttributes = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   int32_t startOffset = 0, endOffset = 0;
   nsCOMPtr<nsIPersistentProperties> attributes;
   nsresult rv = textAcc->GetTextAttributes(true, aOffset,
@@ -205,17 +205,17 @@ ia2AccessibleText::get_selection(long aS
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aText = NULL;
+  *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString text;
   nsresult rv = textAcc->GetText(aStartOffset, aEndOffset, text);
   if (NS_FAILED(rv))
@@ -235,17 +235,17 @@ ia2AccessibleText::get_textBeforeOffset(
                                         enum IA2TextBoundaryType aBoundaryType,
                                         long *aStartOffset, long *aEndOffset,
                                         BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
   *aStartOffset = 0;
   *aEndOffset = 0;
-  *aText = NULL;
+  *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsresult rv = NS_OK;
   nsAutoString text;
   int32_t startOffset = 0, endOffset = 0;
@@ -282,17 +282,17 @@ ia2AccessibleText::get_textAfterOffset(l
                                        enum IA2TextBoundaryType aBoundaryType,
                                        long *aStartOffset, long *aEndOffset,
                                        BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
   *aStartOffset = 0;
   *aEndOffset = 0;
-  *aText = NULL;
+  *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsresult rv = NS_OK;
   nsAutoString text;
   int32_t startOffset = 0, endOffset = 0;
@@ -329,17 +329,17 @@ ia2AccessibleText::get_textAtOffset(long
                                     enum IA2TextBoundaryType aBoundaryType,
                                     long *aStartOffset, long *aEndOffset,
                                     BSTR *aText)
 {
   A11Y_TRYBLOCK_BEGIN
 
   *aStartOffset = 0;
   *aEndOffset = 0;
-  *aText = NULL;
+  *aText = nullptr;
 
   HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
   if (textAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsresult rv = NS_OK;
   nsAutoString text;
   int32_t startOffset = 0, endOffset = 0;
--- a/accessible/src/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleValue.cpp
@@ -14,17 +14,17 @@
 
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleValue::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleValue == iid) {
     AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
     if (valueAcc->HasNumericValue()) {
       *ppv = static_cast<IAccessibleValue*>(this);
       valueAcc->AddRef();
       return S_OK;
     }
--- a/accessible/src/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/AccessibleWrap.cpp
@@ -59,31 +59,31 @@ static gAccessibles = 0;
 #endif
 
 static const int32_t kIEnumVariantDisconnected = -1;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
 
-ITypeInfo* AccessibleWrap::gTypeInfo = NULL;
+ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
 
 NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
 
 //-----------------------------------------------------
 // IUnknown interface methods - see iunknown.h for documentation
 //-----------------------------------------------------
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid)
     *ppv = static_cast<IAccessible*>(this);
   else if (IID_IEnumVARIANT == iid) {
     // Don't support this interface for leaf elements.
     if (!HasChildren() || nsAccUtils::MustPrune(this))
       return E_NOINTERFACE;
 
@@ -94,35 +94,35 @@ AccessibleWrap::QueryInterface(REFIID ii
     *ppv = static_cast<IAccessible2*>(this);
   else if (IID_ISimpleDOMNode == iid) {
     if (IsDefunct() || (!HasOwnContent() && !IsDoc()))
       return E_NOINTERFACE;
 
     *ppv = new sdnAccessible(GetNode());
   }
 
-  if (NULL == *ppv) {
+  if (nullptr == *ppv) {
     HRESULT hr = ia2AccessibleComponent::QueryInterface(iid, ppv);
     if (SUCCEEDED(hr))
       return hr;
   }
 
-  if (NULL == *ppv) {
+  if (nullptr == *ppv) {
     HRESULT hr = ia2AccessibleHyperlink::QueryInterface(iid, ppv);
     if (SUCCEEDED(hr))
       return hr;
   }
 
-  if (NULL == *ppv) {
+  if (nullptr == *ppv) {
     HRESULT hr = ia2AccessibleValue::QueryInterface(iid, ppv);
     if (SUCCEEDED(hr))
       return hr;
   }
 
-  if (NULL == *ppv)
+  if (nullptr == *ppv)
     return E_NOINTERFACE;
 
   (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -130,17 +130,17 @@ AccessibleWrap::QueryInterface(REFIID ii
 // IAccessible methods
 //-----------------------------------------------------
 
 STDMETHODIMP
 AccessibleWrap::get_accParent( IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *ppdispParent = NULL;
+  *ppdispParent = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   DocAccessible* doc = AsDoc();
   if (doc) {
     // Return window system accessible object for root document and tab document
     // accessibles.
@@ -190,17 +190,17 @@ AccessibleWrap::get_accChildCount( long 
 
 STDMETHODIMP
 AccessibleWrap::get_accChild(
       /* [in] */ VARIANT varChild,
       /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *ppdispChild = NULL;
+  *ppdispChild = nullptr;
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   // IAccessible::accChild is used to return this accessible or child accessible
   // at the given index or to get an accessible by child ID in the case of
   // document accessible (it's handled by overriden GetXPAccessibleFor method
   // on the document accessible). The getting an accessible by child ID is used
   // by AccessibleObjectFromEvent() called by AT when AT handles our MSAA event.
@@ -219,17 +219,17 @@ AccessibleWrap::get_accChild(
 
 STDMETHODIMP
 AccessibleWrap::get_accName(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszName)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *pszName = NULL;
+  *pszName = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
 
@@ -256,17 +256,17 @@ AccessibleWrap::get_accName(
 
 STDMETHODIMP
 AccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *pszValue = NULL;
+  *pszValue = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
 
@@ -294,17 +294,17 @@ AccessibleWrap::get_accValue(
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accDescription(VARIANT varChild,
                                    BSTR __RPC_FAR *pszDescription)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *pszDescription = NULL;
+  *pszDescription = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
 
@@ -456,47 +456,47 @@ AccessibleWrap::get_accState(
 
 STDMETHODIMP
 AccessibleWrap::get_accHelp(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszHelp)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *pszHelp = NULL;
+  *pszHelp = nullptr;
   return S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accHelpTopic(
       /* [out] */ BSTR __RPC_FAR *pszHelpFile,
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ long __RPC_FAR *pidTopic)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *pszHelpFile = NULL;
+  *pszHelpFile = nullptr;
   *pidTopic = 0;
   return S_FALSE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accKeyboardShortcut(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!pszKeyboardShortcut)
     return E_INVALIDARG;
-  *pszKeyboardShortcut = NULL;
+  *pszKeyboardShortcut = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* acc = GetXPAccessibleFor(varChild);
   if (!acc)
     return E_INVALIDARG;
 
@@ -595,17 +595,17 @@ AccessibleEnumerator::QueryInterface(REF
     return S_OK;
   }
   if (iid == IID_IUnknown) {
     *ppvObject = static_cast<IUnknown*>(this);
     AddRef();
     return S_OK;
   }
 
-  *ppvObject = NULL;
+  *ppvObject = nullptr;
   return E_NOINTERFACE;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP_(ULONG)
 AccessibleEnumerator::AddRef(void)
 {
@@ -737,17 +737,17 @@ AccessibleWrap::get_accSelection(VARIANT
 
 STDMETHODIMP
 AccessibleWrap::get_accDefaultAction(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszDefaultAction)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *pszDefaultAction = NULL;
+  *pszDefaultAction = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* xpAccessible = GetXPAccessibleFor(varChild);
   if (!xpAccessible)
     return E_INVALIDARG;
 
@@ -1061,17 +1061,17 @@ STDMETHODIMP
 AccessibleWrap::get_relation(long aRelationIndex,
                              IAccessibleRelation** aRelation)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aRelation)
     return E_INVALIDARG;
 
-  *aRelation = NULL;
+  *aRelation = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   long relIdx = 0;
   for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
     uint32_t relType = sRelationTypesForIA2[idx];
     Relation rel = RelationByType(relType);
@@ -1275,28 +1275,28 @@ AccessibleWrap::get_states(AccessibleSta
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_extendedRole(BSTR *aExtendedRole)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aExtendedRole = NULL;
+  *aExtendedRole = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_localizedExtendedRole(BSTR *aLocalizedExtendedRole)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aLocalizedExtendedRole = NULL;
+  *aLocalizedExtendedRole = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_nExtendedStates(long *aNExtendedStates)
 {
@@ -1310,31 +1310,31 @@ AccessibleWrap::get_nExtendedStates(long
 
 STDMETHODIMP
 AccessibleWrap::get_extendedStates(long aMaxExtendedStates,
                                    BSTR **aExtendedStates,
                                    long *aNExtendedStates)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aExtendedStates = NULL;
+  *aExtendedStates = nullptr;
   *aNExtendedStates = 0;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_localizedExtendedStates(long aMaxLocalizedExtendedStates,
                                             BSTR** aLocalizedExtendedStates,
                                             long* aNLocalizedExtendedStates)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aLocalizedExtendedStates = NULL;
+  *aLocalizedExtendedStates = nullptr;
   *aNLocalizedExtendedStates = 0;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 AccessibleWrap::get_uniqueID(long *uniqueID)
@@ -1433,17 +1433,17 @@ AccessibleWrap::get_locale(IA2Locale *aL
 
 STDMETHODIMP
 AccessibleWrap::get_attributes(BSTR *aAttributes)
 {
   A11Y_TRYBLOCK_BEGIN
 
   // The format is name:value;name:value; with \ for escaping these
   // characters ":;=,\".
-  *aAttributes = NULL;
+  *aAttributes = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
   return ConvertToIA2Attributes(attributes, aAttributes);
 
   A11Y_TRYBLOCK_END
@@ -1457,17 +1457,17 @@ AccessibleWrap::GetTypeInfoCount(UINT *p
 {
   *pctinfo = 1;
   return S_OK;
 }
 
 STDMETHODIMP
 AccessibleWrap::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
 {
-  *ppTInfo = NULL;
+  *ppTInfo = nullptr;
 
   if (iTInfo != 0)
     return DISP_E_BADINDEX;
 
   ITypeInfo * typeInfo = GetTI(lcid);
   if (!typeInfo)
     return E_FAIL;
 
@@ -1527,16 +1527,23 @@ AccessibleWrap::HandleAccEvent(AccEvent*
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccessibleWrap
 
 nsresult
 AccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
 {
+  // Don't fire native MSAA events or mess with the system caret
+  // when running in metro mode. This confuses input focus tracking
+  // in metro's UIA implementation.
+  if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
+    return NS_OK;
+  }
+
   uint32_t eventType = aEvent->GetEventType();
 
   MOZ_STATIC_ASSERT(sizeof(gWinEventMap)/sizeof(gWinEventMap[0]) == nsIAccessibleEvent::EVENT_LAST_ENTRY,
                     "MSAA event map skewed");
 
   NS_ENSURE_TRUE(eventType > 0 && eventType < ArrayLength(gWinEventMap), NS_ERROR_FAILURE);
 
   uint32_t winEvent = gWinEventMap[eventType];
@@ -1642,17 +1649,17 @@ AccessibleWrap::GetHWNDFor(Accessible* a
   }
   return nullptr;
 }
 
 HRESULT
 AccessibleWrap::ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
                                        BSTR *aIA2Attributes)
 {
-  *aIA2Attributes = NULL;
+  *aIA2Attributes = nullptr;
 
   // The format is name:value;name:value; with \ for escaping these
   // characters ":;=,\".
 
   if (!aAttributes)
     return S_FALSE;
 
   nsCOMPtr<nsISimpleEnumerator> propEnum;
@@ -1706,17 +1713,17 @@ AccessibleWrap::ConvertToIA2Attributes(n
   return *aIA2Attributes ? S_OK : E_OUTOFMEMORY;
 }
 
 IDispatch*
 AccessibleWrap::NativeAccessible(nsIAccessible* aAccessible)
 {
   if (!aAccessible) {
    NS_WARNING("Not passing in an aAccessible");
-   return NULL;
+   return nullptr;
   }
 
   IAccessible* msaaAccessible = nullptr;
   aAccessible->GetNativeInterface(reinterpret_cast<void**>(&msaaAccessible));
   return static_cast<IDispatch*>(msaaAccessible);
 }
 
 Accessible*
@@ -1784,37 +1791,37 @@ AccessibleWrap::UpdateSystemCaret()
   nsIntRect caretRect = SelectionMgr()->GetCaretRect(&widget);
   HWND caretWnd; 
   if (caretRect.IsEmpty() || !(caretWnd = (HWND)widget->GetNativeData(NS_NATIVE_WINDOW))) {
     return;
   }
 
   // Create invisible bitmap for caret, otherwise its appearance interferes
   // with Gecko caret
-  HBITMAP caretBitMap = CreateBitmap(1, caretRect.height, 1, 1, NULL);
+  HBITMAP caretBitMap = CreateBitmap(1, caretRect.height, 1, 1, nullptr);
   if (::CreateCaret(caretWnd, caretBitMap, 1, caretRect.height)) {  // Also destroys the last caret
     ::ShowCaret(caretWnd);
     RECT windowRect;
     ::GetWindowRect(caretWnd, &windowRect);
     ::SetCaretPos(caretRect.x - windowRect.left, caretRect.y - windowRect.top);
     ::DeleteObject(caretBitMap);
   }
 }
 
 ITypeInfo*
 AccessibleWrap::GetTI(LCID lcid)
 {
   if (gTypeInfo)
     return gTypeInfo;
 
-  ITypeLib *typeLib = NULL;
+  ITypeLib *typeLib = nullptr;
   HRESULT hr = LoadRegTypeLib(LIBID_Accessibility, 1, 0, lcid, &typeLib);
   if (FAILED(hr))
-    return NULL;
+    return nullptr;
 
   hr = typeLib->GetTypeInfoOfGuid(IID_IAccessible, &gTypeInfo);
   typeLib->Release();
 
   if (FAILED(hr))
-    return NULL;
+    return nullptr;
 
   return gTypeInfo;
 }
--- a/accessible/src/windows/msaa/AccessibleWrap.h
+++ b/accessible/src/windows/msaa/AccessibleWrap.h
@@ -41,17 +41,17 @@ virtual HRESULT STDMETHODCALLTYPE QueryI
 
 #define IMPL_IUNKNOWN_QUERY_HEAD(Class)                                        \
 STDMETHODIMP                                                                   \
 Class::QueryInterface(REFIID aIID, void** aInstancePtr)                        \
 {                                                                              \
   A11Y_TRYBLOCK_BEGIN                                                          \
   if (!aInstancePtr)                                                           \
     return E_INVALIDARG;                                                       \
-  *aInstancePtr = NULL;                                                        \
+  *aInstancePtr = nullptr;                                                        \
                                                                                \
   HRESULT hr = E_NOINTERFACE;
 
 #define IMPL_IUNKNOWN_QUERY_TAIL                                               \
   return hr;                                                                   \
   A11Y_TRYBLOCK_END                                                            \
 }
 
--- a/accessible/src/windows/msaa/ApplicationAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/ApplicationAccessibleWrap.cpp
@@ -42,17 +42,17 @@ ApplicationAccessibleWrap::NativeAttribu
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // IUnknown
 
 STDMETHODIMP
 ApplicationAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_IAccessibleApplication == iid) {
     *ppv = static_cast<IAccessibleApplication*>(this);
     (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
     return S_OK;
   }
 
   return AccessibleWrap::QueryInterface(iid, ppv);
@@ -61,17 +61,17 @@ ApplicationAccessibleWrap::QueryInterfac
 ////////////////////////////////////////////////////////////////////////////////
 // IAccessibleApplication
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_appName(BSTR* aName)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aName = NULL;
+  *aName = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString name;
   nsresult rv = GetAppName(name);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
@@ -85,17 +85,17 @@ ApplicationAccessibleWrap::get_appName(B
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_appVersion(BSTR* aVersion)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aVersion = NULL;
+  *aVersion = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString version;
   nsresult rv = GetAppVersion(version);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
@@ -131,17 +131,17 @@ ApplicationAccessibleWrap::get_toolkitNa
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ApplicationAccessibleWrap::get_toolkitVersion(BSTR* aVersion)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aVersion = NULL;
+  *aVersion = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString version;
   nsresult rv = GetPlatformVersion(version);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
--- a/accessible/src/windows/msaa/Compatibility.cpp
+++ b/accessible/src/windows/msaa/Compatibility.cpp
@@ -25,17 +25,17 @@ IsModuleVersionLessThan(HMODULE aModuleH
 
   DWORD dummy = 0;
   DWORD length = ::GetFileVersionInfoSizeW(fileName, &dummy);
 
   LPBYTE versionInfo = new BYTE[length];
   ::GetFileVersionInfoW(fileName, 0, length, versionInfo);
 
   UINT uLen;
-  VS_FIXEDFILEINFO* fixedFileInfo = NULL;
+  VS_FIXEDFILEINFO* fixedFileInfo = nullptr;
   ::VerQueryValueW(versionInfo, L"\\", (LPVOID*)&fixedFileInfo, &uLen);
   DWORD dwFileVersionMS = fixedFileInfo->dwFileVersionMS;
   DWORD dwFileVersionLS = fixedFileInfo->dwFileVersionLS;
   delete [] versionInfo;
 
   DWORD dwLeftMost = HIWORD(dwFileVersionMS);
   DWORD dwSecondRight = HIWORD(dwFileVersionLS);
   return (dwLeftMost < aMajor ||
--- a/accessible/src/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/DocAccessibleWrap.cpp
@@ -33,17 +33,17 @@ using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // DocAccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
 
 DocAccessibleWrap::
   DocAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
                     nsIPresShell* aPresShell) :
-  DocAccessible(aDocument, aRootContent, aPresShell), mHWND(NULL)
+  DocAccessible(aDocument, aRootContent, aPresShell), mHWND(nullptr)
 {
 }
 
 DocAccessibleWrap::~DocAccessibleWrap()
 {
 }
 
 //-----------------------------------------------------
@@ -59,33 +59,33 @@ STDMETHODIMP_(ULONG) DocAccessibleWrap::
 {
   return nsAccessNode::Release();
 }
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 DocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
-  *ppv = NULL;
+  *ppv = nullptr;
 
   if (IID_ISimpleDOMDocument != iid)
     return HyperTextAccessibleWrap::QueryInterface(iid, ppv);
 
   statistics::ISimpleDOMUsed();
   *ppv = static_cast<ISimpleDOMDocument*>(this);
   (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
   return S_OK;
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aURL = NULL;
+  *aURL = nullptr;
 
   nsAutoString URL;
   nsresult rv = GetURL(URL);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   if (URL.IsEmpty())
     return S_FALSE;
@@ -96,17 +96,17 @@ DocAccessibleWrap::get_URL(/* [out] */ B
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_title( /* [out] */ BSTR __RPC_FAR *aTitle)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aTitle = NULL;
+  *aTitle = nullptr;
 
   nsAutoString title;
   nsresult rv = GetTitle(title);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   *aTitle = ::SysAllocStringLen(title.get(), title.Length());
   return *aTitle ? S_OK : E_OUTOFMEMORY;
@@ -114,17 +114,17 @@ DocAccessibleWrap::get_title( /* [out] *
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_mimeType(/* [out] */ BSTR __RPC_FAR *aMimeType)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aMimeType = NULL;
+  *aMimeType = nullptr;
 
   nsAutoString mimeType;
   nsresult rv = GetMimeType(mimeType);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   if (mimeType.IsEmpty())
     return S_FALSE;
@@ -135,17 +135,17 @@ DocAccessibleWrap::get_mimeType(/* [out]
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_docType(/* [out] */ BSTR __RPC_FAR *aDocType)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aDocType = NULL;
+  *aDocType = nullptr;
 
   nsAutoString docType;
   nsresult rv = GetDocType(docType);
   if (NS_FAILED(rv))
     return E_FAIL;
 
   if (docType.IsEmpty())
     return S_FALSE;
@@ -157,17 +157,17 @@ DocAccessibleWrap::get_docType(/* [out] 
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_nameSpaceURIForID(/* [in] */  short aNameSpaceID,
   /* [out] */ BSTR __RPC_FAR *aNameSpaceURI)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aNameSpaceURI = NULL;
+  *aNameSpaceURI = nullptr;
 
   if (aNameSpaceID < 0)
     return E_INVALIDARG;  // -1 is kNameSpaceID_Unknown
 
   nsAutoString nameSpaceURI;
   nsresult rv = GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI);
   if (NS_FAILED(rv))
     return E_FAIL;
@@ -183,29 +183,29 @@ DocAccessibleWrap::get_nameSpaceURIForID
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::put_alternateViewMediaTypes( /* [in] */ BSTR __RPC_FAR *aCommaSeparatedMediaTypes)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aCommaSeparatedMediaTypes = NULL;
+  *aCommaSeparatedMediaTypes = nullptr;
   return E_NOTIMPL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 DocAccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
   // For backwards-compat, we still support old MSAA hack to provide URL in accValue
-  *pszValue = NULL;
+  *pszValue = nullptr;
   // Check for real value first
   HRESULT hr = AccessibleWrap::get_accValue(varChild, pszValue);
   if (FAILED(hr) || *pszValue || varChild.lVal != CHILDID_SELF)
     return hr;
   // If document is being used to create a widget, don't use the URL hack
   roles::Role role = Role();
   if (role != roles::DOCUMENT && role != roles::APPLICATION && 
       role != roles::DIALOG && role != roles::ALERT) 
--- a/accessible/src/windows/msaa/HyperTextAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/HyperTextAccessibleWrap.cpp
@@ -25,17 +25,17 @@ NS_IMPL_ISUPPORTS_INHERITED0(HyperTextAc
                              HyperTextAccessible)
 
 STDMETHODIMP
 HyperTextAccessibleWrap::QueryInterface(REFIID aIID, void** aInstancePtr)
 {
   if (!aInstancePtr)
     return E_FAIL;
 
-  *aInstancePtr = NULL;
+  *aInstancePtr = nullptr;
 
   if (IsTextRole()) {
     if (aIID == IID_IAccessibleText)
       *aInstancePtr =
         static_cast<IAccessibleText*>(static_cast<ia2AccessibleText*>(this));
     else if (aIID == IID_IAccessibleHypertext)
       *aInstancePtr = static_cast<IAccessibleHypertext*>(this);
     else if (aIID == IID_IAccessibleEditableText)
--- a/accessible/src/windows/msaa/RootAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/RootAccessibleWrap.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "RootAccessibleWrap.h"
 
 #include "Compatibility.h"
 #include "nsCoreUtils.h"
 #include "nsWinUtils.h"
 
-#include "nsIDOMEventTarget.h"
 #include "nsEventListenerManager.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 RootAccessibleWrap::
--- a/accessible/src/windows/msaa/ServiceProvider.cpp
+++ b/accessible/src/windows/msaa/ServiceProvider.cpp
@@ -32,17 +32,17 @@ A11Y_TRYBLOCK_END
 
 STDMETHODIMP
 ServiceProvider::QueryService(REFGUID aGuidService, REFIID aIID,
                               void** aInstancePtr)
 {
   if (!aInstancePtr)
     return E_INVALIDARG;
 
-  *aInstancePtr = NULL;
+  *aInstancePtr = nullptr;
 
   // UIA IAccessibleEx
   if (aGuidService == IID_IAccessibleEx &&
       Preferences::GetBool("accessibility.uia.enable")) {
     uiaRawElmProvider* accEx = new uiaRawElmProvider(mAccessible);
     HRESULT hr = accEx->QueryInterface(aIID, aInstancePtr);
     if (FAILED(hr))
       delete accEx;
--- a/accessible/src/windows/msaa/TextLeafAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/TextLeafAccessibleWrap.cpp
@@ -59,17 +59,17 @@ TextLeafAccessibleWrap::QueryInterface(R
 }
 
 STDMETHODIMP
 TextLeafAccessibleWrap::get_domText( 
     /* [retval][out] */ BSTR __RPC_FAR *aDomText)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aDomText = NULL;
+  *aDomText = nullptr;
 
   if (IsDefunct())
     return E_FAIL;
 
   nsAutoString nodeValue;
 
   nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mContent));
   DOMNode->GetNodeValue(nodeValue);
@@ -241,17 +241,17 @@ TextLeafAccessibleWrap::GetCharacterExte
 }
 
 STDMETHODIMP
 TextLeafAccessibleWrap::get_fontFamily(
     /* [retval][out] */ BSTR __RPC_FAR *aFontFamily)
 {
   A11Y_TRYBLOCK_BEGIN
 
-  *aFontFamily = NULL;
+  *aFontFamily = nullptr;
 
   nsIFrame* frame = GetFrame();
   if (!frame) {
     return E_FAIL;
   }
 
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(frame, getter_AddRefs(fm));
--- a/accessible/src/windows/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/windows/msaa/nsAccessNodeWrap.cpp
@@ -85,17 +85,17 @@ nsAccessNodeWrap::WindowProc(HWND hWnd, 
   // message semantics.
 
   switch (msg) {
     case WM_GETOBJECT:
     {
       if (lParam == OBJID_CLIENT) {
         DocAccessible* document = sHWNDCache.GetWeak(static_cast<void*>(hWnd));
         if (document) {
-          IAccessible* msaaAccessible = NULL;
+          IAccessible* msaaAccessible = nullptr;
           document->GetNativeInterface((void**)&msaaAccessible); // does an addref
           if (msaaAccessible) {
             LRESULT result = ::LresultFromObject(IID_IAccessible, wParam,
                                                  msaaAccessible); // does an addref
             msaaAccessible->Release(); // release extra addref
             return result;
           }
         }
--- a/accessible/src/windows/msaa/nsWinUtils.cpp
+++ b/accessible/src/windows/msaa/nsWinUtils.cpp
@@ -60,67 +60,67 @@ nsWinUtils::MaybeStartWindowEmulation()
 }
 
 void
 nsWinUtils::ShutdownWindowEmulation()
 {
   // Unregister window call that's used for document accessibles associated
   // with tabs.
   if (IsWindowEmulationStarted())
-    ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(NULL));
+    ::UnregisterClassW(kClassNameTabContent, GetModuleHandle(nullptr));
 }
 
 bool
 nsWinUtils::IsWindowEmulationStarted()
 {
   return nsAccessNodeWrap::sHWNDCache.IsInitialized();
 }
 
 void
 nsWinUtils::RegisterNativeWindow(LPCWSTR aWindowClass)
 {
   WNDCLASSW wc;
   wc.style = CS_GLOBALCLASS;
   wc.lpfnWndProc = nsAccessNodeWrap::WindowProc;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = 0;
-  wc.hInstance = GetModuleHandle(NULL);
-  wc.hIcon = NULL;
-  wc.hCursor = NULL;
-  wc.hbrBackground = NULL;
-  wc.lpszMenuName = NULL;
+  wc.hInstance = GetModuleHandle(nullptr);
+  wc.hIcon = nullptr;
+  wc.hCursor = nullptr;
+  wc.hbrBackground = nullptr;
+  wc.lpszMenuName = nullptr;
   wc.lpszClassName = aWindowClass;
   ::RegisterClassW(&wc);
 }
 
 HWND
 nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
                                int aX, int aY, int aWidth, int aHeight,
                                bool aIsActive)
 {
   HWND hwnd = ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
                                 L"NetscapeDispatchWnd",
                                 WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
                                 aX, aY, aWidth, aHeight,
                                 aParentWnd,
-                                NULL,
-                                GetModuleHandle(NULL),
-                                NULL);
+                                nullptr,
+                                GetModuleHandle(nullptr),
+                                nullptr);
   if (hwnd) {
     // Mark this window so that ipc related code can identify it.
     ::SetPropW(hwnd, kPropNameTabContent, (HANDLE)1);
   }
   return hwnd;
 }
 
 void
 nsWinUtils::ShowNativeWindow(HWND aWnd)
 {
   ::ShowWindow(aWnd, SW_SHOW);
 }
 
 void
 nsWinUtils::HideNativeWindow(HWND aWnd)
 {
-  ::SetWindowPos(aWnd, NULL, 0, 0, 0, 0,
+  ::SetWindowPos(aWnd, nullptr, 0, 0, 0, 0,
                  SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
                  SWP_NOZORDER | SWP_NOACTIVATE);
 }
--- a/accessible/src/windows/sdn/sdnAccessible.cpp
+++ b/accessible/src/windows/sdn/sdnAccessible.cpp
@@ -26,17 +26,17 @@ using namespace mozilla::a11y;
 
 STDMETHODIMP
 sdnAccessible::QueryInterface(REFIID aREFIID, void** aInstancePtr)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aInstancePtr)
     return E_FAIL;
-  *aInstancePtr = NULL;
+  *aInstancePtr = nullptr;
 
   if (aREFIID == IID_ISimpleDOMNode) {
     *aInstancePtr = this;
     AddRef();
     return S_OK;
   }
 
   AccessibleWrap* accessible = static_cast<AccessibleWrap*>(GetAccessible());
@@ -65,19 +65,19 @@ sdnAccessible::get_nodeInfo(BSTR __RPC_F
                             unsigned short __RPC_FAR* aNodeType)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNodeName || !aNameSpaceID || !aNodeValue || !aNumChildren ||
       !aUniqueID || !aNodeType)
     return E_INVALIDARG;
 
-  *aNodeName = NULL;
+  *aNodeName = nullptr;
   *aNameSpaceID = 0;
-  *aNodeValue = NULL;
+  *aNodeValue = nullptr;
   *aNumChildren = 0;
   *aUniqueID = 0;
   *aNodeType = 0;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mNode));
@@ -138,17 +138,17 @@ sdnAccessible::get_attributes(unsigned  
   uint32_t numAttribs = elm->GetAttrCount();
   if (numAttribs > aMaxAttribs)
     numAttribs = aMaxAttribs;
 
   *aNumAttribs = static_cast<unsigned short>(numAttribs);
 
   for (uint32_t index = 0; index < numAttribs; index++) {
     aNameSpaceIDs[index] = 0;
-    aAttribValues[index] = aAttribNames[index] = NULL;
+    aAttribValues[index] = aAttribNames[index] = nullptr;
     nsAutoString attributeValue;
 
     const nsAttrName* name = elm->GetAttrNameAt(index);
     aNameSpaceIDs[index] = static_cast<short>(name->NamespaceID());
     aAttribNames[index] = ::SysAllocString(name->LocalName()->GetUTF16String());
     elm->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue);
     aAttribValues[index] = ::SysAllocString(attributeValue.get());
   }
@@ -176,17 +176,17 @@ sdnAccessible::get_attributesForNames(un
     return S_FALSE;
 
   nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(mNode));
   nsCOMPtr<nsINameSpaceManager> nameSpaceManager =
     do_GetService(NS_NAMESPACEMANAGER_CONTRACTID);
 
   int32_t index = 0;
   for (index = 0; index < aMaxAttribs; index++) {
-    aAttribValues[index] = NULL;
+    aAttribValues[index] = nullptr;
     if (aAttribNames[index]) {
       nsAutoString attributeValue, nameSpaceURI;
       nsAutoString attributeName(nsDependentString(
         static_cast<PRUnichar*>(aAttribNames[index])));
 
       nsresult rv = NS_OK;
       if (aNameSpaceID[index]>0 &&
         NS_SUCCEEDED(nameSpaceManager->GetNameSpaceURI(aNameSpaceID[index],
@@ -316,17 +316,17 @@ sdnAccessible::scrollTo(boolean aScrollT
 
 STDMETHODIMP
 sdnAccessible::get_parentNode(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNode)
     return E_INVALIDARG;
-  *aNode = NULL;
+  *aNode = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsINode* resultNode = mNode->GetParentNode();
   if (resultNode) {
     *aNode = new sdnAccessible(resultNode);
     (*aNode)->AddRef();
@@ -339,17 +339,17 @@ sdnAccessible::get_parentNode(ISimpleDOM
 
 STDMETHODIMP
 sdnAccessible::get_firstChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNode)
     return E_INVALIDARG;
-  *aNode = NULL;
+  *aNode = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsINode* resultNode = mNode->GetFirstChild();
   if (resultNode) {
     *aNode = new sdnAccessible(resultNode);
     (*aNode)->AddRef();
@@ -362,17 +362,17 @@ sdnAccessible::get_firstChild(ISimpleDOM
 
 STDMETHODIMP
 sdnAccessible::get_lastChild(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNode)
     return E_INVALIDARG;
-  *aNode = NULL;
+  *aNode = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsINode* resultNode = mNode->GetLastChild();
   if (resultNode) {
     *aNode = new sdnAccessible(resultNode);
     (*aNode)->AddRef();
@@ -385,17 +385,17 @@ sdnAccessible::get_lastChild(ISimpleDOMN
 
 STDMETHODIMP
 sdnAccessible::get_previousSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNode)
     return E_INVALIDARG;
-  *aNode = NULL;
+  *aNode = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsINode* resultNode = mNode->GetPreviousSibling();
   if (resultNode) {
     *aNode = new sdnAccessible(resultNode);
     (*aNode)->AddRef();
@@ -408,17 +408,17 @@ sdnAccessible::get_previousSibling(ISimp
 
 STDMETHODIMP
 sdnAccessible::get_nextSibling(ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNode)
     return E_INVALIDARG;
-  *aNode = NULL;
+  *aNode = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsINode* resultNode = mNode->GetNextSibling();
   if (resultNode) {
     *aNode = new sdnAccessible(resultNode);
     (*aNode)->AddRef();
@@ -432,17 +432,17 @@ sdnAccessible::get_nextSibling(ISimpleDO
 STDMETHODIMP
 sdnAccessible::get_childAt(unsigned aChildIndex,
                            ISimpleDOMNode __RPC_FAR *__RPC_FAR* aNode)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aNode)
     return E_INVALIDARG;
-  *aNode = NULL;
+  *aNode = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsINode* resultNode = mNode->GetChildAt(aChildIndex);
   if (resultNode) {
     *aNode = new sdnAccessible(resultNode);
     (*aNode)->AddRef();
@@ -456,17 +456,17 @@ sdnAccessible::get_childAt(unsigned aChi
 
 STDMETHODIMP
 sdnAccessible::get_innerHTML(BSTR __RPC_FAR* aInnerHTML)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aInnerHTML)
     return E_INVALIDARG;
-  *aInnerHTML = NULL;
+  *aInnerHTML = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mNode);
   if (!htmlElement)
     return S_FALSE;
 
@@ -486,17 +486,17 @@ sdnAccessible::get_innerHTML(BSTR __RPC_
 
 STDMETHODIMP
 sdnAccessible::get_localInterface(void __RPC_FAR *__RPC_FAR* aLocalInterface)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aLocalInterface)
     return E_INVALIDARG;
-  *aLocalInterface = NULL;
+  *aLocalInterface = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aLocalInterface = this;
   AddRef();
 
   return S_OK;
@@ -506,17 +506,17 @@ sdnAccessible::get_localInterface(void _
 
 STDMETHODIMP
 sdnAccessible::get_language(BSTR __RPC_FAR* aLanguage)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aLanguage)
     return E_INVALIDARG;
-  *aLanguage = NULL;
+  *aLanguage = nullptr;
 
   if (IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   nsAutoString language;
   if (mNode->IsElement())
     nsCoreUtils::GetLanguageFor(mNode->AsElement(), nullptr, language);
   if (language.IsEmpty()) { // Nothing found, so use document's language
--- a/accessible/src/windows/uia/uiaRawElmProvider.cpp
+++ b/accessible/src/windows/uia/uiaRawElmProvider.cpp
@@ -28,33 +28,33 @@ STDMETHODIMP
 uiaRawElmProvider::GetObjectForChild(long aIdChild,
                                      __RPC__deref_out_opt IAccessibleEx** aAccEx)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aAccEx)
     return E_INVALIDARG;
 
-  *aAccEx = NULL;
+  *aAccEx = nullptr;
 
   return mAcc->IsDefunct() ? CO_E_OBJNOTCONNECTED : S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::GetIAccessiblePair(__RPC__deref_out_opt IAccessible** aAcc,
                                       __RPC__out long* aIdChild)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aAcc || !aIdChild)
     return E_INVALIDARG;
 
-  *aAcc = NULL;
+  *aAcc = nullptr;
   *aIdChild = 0;
 
   if (mAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   *aIdChild = CHILDID_SELF;
   *aAcc = mAcc;
   mAcc->AddRef();
@@ -89,19 +89,19 @@ STDMETHODIMP
 uiaRawElmProvider::ConvertReturnedElement(__RPC__in_opt IRawElementProviderSimple* aRawElmProvider,
                                           __RPC__deref_out_opt IAccessibleEx** aAccEx)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aRawElmProvider || !aAccEx)
     return E_INVALIDARG;
 
-  *aAccEx = NULL;
+  *aAccEx = nullptr;
 
-  void* instancePtr = NULL;
+  void* instancePtr = nullptr;
   HRESULT hr = aRawElmProvider->QueryInterface(IID_IAccessibleEx, &instancePtr);
   if (SUCCEEDED(hr))
     *aAccEx = static_cast<IAccessibleEx*>(instancePtr);
 
   return hr;
 
   A11Y_TRYBLOCK_END
 }
@@ -128,17 +128,17 @@ STDMETHODIMP
 uiaRawElmProvider::GetPatternProvider(PATTERNID aPatternId,
                                       __RPC__deref_out_opt IUnknown** aPatternProvider)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aPatternProvider)
     return E_INVALIDARG;
 
-  *aPatternProvider = NULL;
+  *aPatternProvider = nullptr;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
                                     __RPC__out VARIANT* aPropertyValue)
@@ -234,13 +234,13 @@ STDMETHODIMP
 uiaRawElmProvider::get_HostRawElementProvider(__RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aRawElmProvider)
     return E_INVALIDARG;
 
   // This method is not used with IAccessibleEx implementations.
-  *aRawElmProvider = NULL;
+  *aRawElmProvider = nullptr;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/Makefile.in
@@ -0,0 +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/.
+
+DEPTH = @DEPTH@
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+relativesrcdir = accessible/jsat
+
+include $(DEPTH)/config/autoconf.mk
+
+MOCHITEST_A11Y_FILES =\
+test_utterance_order.html \
+$(NULL)
+
+include $(topsrcdir)/config/rules.mk
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/moz.build
@@ -0,0 +1,4 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/test_utterance_order.html
@@ -0,0 +1,184 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=753984
+-->
+  <head>
+    <title>[AccessFu] utterance order test</title>
+    <meta charset="utf-8">
+    <link rel="stylesheet" type="text/css"
+          href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+    <script type="application/javascript"
+            src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="application/javascript"
+            src="../common.js"></script>
+    <script type="application/javascript">
+
+      const Cu = Components.utils;
+      const PREF_UTTERANCE_ORDER = "accessibility.accessfu.utterance";
+
+      Cu.import('resource://gre/modules/accessibility/Utils.jsm');
+      Cu.import("resource://gre/modules/accessibility/UtteranceGenerator.jsm",
+        this);
+
+      // Test UtteranceGenerator.genForContext utterance order for
+      // a particular accessible context with an optional old accessible.
+      function testContextUtterance(expected, aAccOrElmOrID, oldAAccOrElmOrID) {
+        oldAAccOrElmOrID = oldAAccOrElmOrID || "root";
+        var accessible = getAccessible(aAccOrElmOrID);
+        var oldAccessible = getAccessible(oldAAccOrElmOrID);
+        var context = new PivotContext(accessible, oldAccessible);
+        var utterance = UtteranceGenerator.genForContext(context);
+        isDeeply(utterance, expected,
+          "Utterance order is correct for " + aAccOrElmOrID);
+      }
+
+      // Test UtteranceGenerator.genForObject for a particular aAccOrElmOrID.
+      function testUtterance(utteranceOrder, aAccOrElmOrID) {
+        var accessible = getAccessible(aAccOrElmOrID);
+        var utterance = UtteranceGenerator.genForObject(accessible);
+        var expectedNameIndex = utteranceOrder === 0 ? utterance.length - 1 : 0;
+
+        if (aAccOrElmOrID === "li_one" || aAccOrElmOrID === "cell") {
+          // List item's and table cell's name is not included into an object
+          // utterance.
+          expectedNameIndex = -1;
+        }
+        ok(utterance.indexOf(accessible.name) === expectedNameIndex,
+          "Object utterance is correct for " + aAccOrElmOrID);
+      }
+
+      function doTest() {
+        // Test the following aAccOrElmOrID (with optional old aAccOrElmOrID).
+        // Note: each aAccOrElmOrID entry maps to a unique object utterance
+        // generator function within the UtteranceGenerator.
+        var tests = [{
+          aAccOrElmOrID: "anchor",
+          expected: [["link", "title"], ["title", "link"]]
+        }, {
+          aAccOrElmOrID: "textarea",
+          expected: [[
+            "text area", "Test Text Area", "This is the text area text.", "\n"
+          ], [
+            "This is the text area text.", "\n", "Test Text Area", "text area"
+          ]]
+        }, {
+          aAccOrElmOrID: "heading",
+          expected: [
+            ["heading level 1", "Test heading"],
+            ["Test heading", "heading level 1"]
+          ]
+        }, {
+          aAccOrElmOrID: "list",
+          expected: [
+            ["list 1 items", "Test List", "First item", "1. ", "list one"],
+            ["1. ", "list one", "First item", "Test List", "list 1 items"]
+          ]
+        }, {
+          aAccOrElmOrID: "dlist",
+          expected: [
+            ["definition list 0.5 items", "Test Definition List", "dd one "],
+            ["dd one ", "Test Definition List", "definition list 0.5 items"]
+          ]
+        }, {
+          aAccOrElmOrID: "li_one",
+          expected: [
+            ["list 1 items", "Test List", "First item", "1. ", "list one"],
+            ["1. ", "list one", "First item", "Test List", "list 1 items"]
+          ]
+        }, {
+          aAccOrElmOrID: "cell",
+          expected: [[
+            "table", "Fruits and vegetables", "list 4 items", "First item", " ",
+            "link", "Apples", " ", "link", "Bananas", " ", "link", "Peaches",
+            "Last item", " ", "link", "Plums"
+          ], [
+            " ", "Apples", "link", "First item", " ", "Bananas", "link", " ",
+            "Peaches", "link", " ", "Plums", "link", "Last item",
+            "list 4 items", "Fruits and vegetables", "table"
+          ]]
+        }, {
+          // Test pivot to list from li_one.
+          aAccOrElmOrID: "list",
+          oldAAccOrElmOrID: "li_one",
+          expected: [
+            ["list 1 items", "Test List", "First item", "1. ", "list one"],
+            ["1. ", "list one", "First item", "Test List", "list 1 items"]
+          ]
+        }, {
+          // Test pivot to "apples" link from the table cell.
+          aAccOrElmOrID: "apples",
+          oldAAccOrElmOrID: "cell",
+          expected: [
+            ["list 4 items", "First item", "link", "Apples"],
+            ["Apples", "link", "First item", "list 4 items"]
+          ]
+        }, {
+          // Test pivot to 'bananas' link from 'apples' link.
+          aAccOrElmOrID: "bananas",
+          oldAAccOrElmOrID: "apples",
+          expected: [["link", "Bananas"], ["Bananas", "link"]]
+        }];
+
+        // Test all possible utterance order preference values.
+        tests.forEach(function run(test) {
+          var utteranceOrderValues = [0, 1];
+          utteranceOrderValues.forEach(
+            function testUtteranceOrder(utteranceOrder) {
+              SpecialPowers.setIntPref(PREF_UTTERANCE_ORDER, utteranceOrder);
+              testContextUtterance(test.expected[utteranceOrder],
+                test.aAccOrElmOrID, test.oldAAccOrElmOrID);
+              // Just need to test object utterance for individual
+              // aAccOrElmOrID.
+              if (test.oldAAccOrElmOrID) {
+                return;
+              }
+              testUtterance(utteranceOrder, test.aAccOrElmOrID);
+            }
+          );
+        });
+
+        // If there was an original utterance order preference, revert to it.
+        SpecialPowers.clearUserPref(PREF_UTTERANCE_ORDER);
+        SimpleTest.finish();
+      }
+
+      SimpleTest.waitForExplicitFinish();
+      addA11yLoadEvent(doTest);
+
+    </script>
+  </head>
+  <body>
+    <div id="root">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=753984"
+         title="[AccessFu] utterance order test">
+         Mozilla Bug 753984</a>
+      <p id="display"></p>
+      <div id="content" style="display: none"></div>
+      <pre id="test"></pre>
+      <a id="anchor" href="#test" title="title"></a>
+      <textarea id="textarea" title="Test Text Area" cols="80" rows="5">This is the text area text.</textarea>
+      <h1 id="heading" title="Test heading"></h1>
+      <ol id="list" title="Test List">
+        <li id="li_one">list one</li>
+      </ol>
+      <dl id="dlist" title="Test Definition List">
+        <dd id="dd_one">dd one</li>
+      </dl>
+      <table>
+        <caption>Fruits and vegetables</caption>
+        <tr>
+          <td id="cell">
+            <ul style="list-style-type: none;">
+              <li><a id="apples" href="#">Apples</a></li>
+              <li><a id="bananas" href="#">Bananas</a></li>
+              <li><a href="#">Peaches</a></li>
+              <li><a href="#">Plums</a></li>
+            </ul>
+          </td>
+        </tr>
+      </table>
+    </div>
+  </body>
+</html>
\ No newline at end of file
--- a/accessible/tests/mochitest/moz.build
+++ b/accessible/tests/mochitest/moz.build
@@ -10,16 +10,17 @@ DIRS += [
     'bounds',
     'editabletext',
     'elm',
     'events',
     'focus',
     'hittest',
     'hyperlink',
     'hypertext',
+    'jsat',
     'name',
     'pivot',
     'relations',
     'role',
     'scroll',
     'selectable',
     'states',
     'table',
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -108,22 +108,39 @@
       testStates("aria_pressed_button", STATE_PRESSED | STATE_CHECKABLE);
 
       // aria-readonly
       testStates("aria_readonly_textbox", STATE_READONLY);
 
       // readonly/editable on grid and gridcell
       testStates("aria_grid_default", 0, EXT_STATE_EDITABLE,
                  STATE_READONLY, 0);
+      testStates("aria_grid_default_colheader_readonly", STATE_READONLY, 0,
+                 0, EXT_STATE_EDITABLE);
+      testStates("aria_grid_default_colheader_inherited", 0, EXT_STATE_EDITABLE,
+                 STATE_READONLY, 0);
+      testStates("aria_grid_default_rowheader_readonly", STATE_READONLY, 0,
+                 0, EXT_STATE_EDITABLE);
+      testStates("aria_grid_default_rowheader_inherited", 0, EXT_STATE_EDITABLE,
+                 STATE_READONLY, 0);
       testStates("aria_grid_default_cell_readonly", STATE_READONLY, 0,
                  0, EXT_STATE_EDITABLE);
       testStates("aria_grid_default_cell_inherited", 0, EXT_STATE_EDITABLE,
                  STATE_READONLY, 0);
+
       testStates("aria_grid_readonly", STATE_READONLY, 0,
                  0, EXT_STATE_EDITABLE);
+      testStates("aria_grid_readonly_colheader_editable", 0, EXT_STATE_EDITABLE,
+                 STATE_READONLY, 0);
+      testStates("aria_grid_readonly_colheader_inherited", STATE_READONLY, 0,
+                 0, EXT_STATE_EDITABLE);
+      testStates("aria_grid_readonly_rowheader_editable", 0, EXT_STATE_EDITABLE,
+                 STATE_READONLY, 0);
+      testStates("aria_grid_readonly_rowheader_inherited", STATE_READONLY, 0,
+                 0, EXT_STATE_EDITABLE);
       testStates("aria_grid_readonly_cell_editable", 0, EXT_STATE_EDITABLE,
                  STATE_READONLY, 0);
       testStates("aria_grid_readonly_cell_inherited", STATE_READONLY, 0,
                  0, EXT_STATE_EDITABLE);
 
       // aria-selectable
       testStates("aria_selectable_listitem", STATE_SELECTABLE | STATE_SELECTED);
 
@@ -283,28 +300,54 @@
   <div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
   <div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>
 
   <div id="aria_readonly_textbox"
        role="textbox" aria-readonly="true">This text should be readonly</div>
 
   <div id="aria_grid_default" role="grid">
     <div role="row">
+      <div id="aria_grid_default_colheader_readonly"
+           role="columnheader" aria-readonly="true">colheader1</div>
+      <div id="aria_grid_default_colheader_inherited"
+           role="columnheader">colheader2</div>
+    </div>
+    <div role="row">
+      <div id="aria_grid_default_rowheader_readonly"
+           role="rowheader" aria-readonly="true">rowheader1</div>
+      <div id="aria_grid_default_rowheader_inherited"
+           role="rowheader">rowheader2</div>
+    </div>
+    <div role="row">
       <div id="aria_grid_default_cell_readonly"
            role="gridcell" aria-readonly="true">gridcell1</div>
       <div id="aria_grid_default_cell_inherited"
            role="gridcell">gridcell2</div>
+    </div>
   </div>
 
   <div id="aria_grid_readonly" role="grid" aria-readonly="true">
     <div role="row">
+      <div id="aria_grid_readonly_colheader_editable"
+           role="columnheader" aria-readonly="false">colheader1</div>
+      <div id="aria_grid_readonly_colheader_inherited"
+           role="columnheader">colheader2</div>
+    </div>
+    <div role="row">
+      <div id="aria_grid_readonly_rowheader_editable"
+           role="rowheader" aria-readonly="false">rowheader1</div>
+      <div id="aria_grid_readonly_rowheader_inherited"
+           role="rowheader">rowheader2</div>
+    </div>
+    <div role="row">
       <div id="aria_grid_readonly_cell_editable"
            role="gridcell" aria-readonly="false">gridcell1</div>
       <div id="aria_grid_readonly_cell_inherited"
            role="gridcell">gridcell2</div>
+    </div>
   </div>
 
   <div role="listbox">
     <div id="aria_selectable_listitem" role="option" aria-selected="true">Item1</div>
   </div>
 
   <!-- Test that aria-disabled state gets propagated to all descendants -->
   <div id="group" role="group" aria-disabled="true">
--- a/addon-sdk/source/doc/dev-guide-source/credits.md
+++ b/addon-sdk/source/doc/dev-guide-source/credits.md
@@ -152,16 +152,17 @@ We'd like to thank our many Jetpack proj
 * Till Schneidereit
 * Justin Scott
 * Ayan Shah
 * [skratchdot](https://github.com/skratchdot)
 * Henrik Skupin
 * slash
 * Markus Stange
 * Dan Stevens
+* [J. Ryan Stinnett](https://github.com/jryans)
 * [Mihai Sucan](https://github.com/mihaisucan)
 
 <!--end-->
 
 ### T ###
 
 * taku0
 * Clint Talbert
--- a/addon-sdk/source/doc/module-source/sdk/page-mod.md
+++ b/addon-sdk/source/doc/module-source/sdk/page-mod.md
@@ -1,9 +1,8 @@
-
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!-- contributed by Nickolay Ponomarev [asqueella@gmail.com] -->
 <!-- contributed by Myk Melez [myk@mozilla.org] -->
 <!-- contributed by Irakli Gozalishvil [gozala@mozilla.com] -->
 
@@ -53,18 +52,18 @@ In this case files are specified by a UR
 
 <!-- -->
 
     var data = require("sdk/self").data;
     var pageMod = require("sdk/page-mod");
 
     pageMod.PageMod({
       include: "*.mozilla.org",
-      contentScriptFile: [self.data.url("jquery-1.7.min.js"),
-                          self.data.url("my-script.js")]
+      contentScriptFile: [data.url("jquery-1.7.min.js"),
+                          data.url("my-script.js")]
     });
 
 <div class="warning">
 <p>Unless your content script is extremely simple and consists only of a
 static string, don't use <code>contentScript</code>: if you do, you may
 have problems getting your add-on approved on AMO.</p>
 <p>Instead, keep the script in a separate file and load it using
 <code>contentScriptFile</code>. This makes your code easier to maintain,
--- a/addon-sdk/source/doc/module-source/sdk/tabs.md
+++ b/addon-sdk/source/doc/module-source/sdk/tabs.md
@@ -164,16 +164,22 @@ If present and true, then the new tab wi
 A callback function that will be registered for 'open' event.
 This is an optional property.
 @prop [onClose] {function}
 A callback function that will be registered for 'close' event.
 This is an optional property.
 @prop [onReady] {function}
 A callback function that will be registered for 'ready' event.
 This is an optional property.
+@prop [onLoad] {function}
+A callback function that will be registered for 'load' event.
+This is an optional property.
+@prop [onPageShow] {function}
+A callback function that will be registered for 'pageshow' event.
+This is an optional property.
 @prop [onActivate] {function}
 A callback function that will be registered for 'activate' event.
 This is an optional property.
 @prop [onDeactivate] {function}
 A callback function that will be registered for 'deactivate' event.
 This is an optional property.
 </api>
 
@@ -327,16 +333,57 @@ emitted again if the tab's location chan
 
 After this event has been emitted, all properties relating to the tab's
 content can be used.
 
 @argument {Tab}
 Listeners are passed the tab object.
 </api>
 
+<api name="load">
+@event
+
+This event is emitted when the page for the tab's content is loaded. It is
+equivalent to the `load` event for the given content page.
+
+A single tab will emit this event every time the page is loaded: so it will be
+emitted again if the tab's location changes or the content is reloaded.
+
+After this event has been emitted, all properties relating to the tab's
+content can be used.
+
+This is fired after the `ready` event on DOM content pages and can be used
+for pages that do not have a `DOMContentLoaded` event, like images.
+
+@argument {Tab}
+Listeners are passed the tab object.
+</api>
+
+<api name="pageshow">
+@event
+
+This event is emitted when the page for the tab's content is potentially
+from the cache. It is equivilent to the [pageshow](https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/pageshow) event for the given
+content page.
+
+After this event has been emitted, all properties relating to the tab's
+content can be used.
+
+While the `ready` and `load` events will not be fired when a user uses the back
+or forward buttons to navigate history, the `pageshow` event will be fired.
+If the `persisted` argument is true, then the contents were loaded from the
+bfcache.
+
+@argument {Tab}
+Listeners are passed the tab object.
+@argument {persisted}
+Listeners are passed a boolean value indicating whether or not the page
+was loaded from the [bfcache](https://developer.mozilla.org/en-US/docs/Working_with_BFCache) or not.
+</api>
+
 <api name="activate">
 @event
 
 This event is emitted when the tab is made active.
 
 @argument {Tab}
 Listeners are passed the tab object.
 </api>
old mode 100755
new mode 100644
--- a/addon-sdk/source/lib/sdk/addon/runner.js
+++ b/addon-sdk/source/lib/sdk/addon/runner.js
@@ -11,16 +11,18 @@ module.metadata = {
 const { Cc, Ci } = require('chrome');
 const { descriptor, Sandbox, evaluate, main, resolveURI } = require('toolkit/loader');
 const { once } = require('../system/events');
 const { exit, env, staticArgs, name } = require('../system');
 const { when: unload } = require('../system/unload');
 const { loadReason } = require('../self');
 const { rootURI } = require("@loader/options");
 const globals = require('../system/globals');
+const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
+                        getService(Ci.nsIAppShellService);
 
 const NAME2TOPIC = {
   'Firefox': 'sessionstore-windows-restored',
   'Fennec': 'sessionstore-windows-restored',
   'SeaMonkey': 'sessionstore-windows-restored',
   'Thunderbird': 'mail-startup-done',
   '*': 'final-ui-startup'
 };
@@ -65,18 +67,28 @@ function definePseudo(loader, id, export
 
 function wait(reason, options) {
   once(APP_STARTUP, function() {
     startup(null, options);
   });
 }
 
 function startup(reason, options) {
-  if (reason === 'startup')
+  // Try accessing hidden window to guess if we are running during firefox
+  // startup, so that we should wait for session restore event before
+  // running the addon
+  let initialized = false;
+  try {
+    appShellService.hiddenDOMWindow;
+    initialized = true;
+  }
+  catch(e) {}
+  if (reason === 'startup' || !initialized) {
     return wait(reason, options);
+  }
 
   // Inject globals ASAP in order to have console API working ASAP
   Object.defineProperties(options.loader.globals, descriptor(globals));
 
   // NOTE: Module is intentionally required only now because it relies
   // on existence of hidden window, which does not exists until startup.
   let { ready } = require('../addon/window');
   // Load localization manifest and .properties files.
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/browser/events.js
@@ -0,0 +1,20 @@
+/* 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";
+
+module.metadata = {
+  "stability": "unstable"
+};
+
+const { events } = require("../window/events");
+const { filter } = require("../event/utils");
+const { isBrowser } = require("../window/utils");
+
+// TODO: `isBrowser` detects weather window is a browser by checking
+// `windowtype` attribute, which means that all 'open' events will be
+// filtered out since document is not loaded yet. Maybe we can find a better
+// implementation for `isBrowser`. Either way it's not really needed yet
+// neither window tracker provides this event.
+
+exports.events = filter(function({target}) isBrowser(target), events);
--- a/addon-sdk/source/lib/sdk/deprecated/unit-test.js
+++ b/addon-sdk/source/lib/sdk/deprecated/unit-test.js
@@ -265,16 +265,22 @@ TestRunner.prototype = {
       if (this.waitTimeout !== null) {
         timer.clearTimeout(this.waitTimeout);
         this.waitTimeout = null;
       }
       // Do not leave any callback set when calling to `waitUntil`
       this.waitUntilCallback = null;
       if (this.test.passed == 0 && this.test.failed == 0) {
         this._logTestFailed("empty test");
+        if ("testMessage" in this.console) {
+          this.console.testMessage(false, false, this.test.name, "Empty test");
+        }
+        else {
+          this.console.error("fail:", "Empty test")
+        }
         this.failed++;
         this.test.failed++;
       }
       
       this.testRunSummary.push({
         name: this.test.name,
         passed: this.test.passed,
         failed: this.test.failed,
@@ -409,16 +415,22 @@ TestRunner.prototype = {
   waitUntilDone: function waitUntilDone(ms) {
     if (ms === undefined)
       ms = this.DEFAULT_PAUSE_TIMEOUT;
 
     var self = this;
 
     function tiredOfWaiting() {
       self._logTestFailed("timed out");
+      if ("testMessage" in self.console) {
+        self.console.testMessage(false, false, self.test.name, "Timed out");
+      }
+      else {
+        self.console.error("fail:", "Timed out")
+      }
       if (self.waitUntilCallback) {
         self.waitUntilCallback(true);
         self.waitUntilCallback = null;
       }
       self.failed++;
       self.test.failed++;
       self.done();
     }
--- a/addon-sdk/source/lib/sdk/event/core.js
+++ b/addon-sdk/source/lib/sdk/event/core.js
@@ -90,25 +90,30 @@ function emit(target, type, message /*, 
  * need it. Also it may be removed at any point without any further notice.
  *
  * Creates lazy iterator of return values of listeners. You can think of it
  * as lazy array of return values of listeners for the `emit` with the given
  * arguments.
  */
 emit.lazy = function lazy(target, type, message /*, ...*/) {
   let args = Array.slice(arguments, 2);
-  let listeners = observers(target, type).slice();
+  let state = observers(target, type);
+  let listeners = state.slice();
   let index = 0;
   let count = listeners.length;
 
   // If error event and there are no handlers then print error message
   // into a console.
   if (count === 0 && type === 'error') console.exception(message);
   while (index < count) {
-    try { yield listeners[index].apply(target, args); }
+    try {
+      let listener = listeners[index];
+      // Dispatch only if listener is still registered.
+      if (~state.indexOf(listener)) yield listener.apply(target, args);
+    }
     catch (error) {
       // If exception is not thrown by a error listener and error listener is
       // registered emit `error` event. Otherwise dump exception to the console.
       if (type !== 'error') emit(target, 'error', error);
       else console.exception(error);
     }
     index = index + 1;
   }
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/event/dom.js
@@ -0,0 +1,26 @@
+/* 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";
+
+module.metadata = {
+  "stability": "unstable"
+};
+
+let { emit, on, off } = require("./core");
+
+// Simple utility function takes event target, event type and optional
+// `options.capture` and returns node style event stream that emits "data"
+// events every time event of that type occurs on the given `target`.
+function open(target, type, options) {
+  let output = {};
+  let capture = options && options.capture ? true : false;
+
+  target.addEventListener(type, function(event) {
+    emit(output, "data", event);
+  }, capture);
+
+  return output;
+}
+exports.open = open;
--- a/addon-sdk/source/lib/sdk/event/target.js
+++ b/addon-sdk/source/lib/sdk/event/target.js
@@ -70,11 +70,14 @@ const EventTarget = Class({
    *    The listener function that processes the event.
    */
   removeListener: function removeListener(type, listener) {
     // Note: We can't just wrap `off` in `method` as we do it for other methods
     // cause skipping a second or third argument will behave very differently
     // than intended. This way we make sure all arguments are passed and only
     // one listener is removed at most.
     off(this, type, listener);
+  },
+  off: function(type, listener) {
+    off(this, type, listener)
   }
 });
 exports.EventTarget = EventTarget;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/event/utils.js
@@ -0,0 +1,101 @@
+/* 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";
+
+module.metadata = {
+  "stability": "unstable"
+};
+
+let { emit, on, off } = require("./core");
+
+// This module provides set of high order function for working with event
+// streams (streams in a NodeJS style that dispatch data, end and error
+// events).
+
+// Function takes a `target` object and returns set of implicit references
+// (non property references) it keeps. This basically allows defining
+// references between objects without storing the explicitly. See transform for
+// more details.
+let refs = (function() {
+  let refSets = new WeakMap();
+  return function refs(target) {
+    if (!refSets.has(target)) refSets.set(target, new Set());
+    return refSets.get(target);
+  }
+})();
+
+function transform(f, input) {
+  let output = {};
+
+  // Since event listeners don't prevent `input` to be GC-ed we wanna presrve
+  // it until `output` can be GC-ed. There for we add implicit reference which
+  // is removed once `input` ends.
+  refs(output).add(input);
+
+  function next(data) emit(output, "data", data);
+  on(input, "error", function(error) emit(output, "error", error));
+  on(input, "end", function() {
+    refs(output).delete(input);
+    emit(output, "end");
+  });
+  on(input, "data", function(data) f(data, next));
+  return output;
+}
+
+// High order event transformation function that takes `input` event channel
+// and returns transformation containing only events on which `p` predicate
+// returns `true`.
+function filter(predicate, input) {
+  return transform(function(data, next) {
+    if (predicate(data)) next(data)
+  }, input);
+}
+exports.filter = filter;
+
+// High order function that takes `input` and returns input of it's values
+// mapped via given `f` function.
+function map(f, input) transform(function(data, next) next(f(data)), input)
+exports.map = map;
+
+// High order function that takes `input` stream of streams and merges them
+// into single event stream. Like flatten but time based rather than order
+// based.
+function merge(inputs) {
+  let output = {};
+  let open = 1;
+  let state = [];
+  output.state = state;
+  refs(output).add(inputs);
+
+  function end(input) {
+    open = open - 1;
+    refs(output).delete(input);
+    if (open === 0) emit(output, "end");
+  }
+  function error(e) emit(output, "error", e);
+  function forward(input) {
+    state.push(input);
+    open = open + 1;
+    on(input, "end", function() end(input));
+    on(input, "error", error);
+    on(input, "data", function(data) emit(output, "data", data));
+  }
+
+  // If `inputs` is an array treat it as a stream.
+  if (Array.isArray(inputs)) {
+    inputs.forEach(forward)
+    end(inputs)
+  }
+  else {
+    on(inputs, "end", function() end(inputs));
+    on(inputs, "error", error);
+    on(inputs, "data", forward);
+  }
+
+  return output;
+}
+exports.merge = merge;
+
+function expand(f, inputs) merge(map(f, inputs))
+exports.expand = expand;
--- a/addon-sdk/source/lib/sdk/request.js
+++ b/addon-sdk/source/lib/sdk/request.js
@@ -11,26 +11,26 @@ module.metadata = {
 const { ns } = require("./core/namespace");
 const { emit } = require("./event/core");
 const { merge } = require("./util/object");
 const { stringify } = require("./querystring");
 const { EventTarget } = require("./event/target");
 const { Class } = require("./core/heritage");
 const { XMLHttpRequest } = require("./net/xhr");
 const apiUtils = require("./deprecated/api-utils");
+const { isValidURI } = require("./url.js");
 
 const response = ns();
 const request = ns();
 
 // Instead of creating a new validator for each request, just make one and
 // reuse it.
 const { validateOptions, validateSingleOption } = new OptionsValidator({
   url: {
-    //XXXzpao should probably verify that url is a valid url as well
-    is:  ["string"]
+    ok: isValidURI
   },
   headers: {
     map: function (v) v || {},
     is:  ["object"],
   },
   content: {
     map: function (v) v || null,
     is:  ["string", "object", "null"],
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/tab/events.js
@@ -0,0 +1,60 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+// This module provides temporary shim until Bug 843901 is shipped.
+// It basically registers tab event listeners on all windows that get
+// opened and forwards them through observer notifications.
+
+module.metadata = {
+  "stability": "experimental"
+};
+
+const { Ci } = require("chrome");
+const { windows, isInteractive } = require("../window/utils");
+const { events } = require("../browser/events");
+const { open } = require("../event/dom");
+const { filter, map, merge, expand } = require("../event/utils");
+
+// Module provides event stream (in nodejs style) that emits data events
+// for all the tab events that happen in running firefox. At the moment
+// it does it by registering listeners on all browser windows and then
+// forwarding events when they occur to a stream. This will become obsolete
+// once Bug 843901 is fixed, and we'll just leverage observer notifications.
+
+// Set of tab events that this module going to aggregate and expose.
+const TYPES = ["TabOpen","TabClose","TabSelect","TabMove","TabPinned",
+               "TabUnpinned"];
+
+// Utility function that given a browser `window` returns stream of above
+// defined tab events for all tabs on the given window.
+function tabEventsFor(window) {
+  // Map supported event types to a streams of those events on the given
+  // `window` and than merge these streams into single form stream off
+  // all events.
+  let channels = TYPES.map(function(type) open(window, type));
+  return merge(channels);
+}
+
+// Filter DOMContentLoaded events from all the browser events.
+let readyEvents = filter(function(e) e.type === "DOMContentLoaded", events);
+// Map DOMContentLoaded events to it's target browser windows.
+let futureWindows = map(function(e) e.target, readyEvents);
+// Expand all browsers that will become interactive to supported tab events
+// on these windows. Result will be a tab events from all tabs of all windows
+// that will become interactive.
+let eventsFromFuture = expand(tabEventsFor, futureWindows);
+
+// Above covers only windows that will become interactive in a future, but some
+// windows may already be interactive so we pick those and expand to supported
+// tab events for them too.
+let interactiveWindows = windows("navigator:browser", { includePrivate: true }).
+                         filter(isInteractive);
+let eventsFromInteractive = merge(interactiveWindows.map(tabEventsFor));
+
+
+// Finally merge stream of tab events from future windows and current windows
+// to cover all tab events on all windows that will open.
+exports.events = merge([eventsFromInteractive, eventsFromFuture]);
--- a/addon-sdk/source/lib/sdk/tabs/common.js
+++ b/addon-sdk/source/lib/sdk/tabs/common.js
@@ -15,13 +15,15 @@ function Options(options) {
       map: function(v) !!v,
       is: ["undefined", "boolean"]
     },
     isPinned: { is: ["undefined", "boolean"] },
     isPrivate: { is: ["undefined", "boolean"] },
     onOpen: { is: ["undefined", "function"] },
     onClose: { is: ["undefined", "function"] },
     onReady: { is: ["undefined", "function"] },
+    onLoad: { is: ["undefined", "function"] },
+    onPageShow: { is: ["undefined", "function"] },
     onActivate: { is: ["undefined", "function"] },
     onDeactivate: { is: ["undefined", "function"] }
   });
 }
 exports.Options = Options;
--- a/addon-sdk/source/lib/sdk/tabs/events.js
+++ b/addon-sdk/source/lib/sdk/tabs/events.js
@@ -7,16 +7,18 @@ module.metadata = {
   "stability": "unstable"
 };
 
 const ON_PREFIX = "on";
 const TAB_PREFIX = "Tab";
 
 const EVENTS = {
   ready: "DOMContentLoaded",
+  load: "load", // Used for non-HTML content
+  pageshow: "pageshow", // Used for cached content
   open: "TabOpen",
   close: "TabClose",
   activate: "TabSelect",
   deactivate: null,
   pinned: "TabPinned",
   unpinned: "TabUnpinned"
 }
 exports.EVENTS = EVENTS;
--- a/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
+++ b/addon-sdk/source/lib/sdk/tabs/tab-firefox.js
@@ -1,16 +1,17 @@
 /* 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 { Trait } = require("../deprecated/traits");
 const { EventEmitter } = require("../deprecated/events");
 const { defer } = require("../lang/functional");
+const { has } = require("../util/array");
 const { EVENTS } = require("./events");
 const { getThumbnailURIForWindow } = require("../content/thumbnail");
 const { getFaviconURIForLocation } = require("../io/data");
 const { activateTab, getOwnerWindow, getBrowserForTab, getTabTitle, setTabTitle,
         getTabURL, setTabURL, getTabContentType, getTabId } = require('./utils');
 const { getOwnerWindow: getPBOwnerWindow } = require('../private-browsing/window/utils');
 const viewNS = require('sdk/core/namespace').ns();
 
@@ -28,31 +29,38 @@ const TabTrait = Trait.compose(EventEmit
    */
   _tab: null,
   /**
    * Window wrapper whose tab this object represents.
    */
   window: null,
   constructor: function Tab(options) {
     this._onReady = this._onReady.bind(this);
+    this._onLoad = this._onLoad.bind(this);
+    this._onPageShow = this._onPageShow.bind(this);
     this._tab = options.tab;
     // TODO: Remove this dependency
     let window = this.window = options.window || require('../windows').BrowserWindow({ window: getOwnerWindow(this._tab) });
 
     // Setting event listener if was passed.
     for each (let type in EVENTS) {
       let listener = options[type.listener];
-      if (listener)
+      if (listener) {
         this.on(type.name, options[type.listener]);
-      if ('ready' != type.name) // window spreads this event.
+      }
+      // window spreads this event.
+      if (!has(['ready', 'load', 'pageshow'], (type.name)))
         window.tabs.on(type.name, this._onEvent.bind(this, type.name));
     }
 
     this.on(EVENTS.close.name, this.destroy.bind(this));
+
     this._browser.addEventListener(EVENTS.ready.dom, this._onReady, true);
+    this._browser.addEventListener(EVENTS.load.dom, this._onLoad, true);
+    this._browser.addEventListener(EVENTS.pageshow.dom, this._onPageShow, true);
 
     if (options.isPinned)
       this.pin();
 
     viewNS(this._public).tab = this._tab;
     getPBOwnerWindow.implement(this._public, getChromeTab);
 
     // Since we will have to identify tabs by a DOM elements facade function
@@ -60,32 +68,57 @@ const TabTrait = Trait.compose(EventEmit
     // that they more then one wrapper is not created per tab.
     return this;
   },
   destroy: function destroy() {
     this._removeAllListeners();
     if (this._tab) {
       let browser = this._browser;
       // The tab may already be removed from DOM -or- not yet added
-      if (browser)
+      if (browser) {
         browser.removeEventListener(EVENTS.ready.dom, this._onReady, true);
+        browser.removeEventListener(EVENTS.load.dom, this._onLoad, true);
+        browser.removeEventListener(EVENTS.pageshow.dom, this._onPageShow, true);
+      }
       this._tab = null;
       TABS.splice(TABS.indexOf(this), 1);
     }
   },
 
   /**
    * Internal listener that emits public event 'ready' when the page of this
-   * tab is loaded.
+   * tab is loaded, from DOMContentLoaded
    */
   _onReady: function _onReady(event) {
     // IFrames events will bubble so we need to ignore those.
     if (event.target == this._contentDocument)
       this._emit(EVENTS.ready.name, this._public);
   },
+  
+  /**
+   * Internal listener that emits public event 'load' when the page of this
+   * tab is loaded, for triggering on non-HTML content, bug #671305
+   */
+  _onLoad: function _onLoad(event) {
+    // IFrames events will bubble so we need to ignore those.
+    if (event.target == this._contentDocument) {
+      this._emit(EVENTS.load.name, this._public);
+    }
+  },
+
+  /**
+   * Internal listener that emits public event 'pageshow' when the page of this
+   * tab is loaded from cache, bug #671305
+   */
+  _onPageShow: function _onPageShow(event) {
+    // IFrames events will bubble so we need to ignore those.
+    if (event.target == this._contentDocument) {
+      this._emit(EVENTS.pageshow.name, this._public, event.persisted);
+    }
+  },
   /**
    * Internal tab event router. Window will emit tab related events for all it's
    * tabs, this listener will propagate all the events for this tab to it's
    * listeners.
    */
   _onEvent: function _onEvent(type, tab) {
     if (tab == this._public)
       this._emit(type, tab);
--- a/addon-sdk/source/lib/sdk/tabs/utils.js
+++ b/addon-sdk/source/lib/sdk/tabs/utils.js
@@ -298,8 +298,58 @@ function getTabForBrowser(browser) {
       if (tab.browser === browser)
         return tab;
     }
   }
   return null;
 }
 exports.getTabForBrowser = getTabForBrowser;
 
+function pin(tab) {
+  let gBrowser = getTabBrowserForTab(tab);
+  // TODO: Implement Fennec support
+  if (gBrowser) gBrowser.pinTab(tab);
+}
+exports.pin = pin;
+
+function unpin(tab) {
+  let gBrowser = getTabBrowserForTab(tab);
+  // TODO: Implement Fennec support
+  if (gBrowser) gBrowser.unpinTab(tab);
+}
+exports.unpin = unpin;
+
+function isPinned(tab) !!tab.pinned
+exports.isPinned = isPinned;
+
+function reload(tab) {
+  let gBrowser = getTabBrowserForTab(tab);
+  // Firefox
+  if (gBrowser) gBrowser.unpinTab(tab);
+  // Fennec
+  else if (tab.browser) tab.browser.reload();
+}
+exports.reload = reload
+
+function getIndex(tab) {
+  let gBrowser = getTabBrowserForTab(tab);
+  // Firefox
+  if (gBrowser) {
+    let document = getBrowserForTab(tab).contentDocument;
+    return gBrowser.getBrowserIndexForDocument(document);
+  }
+  // Fennec
+  else {
+    let window = getWindowHoldingTab(tab)
+    let tabs = window.BrowserApp.tabs;
+    for (let i = tabs.length; i >= 0; i--)
+      if (tabs[i] === tab) return i;
+  }
+}
+exports.getIndex = getIndex;
+
+function move(tab, index) {
+  let gBrowser = getTabBrowserForTab(tab);
+  // Firefox
+  if (gBrowser) gBrowser.moveTabTo(tab, index);
+  // TODO: Implement fennec support
+}
+exports.move = move;
--- a/addon-sdk/source/lib/sdk/test/runner.js
+++ b/addon-sdk/source/lib/sdk/test/runner.js
@@ -21,17 +21,18 @@ function runTests(findAndRunTests) {
     var total = tests.passed + tests.failed;
     stdout.write(tests.passed + " of " + total + " tests passed.\n");
 
     if (tests.failed == 0) {
       if (tests.passed === 0)
         stdout.write("No tests were run\n");
       exit(0);
     } else {
-      printFailedTests(tests, cfxArgs.verbose, stdout.write);
+      if (cfxArgs.verbose || cfxArgs.parseable)
+        printFailedTests(tests, stdout.write);
       exit(1);
     }
   };
 
   // We may have to run test on next cycle, otherwise XPCOM components
   // are not correctly updated.
   // For ex: nsIFocusManager.getFocusedElementForWindow may throw
   // NS_ERROR_ILLEGAL_VALUE exception.
@@ -45,20 +46,17 @@ function runTests(findAndRunTests) {
       verbose: cfxArgs.verbose,
       parseable: cfxArgs.parseable,
       print: stdout.write,
       onDone: onDone
     });
   }, 0);
 }
 
-function printFailedTests(tests, verbose, print) {
-  if (!verbose)
-    return;
-
+function printFailedTests(tests, print) {
   let iterationNumber = 0;
   let singleIteration = tests.testRuns.length == 1;
   let padding = singleIteration ? "" : "  ";
 
   print("\nThe following tests failed:\n");
 
   for each (let testRun in tests.testRuns) {
     iterationNumber++;
--- a/addon-sdk/source/lib/sdk/url.js
+++ b/addon-sdk/source/lib/sdk/url.js
@@ -229,8 +229,17 @@ const DataURL = Class({
     return "data:" +
       this.mimeType +
       parametersList.join(";") + "," +
       encodeURIComponent(data);
   }
 });
 
 exports.DataURL = DataURL;
+
+let isValidURI = exports.isValidURI = function (uri) {
+  try {
+    newURI(uri);
+  } catch(e) {
+    return false;
+  }
+  return true;
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/window/events.js
@@ -0,0 +1,80 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+module.metadata = {
+  "stability": "unstable"
+};
+
+const { Ci } = require("chrome");
+const events = require("../system/events");
+const { on, off, emit } = require("../event/core");
+const { windows } = require("../window/utils");
+
+// Object represents event channel on which all top level window events
+// will be dispatched, allowing users to react to those evens.
+const channel = {};
+exports.events = channel;
+
+const types = {
+  domwindowopened: "open",
+  domwindowclosed: "close",
+}
+
+// Utility function to query observer notification subject to get DOM window.
+function nsIDOMWindow($) $.QueryInterface(Ci.nsIDOMWindow);
+
+// Utility function used as system event listener that is invoked every time
+// top level window is open. This function does two things:
+// 1. Registers event listeners to track when document becomes interactive and
+//    when it's done loading. This will become obsolete once Bug 843910 is
+//    fixed.
+// 2. Forwards event to an exported event stream.
+function onOpen(event) {
+  observe(nsIDOMWindow(event.subject));
+  dispatch(event);
+}
+
+// Function registers single shot event listeners for relevant window events
+// that forward events to exported event stream.
+function observe(window) {
+  function listener(event) {
+    if (event.target === window.document) {
+      window.removeEventListener(event.type, listener, true);
+      emit(channel, "data", { type: event.type, target: window });
+    }
+  }
+
+  // Note: we do not remove listeners on unload since on add-on unload we
+  // nuke add-on sandbox that should allow GC-ing listeners. This also has
+  // positive effects on add-on / firefox unloads.
+  window.addEventListener("DOMContentLoaded", listener, true);
+  window.addEventListener("load", listener, true);
+  // TODO: Also add focus event listener so that can be forwarded to event
+  // stream. It can be part of Bug 854982.
+}
+
+// Utility function that takes system notification event and forwards it to a
+// channel in restructured form.
+function dispatch({ type: topic, subject }) {
+  emit(channel, "data", {
+    topic: topic,
+    type: types[topic],
+    target: nsIDOMWindow(subject)
+  });
+}
+
+// In addition to observing windows that are open we also observe windows
+// that are already already opened in case they're in process of loading.
+let opened = windows(null, { includePrivate: true });
+opened.forEach(observe);
+
+// Register system event listeners to forward messages on exported event
+// stream. Note that by default only weak refs are kept by system events
+// module so they will be GC-ed once add-on unloads and no manual cleanup
+// is required. Also note that listeners are intentionally not inlined since
+// to avoid premature GC-ing. Currently refs are kept by module scope and there
+// for they remain alive.
+events.on("domwindowopened", onOpen);
+events.on("domwindowclosed", dispatch);
--- a/addon-sdk/source/lib/sdk/window/utils.js
+++ b/addon-sdk/source/lib/sdk/window/utils.js
@@ -271,16 +271,25 @@ function windows(type, options) {
       list.push(window);
     }
   }
   return list;
 }
 exports.windows = windows;
 
 /**
+ * Check if the given window is interactive.
+ * i.e. if its "DOMContentLoaded" event has already been fired.
+ * @params {nsIDOMWindow} window
+ */
+function isInteractive(window)
+  window.document.readyState === "interactive" || isDocumentLoaded(window)
+exports.isInteractive = isInteractive;
+
+/**
  * Check if the given window is completely loaded.
  * i.e. if its "load" event has already been fired and all possible DOM content
  * is done loading (the whole DOM document, images content, ...)
  * @params {nsIDOMWindow} window
  */
 function isDocumentLoaded(window) {
   return window.document.readyState == "complete";
 }
--- a/addon-sdk/source/lib/sdk/windows/tabs-firefox.js
+++ b/addon-sdk/source/lib/sdk/windows/tabs-firefox.js
@@ -47,16 +47,18 @@ const WindowTabTracker = Trait.compose({
   _initWindowTabTracker: function _initWindowTabTracker() {
     // Ugly hack that we have to remove at some point (see Bug 658059). At this
     // point it is necessary to invoke lazy `tabs` getter on the windows object
     // which creates a `TabList` instance.
     this.tabs;
 
     // Binding all methods used as event listeners to the instance.
     this._onTabReady = this._emitEvent.bind(this, "ready");
+    this._onTabLoad = this._emitEvent.bind(this, "load");
+    this._onTabPageShow = this._emitEvent.bind(this, "pageshow");
     this._onTabOpen = this._onTabEvent.bind(this, "open");
     this._onTabClose = this._onTabEvent.bind(this, "close");
     this._onTabActivate = this._onTabEvent.bind(this, "activate");
     this._onTabDeactivate = this._onTabEvent.bind(this, "deactivate");
     this._onTabPinned = this._onTabEvent.bind(this, "pinned");
     this._onTabUnpinned = this._onTabEvent.bind(this, "unpinned");
 
     for each (let tab in getTabs(this._window)) {
@@ -104,27 +106,33 @@ const WindowTabTracker = Trait.compose({
 
       // Create a tab wrapper on open event, otherwise, just fetch existing
       // tab object
       let wrappedTab = Tab(options, type !== "open");
       if (!wrappedTab)
         return;
 
       // Setting up an event listener for ready events.
-      if (type === "open")
+      if (type === "open") {
         wrappedTab.on("ready", this._onTabReady);
+        wrappedTab.on("load", this._onTabLoad);
+        wrappedTab.on("pageshow", this._onTabPageShow);
+      }
 
       this._emitEvent(type, wrappedTab);
     }
   },
-  _emitEvent: function _emitEvent(type, tab) {
+  _emitEvent: function _emitEvent(type, tag) {
+    // Slices additional arguments and passes them into exposed
+    // listener like other events (for pageshow)
+    let args = Array.slice(arguments);
     // Notifies combined tab list that tab was added / removed.
-    tabs._emit(type, tab);
+    tabs._emit.apply(tabs, args);
     // Notifies contained tab list that window was added / removed.
-    this._tabs._emit(type, tab);
+    this._tabs._emit.apply(this._tabs, args);
   }
 });
 exports.WindowTabTracker = WindowTabTracker;
 
 /**
  * This trait is used to create live representation of open tab lists. Each
  * window wrapper's tab list is represented by an object created from this
  * trait. It is also used to represent list of all the open windows. Trait is
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/event/helpers.js
@@ -0,0 +1,59 @@
+/* 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 { on, once, off, emit, count } = require("sdk/event/core");
+
+function scenario(setup) {
+  return function(unit) {
+    return function(assert) {
+      let actual = [];
+      let input = {};
+      unit(input, function(output, events, expected, message) {
+        let result = setup(output, expected, actual);
+
+        events.forEach(function(event) emit(input, "data", event));
+
+        assert.deepEqual(actual, result, message);
+      });
+    }
+  }
+}
+
+exports.emits = scenario(function(output, expected, actual) {
+  on(output, "data", function(data) actual.push(this, data));
+
+  return expected.reduce(function($$, $) $$.concat(output, $), []);
+});
+
+exports.registerOnce = scenario(function(output, expected, actual) {
+  function listener(data) actual.push(data);
+  on(output, "data", listener);
+  on(output, "data", listener);
+  on(output, "data", listener);
+
+  return expected;
+});
+
+exports.ignoreNew = scenario(function(output, expected, actual) {
+  on(output, "data", function(data) {
+    actual.push(data + "#1");
+    on(output, "data", function(data) {
+      actual.push(data + "#2");
+    });
+  });
+
+  return expected.map(function($) $ + "#1");
+});
+
+exports.FIFO = scenario(function(target, expected, actual) {
+  on(target, "data", function($) actual.push($ + "#1"));
+  on(target, "data", function($) actual.push($ + "#2"));
+  on(target, "data", function($) actual.push($ + "#3"));
+
+  return expected.reduce(function(result, value) {
+    return result.concat(value + "#1", value + "#2", value + "#3");
+  }, []);
+});
--- a/addon-sdk/source/test/tabs/test-firefox-tabs.js
+++ b/addon-sdk/source/test/tabs/test-firefox-tabs.js
@@ -3,16 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 'use strict';
 
 const { Cc, Ci } = require('chrome');
 const { Loader } = require('sdk/test/loader');
 const timer = require('sdk/timers');
 const { StringBundle } = require('sdk/deprecated/app-strings');
 
+const base64png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
+                  "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
+                  "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
+                  "bWRR9AAAAABJRU5ErkJggg%3D%3D";
+
 // TEST: tabs.activeTab getter
 exports.testActiveTab_getter = function(test) {
   test.waitUntilDone();
 
   openBrowserWindow(function(window, browser) {
     let tabs = require("sdk/tabs");
 
     let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head></html>";
@@ -173,20 +178,36 @@ exports.testTabProperties = function(tes
       onReady: function(tab) {
         test.assertEqual(tab.title, "foo", "title of the new tab matches");
         test.assertEqual(tab.url, url, "URL of the new tab matches");
         test.assert(tab.favicon, "favicon of the new tab is not empty");
         test.assertEqual(tab.style, null, "style of the new tab matches");
         test.assertEqual(tab.index, 1, "index of the new tab matches");
         test.assertNotEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
         test.assertNotEqual(tab.id, null, "a tab object always has an id property.");
-        closeBrowserWindow(window, function() test.done());
+        onReadyOrLoad(window);
+      },
+      onLoad: function(tab) {
+        test.assertEqual(tab.title, "foo", "title of the new tab matches");
+        test.assertEqual(tab.url, url, "URL of the new tab matches");
+        test.assert(tab.favicon, "favicon of the new tab is not empty");
+        test.assertEqual(tab.style, null, "style of the new tab matches");
+        test.assertEqual(tab.index, 1, "index of the new tab matches");
+        test.assertNotEqual(tab.getThumbnail(), null, "thumbnail of the new tab matches");
+        test.assertNotEqual(tab.id, null, "a tab object always has an id property.");
+        onReadyOrLoad(window);
       }
     });
   });
+
+  let count = 0;
+  function onReadyOrLoad (window) {
+    if (count++)
+      closeBrowserWindow(window, function() test.done());
+  }
 };
 
 // TEST: tab properties
 exports.testTabContentTypeAndReload = function(test) {
   test.waitUntilDone();
   openBrowserWindow(function(window, browser) {
     let tabs = require("sdk/tabs");
     let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
@@ -956,16 +977,123 @@ exports['test unique tab ids'] = functio
     index++
     fn(index);
   }
 
   // run!
   next(0);
 }
 
+// related to Bug 671305
+exports.testOnLoadEventWithDOM = function(test) {
+  test.waitUntilDone();
+
+  openBrowserWindow(function(window, browser) {
+    let tabs = require('sdk/tabs');
+    let count = 0;
+    tabs.on('load', function onLoad(tab) {
+      test.assertEqual(tab.title, 'tab', 'tab passed in as arg, load called');
+      if (!count++) {
+        tab.reload();
+      }
+      else {
+        // end of test
+        tabs.removeListener('load', onLoad);
+        test.pass('onLoad event called on reload');
+        closeBrowserWindow(window, function() test.done());
+      }
+    });
+
+    // open a about: url
+    tabs.open({
+      url: 'data:text/html;charset=utf-8,<title>tab</title>',
+      inBackground: true
+    });
+  });
+};
+
+// related to Bug 671305
+exports.testOnLoadEventWithImage = function(test) {
+  test.waitUntilDone();
+
+  openBrowserWindow(function(window, browser) {
+    let tabs = require('sdk/tabs');
+    let count = 0;
+    tabs.on('load', function onLoad(tab) {
+      if (!count++) {
+        tab.reload();
+      }
+      else {
+        // end of test
+        tabs.removeListener('load', onLoad);
+        test.pass('onLoad event called on reload with image');
+        closeBrowserWindow(window, function() test.done());
+      }
+    });
+
+    // open a image url
+    tabs.open({
+      url: base64png,
+      inBackground: true
+    });
+  });
+};
+
+exports.testOnPageShowEvent = function (test) {
+  test.waitUntilDone();
+
+  let firstUrl = 'about:home';
+  let secondUrl = 'about:newtab';
+
+  openBrowserWindow(function(window, browser) {
+    let tabs = require('sdk/tabs');
+
+    let wait = 500;
+    let counter = 1;
+    tabs.on('pageshow', function setup(tab, persisted) {
+      if (counter === 1)
+        test.assert(!persisted, 'page should not be cached on initial load');
+
+      if (wait > 5000) {
+        test.fail('Page was not cached after 5s')
+        closeBrowserWindow(window, function() test.done());
+      }
+
+      if (tab.url === firstUrl) {
+        // If first page has persisted, pass
+        if (persisted) {
+          tabs.removeListener('pageshow', setup);
+          test.pass('pageshow event called on history.back()');
+          closeBrowserWindow(window, function() test.done());
+        }
+        // On the first run, or if the page wasn't cached
+        // the first time due to not waiting long enough,
+        // try again with a longer delay (this is terrible
+        // and ugly)
+        else {
+          counter++;
+          timer.setTimeout(function () {
+            tab.url = secondUrl;
+            wait *= 2;
+          }, wait);
+        }
+      }
+      else {
+        tab.attach({
+          contentScript: 'setTimeout(function () { window.history.back(); }, 0)'
+        });
+      }
+    });
+
+    tabs.open({
+      url: firstUrl
+    });
+  });
+};
+
 /******************* helpers *********************/
 
 // Helper for getting the active window
 this.__defineGetter__("activeWindow", function activeWindow() {
   return Cc["@mozilla.org/appshell/window-mediator;1"].
          getService(Ci.nsIWindowMediator).
          getMostRecentWindow("navigator:browser");
 });
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/test-browser-events.js
@@ -0,0 +1,105 @@
+/* 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 { Loader } = require("sdk/test/loader");
+const { open, getMostRecentBrowserWindow, getOuterId } = require("sdk/window/utils");
+const { setTimeout } = require("sdk/timers");
+
+exports["test browser events"] = function(assert, done) {
+  let loader = Loader(module);
+  let { events } = loader.require("sdk/browser/events");
+  let { on, off } = loader.require("sdk/event/core");
+  let actual = [];
+
+  on(events, "data", function handler(e) {
+    actual.push(e);
+    if (e.type === "load") window.close();
+    if (e.type === "close") {
+      // Unload the module so that all listeners set by observer are removed.
+
+      let [ ready, load, close ] = actual;
+
+      assert.equal(ready.type, "DOMContentLoaded");
+      assert.equal(ready.target, window, "window ready");
+
+      assert.equal(load.type, "load");
+      assert.equal(load.target, window, "window load");
+
+      assert.equal(close.type, "close");
+      assert.equal(close.target, window, "window load");
+
+      // Note: If window is closed right after this GC won't have time
+      // to claim loader and there for this listener, there for it's safer
+      // to remove listener.
+      off(events, "data", handler);
+      loader.unload();
+      done();
+    }
+  });
+
+  // Open window and close it to trigger observers.
+  let window = open();
+};
+
+exports["test browser events ignore other wins"] = function(assert, done) {
+  let loader = Loader(module);
+  let { events: windowEvents } = loader.require("sdk/window/events");
+  let { events: browserEvents } = loader.require("sdk/browser/events");
+  let { on, off } = loader.require("sdk/event/core");
+  let actualBrowser = [];
+  let actualWindow = [];
+
+  function browserEventHandler(e) actualBrowser.push(e)
+  on(browserEvents, "data", browserEventHandler);
+  on(windowEvents, "data", function handler(e) {
+    actualWindow.push(e);
+    // Delay close so that if "load" is also emitted on `browserEvents`
+    // `browserEventHandler` will be invoked.
+    if (e.type === "load") setTimeout(window.close);
+    if (e.type === "close") {
+      assert.deepEqual(actualBrowser, [], "browser events were not triggered");
+      let [ open, ready, load, close ] = actualWindow;
+
+      assert.equal(open.type, "open");
+      assert.equal(open.target, window, "window is open");
+
+
+
+      assert.equal(ready.type, "DOMContentLoaded");
+      assert.equal(ready.target, window, "window ready");
+
+      assert.equal(load.type, "load");
+      assert.equal(load.target, window, "window load");
+
+      assert.equal(close.type, "close");
+      assert.equal(close.target, window, "window load");
+
+
+      // Note: If window is closed right after this GC won't have time
+      // to claim loader and there for this listener, there for it's safer
+      // to remove listener.
+      off(windowEvents, "data", handler);
+      off(browserEvents, "data", browserEventHandler);
+      loader.unload();
+      done();
+    }
+  });
+
+  // Open window and close it to trigger observers.
+  let window = open("data:text/html,not a browser");
+};
+
+if (require("sdk/system/xul-app").is("Fennec")) {
+  module.exports = {
+    "test Unsupported Test": function UnsupportedTest (assert) {
+        assert.pass(
+          "Skipping this test until Fennec support is implemented." +
+          "See bug 793071");
+    }
+  }
+}
+
+require("test").run(exports);
--- a/addon-sdk/source/test/test-event-core.js
+++ b/addon-sdk/source/test/test-event-core.js
@@ -63,16 +63,29 @@ exports['test no side-effects in emit'] 
     assert.pass('first listener is called');
     on(target, 'message', function() {
       assert.fail('second listener is called');
     });
   });
   emit(target, 'message');
 };
 
+exports['test can remove next listener'] = function(assert) {
+  let target = { name: 'target' };
+  function fail() assert.fail('Listener should be removed');
+
+  on(target, 'data', function() {
+    assert.pass('first litener called');
+    off(target, 'data', fail);
+  });
+  on(target, 'data', fail);
+
+  emit(target, 'data', 'hello');
+};
+
 exports['test order of propagation'] = function(assert) {
   let actual = [];
   let target = { name: 'target' };
   on(target, 'message', function() { actual.push(1); });
   on(target, 'message', function() { actual.push(2); });
   on(target, 'message', function() { actual.push(3); });
   emit(target, 'message');
   assert.deepEqual([ 1, 2, 3 ], actual, 'called in order they were added');
--- a/addon-sdk/source/test/test-event-target.js
+++ b/addon-sdk/source/test/test-event-target.js
@@ -110,17 +110,17 @@ exports['test remove a listener'] = func
   target.on('message', function listener() {
     actual.push(1);
     target.on('message', function() {
       target.removeListener('message', listener);
       actual.push(2);
     })
   });
 
-  target.removeListener('message'); // must do nothing.
+  target.off('message'); // must do nothing.
   emit(target, 'message');
   assert.deepEqual([ 1 ], actual, 'first listener called');
   emit(target, 'message');
   assert.deepEqual([ 1, 1, 2 ], actual, 'second listener called');
   emit(target, 'message');
   assert.deepEqual([ 1, 1, 2, 2, 2 ], actual, 'first listener removed');
 };
 
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/test-event-utils.js
@@ -0,0 +1,169 @@
+/* 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 { on, emit } = require("sdk/event/core");
+const { filter, map, merge, expand } = require("sdk/event/utils");
+const $ = require("./event/helpers");
+
+function isEven(x) !(x % 2)
+function inc(x) x + 1
+
+exports["test filter events"] = function(assert) {
+  let input = {};
+  let evens = filter(isEven, input);
+  let actual = [];
+  on(evens, "data", function(e) actual.push(e));
+
+  [1, 2, 3, 4, 5, 6, 7].forEach(function(x) emit(input, "data", x));
+
+  assert.deepEqual(actual, [2, 4, 6], "only even numbers passed through");
+};
+
+exports["test filter emits"] = $.emits(function(input, assert) {
+  let output = filter(isEven, input);
+  assert(output,  [1, 2, 3, 4, 5], [2, 4], "this is `output` & evens passed");
+});;
+
+exports["test filter reg once"] = $.registerOnce(function(input, assert) {
+  assert(filter(isEven, input),  [1, 2, 3, 4, 5, 6], [2, 4, 6],
+         "listener can be registered only once");
+});
+
+exports["test filter ignores new"] = $.ignoreNew(function(input, assert) {
+  assert(filter(isEven, input), [1, 2, 3], [2],
+         "new listener is ignored")
+});
+
+exports["test filter is FIFO"] = $.FIFO(function(input, assert) {
+  assert(filter(isEven, input), [1, 2, 3, 4], [2, 4],
+         "listeners are invoked in fifo order")
+});
+
+exports["test map events"] = function(assert) {
+  let input = {};
+  let incs = map(inc, input);
+  let actual = [];
+  on(incs, "data", function(e) actual.push(e));
+
+  [1, 2, 3, 4].forEach(function(x) emit(input, "data", x));
+
+  assert.deepEqual(actual, [2, 3, 4, 5], "all numbers were incremented");
+};
+
+exports["test map emits"] = $.emits(function(input, assert) {
+  let output = map(inc, input);
+  assert(output,  [1, 2, 3], [2, 3, 4], "this is `output` & evens passed");
+});;
+
+exports["test map reg once"] = $.registerOnce(function(input, assert) {
+  assert(map(inc, input),  [1, 2, 3], [2, 3, 4],
+         "listener can be registered only once");
+});
+
+exports["test map ignores new"] = $.ignoreNew(function(input, assert) {
+  assert(map(inc, input), [1], [2],
+         "new listener is ignored")
+});
+
+exports["test map is FIFO"] = $.FIFO(function(input, assert) {
+  assert(map(inc, input), [1, 2, 3, 4], [2, 3, 4, 5],
+         "listeners are invoked in fifo order")
+});
+
+exports["test merge stream[stream]"] = function(assert) {
+  let a = {}, b = {}, c = {};
+  let inputs = {};
+  let actual = [];
+
+  on(merge(inputs), "data", function($) actual.push($))
+
+  emit(inputs, "data", a);
+  emit(a, "data", "a1");
+  emit(inputs, "data", b);
+  emit(b, "data", "b1");
+  emit(a, "data", "a2");
+  emit(inputs, "data", c);
+  emit(c, "data", "c1");
+  emit(c, "data", "c2");
+  emit(b, "data", "b2");
+  emit(a, "data", "a3");
+
+  assert.deepEqual(actual, ["a1", "b1", "a2", "c1", "c2", "b2", "a3"],
+                   "all inputs data merged into one");
+};
+
+exports["test merge array[stream]"] = function(assert) {
+  let a = {}, b = {}, c = {};
+  let inputs = {};
+  let actual = [];
+
+  on(merge([a, b, c]), "data", function($) actual.push($))
+
+  emit(a, "data", "a1");
+  emit(b, "data", "b1");
+  emit(a, "data", "a2");
+  emit(c, "data", "c1");
+  emit(c, "data", "c2");
+  emit(b, "data", "b2");
+  emit(a, "data", "a3");
+
+  assert.deepEqual(actual, ["a1", "b1", "a2", "c1", "c2", "b2", "a3"],
+                   "all inputs data merged into one");
+};
+
+exports["test merge emits"] = $.emits(function(input, assert) {
+  let evens = filter(isEven, input)
+  let output = merge([evens, input]);
+  assert(output, [1, 2, 3], [1, 2, 2, 3], "this is `output` & evens passed");
+});
+
+
+exports["test merge reg once"] = $.registerOnce(function(input, assert) {
+  let evens = filter(isEven, input)
+  let output = merge([input, evens]);
+  assert(output,  [1, 2, 3, 4], [1, 2, 2, 3, 4, 4],
+         "listener can be registered only once");
+});
+
+exports["test merge ignores new"] = $.ignoreNew(function(input, assert) {
+  let evens = filter(isEven, input)
+  let output = merge([input, evens])
+  assert(output, [1], [1],
+         "new listener is ignored")
+});
+
+exports["test marge is FIFO"] = $.FIFO(function(input, assert) {
+  let evens = filter(isEven, input)
+  let output = merge([input, evens])
+
+  assert(output, [1, 2, 3, 4], [1, 2, 2, 3, 4, 4],
+         "listeners are invoked in fifo order")
+});
+
+exports["test expand"] = function(assert) {
+  let a = {}, b = {}, c = {};
+  let inputs = {};
+  let actual = [];
+
+  on(expand(function($) $(), inputs), "data", function($) actual.push($))
+
+  emit(inputs, "data", function() a);
+  emit(a, "data", "a1");
+  emit(inputs, "data", function() b);
+  emit(b, "data", "b1");
+  emit(a, "data", "a2");
+  emit(inputs, "data", function() c);
+  emit(c, "data", "c1");
+  emit(c, "data", "c2");
+  emit(b, "data", "b2");
+  emit(a, "data", "a3");
+
+  assert.deepEqual(actual, ["a1", "b1", "a2", "c1", "c2", "b2", "a3"],
+                   "all inputs data merged into one");
+}
+
+
+require('test').run(exports);
--- a/addon-sdk/source/test/test-indexed-db.js
+++ b/addon-sdk/source/test/test-indexed-db.js
@@ -4,17 +4,17 @@
 
 "use strict";
 
 let xulApp = require("sdk/system/xul-app");
 if (xulApp.versionInRange(xulApp.platformVersion, "16.0a1", "*")) {
 new function tests() {
 
 const { indexedDB, IDBKeyRange, DOMException, IDBCursor, IDBTransaction,
-        IDBOpenDBRequest, IDBVersionChangeEvent, IDBDatabase, IDBIndex,
+        IDBOpenDBRequest, IDBVersionChangeEvent, IDBDatabase, IDBIndex, 
         IDBObjectStore, IDBRequest
       } = require("sdk/indexed-db");
 
 exports["test indexedDB is frozen"] = function(assert){
   let original = indexedDB.open;
   let f = function(){};
   assert.throws(function(){indexedDB.open = f});
   assert.equal(indexedDB.open,original);
--- a/addon-sdk/source/test/test-request.js
+++ b/addon-sdk/source/test/test-request.js
@@ -25,26 +25,26 @@ const port = 8099;
 
 
 exports.testOptionsValidator = function(test) {
   // First, a simple test to make sure we didn't break normal functionality.
   test.assertRaises(function () {
     Request({
       url: null
     });
-  }, 'The option "url" must be one of the following types: string');
+  }, 'The option "url" is invalid.');
 
   // Next we'll have a Request that doesn't throw from c'tor, but from a setter.
   let req = Request({
     url: "http://playground.zpao.com/jetpack/request/text.php",
     onComplete: function () {}
   });
   test.assertRaises(function () {
-    req.url = null;
-  }, 'The option "url" must be one of the following types: string');
+    req.url = 'www.mozilla.org';
+  }, 'The option "url" is invalid.');
   // The url shouldn't have changed, so check that
   test.assertEqual(req.url, "http://playground.zpao.com/jetpack/request/text.php");
 }
 
 exports.testContentValidator = function(test) {
   test.waitUntilDone();
   Request({
     url: "data:text/html;charset=utf-8,response",
--- a/addon-sdk/source/test/test-self.js
+++ b/addon-sdk/source/test/test-self.js
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {Cc, Ci, Cu, Cm, components} = require('chrome');
 Cu.import("resource://gre/modules/AddonManager.jsm", this);
+const xulApp = require("sdk/system/xul-app");
 
 exports.testSelf = function(test) {
   var self = require("sdk/self");
 
   var source = self.data.load("test-content-symbiont.js");
   test.assert(source.match(/test-content-symbiont/), "self.data.load() works");
 
   // Likewise, we can't assert anything about the full URL, because that
@@ -25,18 +26,22 @@ exports.testSelf = function(test) {
   test.assertEqual(typeof(url), "string", "self.data.url() returns string");
   test.assertEqual(/\/undefined$/.test(url), false);
 
   // When tests are run on just the api-utils package, self.name is
   // api-utils. When they're run as 'cfx testall', self.name is testpkgs.
   test.assert(self.name == "addon-sdk", "self.name is addon-sdk");
 
   // loadReason may change here, as we change the way tests addons are installed
-  test.assertEqual(self.loadReason, "startup",
-                   "self.loadReason is always `startup` on test runs");
+  // Bug 854937 fixed loadReason and is now install
+  let testLoadReason = xulApp.versionInRange(xulApp.platformVersion,
+                                             "23.0a1", "*") ? "install"
+                                                            : "startup";
+  test.assertEqual(self.loadReason, testLoadReason,
+                   "self.loadReason is either startup or install on test runs");
 
   test.assertEqual(self.isPrivateBrowsingSupported, false,
                    'usePrivateBrowsing property is false by default');
 };
 
 exports.testSelfID = function(test) {
   test.waitUntilDone();
 
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/test-tab-events.js
@@ -0,0 +1,175 @@
+/* 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 { Loader } = require("sdk/test/loader");
+const utils = require("sdk/tabs/utils");
+const { open, close } = require("sdk/window/helpers");
+const { getMostRecentBrowserWindow } = require("sdk/window/utils");
+const { events } = require("sdk/tab/events");
+const { on, off } = require("sdk/event/core");
+const { resolve } = require("sdk/core/promise");
+
+let isFennec = require("sdk/system/xul-app").is("Fennec");
+
+function test(scenario, currentWindow) {
+  let useActiveWindow = isFennec || currentWindow;
+  return function(assert, done) {
+    let actual = [];
+    function handler(event) actual.push(event)
+
+    let win = useActiveWindow ? resolve(getMostRecentBrowserWindow()) :
+              open(null, {
+                features: { private: true, toolbar:true, chrome: true }
+              });
+    let window = null;
+
+    win.then(function(w) {
+      window = w;
+      on(events, "data", handler);
+      return scenario(assert, window, actual);
+    }).then(function() {
+      off(events, "data", handler);
+      return useActiveWindow ? null : close(window);
+    }).then(done, assert.fail);
+  }
+}
+
+exports["test current window"] = test(function(assert, window, events) {
+  // Just making sure that tab events work for already opened tabs not only
+  // for new windows.
+  let tab = utils.openTab(window, 'data:text/plain,open');
+  utils.closeTab(tab);
+
+  let [open, select, close] = events;
+
+  assert.equal(open.type, "TabOpen");
+  assert.equal(open.target, tab);
+
+  assert.equal(select.type, "TabSelect");
+  assert.equal(select.target, tab);
+
+  assert.equal(close.type, "TabClose");
+  assert.equal(close.target, tab);
+});
+
+exports["test open"] = test(function(assert, window, events) {
+  let tab = utils.openTab(window, 'data:text/plain,open');
+  let [open, select] = events;
+
+  assert.equal(open.type, "TabOpen");
+  assert.equal(open.target, tab);
+
+  assert.equal(select.type, "TabSelect");
+  assert.equal(select.target, tab);
+});
+
+exports["test open -> close"] = test(function(assert, window, events) {
+  // First tab is useless we just open it so that closing second tab won't
+  // close window on some platforms.
+  let _ = utils.openTab(window, 'daat:text/plain,ignore');
+  let tab = utils.openTab(window, 'data:text/plain,open-close');
+  utils.closeTab(tab);
+
+  let [_open, _select, open, select, close] = events;
+
+  assert.equal(open.type, "TabOpen");
+  assert.equal(open.target, tab);
+
+  assert.equal(select.type, "TabSelect");
+  assert.equal(select.target, tab);
+
+  assert.equal(close.type, "TabClose");
+  assert.equal(close.target, tab);
+});
+
+exports["test open -> open -> select"] = test(function(assert, window, events) {
+  let tab1 = utils.openTab(window, 'data:text/plain,Tab-1');
+  let tab2 = utils.openTab(window, 'data:text/plain,Tab-2');
+  utils.activateTab(tab1, window);
+
+  let [open1, select1, open2, select2, select3] = events;
+
+  // Open first tab
+  assert.equal(open1.type, "TabOpen", "first tab opened")
+  assert.equal(open1.target, tab1, "event.target is first tab")
+
+  assert.equal(select1.type, "TabSelect", "first tab seleceted")
+  assert.equal(select1.target, tab1, "event.target is first tab")
+
+
+  // Open second tab
+  assert.equal(open2.type, "TabOpen", "second tab opened");
+  assert.equal(open2.target, tab2, "event.target is second tab");
+
+  assert.equal(select2.type, "TabSelect", "second tab seleceted");
+  assert.equal(select2.target, tab2, "event.target is second tab");
+
+  // Select first tab
+  assert.equal(select3.type, "TabSelect", "tab seleceted");
+  assert.equal(select3.target, tab1, "event.target is first tab");
+});
+
+exports["test open -> pin -> unpin"] = test(function(assert, window, events) {
+  let tab = utils.openTab(window, 'data:text/plain,pin-unpin');
+  utils.pin(tab);
+  utils.unpin(tab);
+
+  let [open, select, move, pin, unpin] = events;
+
+  assert.equal(open.type, "TabOpen");
+  assert.equal(open.target, tab);
+
+  assert.equal(select.type, "TabSelect");
+  assert.equal(select.target, tab);
+
+  if (isFennec) {
+    assert.pass("Tab pin / unpin is not supported by Fennec");
+  }
+  else {
+    assert.equal(move.type, "TabMove");
+    assert.equal(move.target, tab);
+
+    assert.equal(pin.type, "TabPinned");
+    assert.equal(pin.target, tab);
+
+    assert.equal(unpin.type, "TabUnpinned");
+    assert.equal(unpin.target, tab);
+  }
+});
+
+exports["test open -> open -> move "] = test(function(assert, window, events) {
+  let tab1 = utils.openTab(window, 'data:text/plain,Tab-1');
+  let tab2 = utils.openTab(window, 'data:text/plain,Tab-2');
+  utils.move(tab1, 2);
+
+  let [open1, select1, open2, select2, move] = events;
+
+  // Open first tab
+  assert.equal(open1.type, "TabOpen", "first tab opened");
+  assert.equal(open1.target, tab1, "event.target is first tab");
+
+  assert.equal(select1.type, "TabSelect", "first tab seleceted")
+  assert.equal(select1.target, tab1, "event.target is first tab");
+
+
+  // Open second tab
+  assert.equal(open2.type, "TabOpen", "second tab opened");
+  assert.equal(open2.target, tab2, "event.target is second tab");
+
+  assert.equal(select2.type, "TabSelect", "second tab seleceted");
+  assert.equal(select2.target, tab2, "event.target is second tab");
+
+  if (isFennec) {
+    assert.pass("Tab index changes not supported on Fennec yet")
+  }
+  else {
+    // Move first tab
+    assert.equal(move.type, "TabMove", "tab moved");
+    assert.equal(move.target, tab1, "event.target is first tab");
+  }
+});
+
+require("test").run(exports);
--- a/addon-sdk/source/test/test-unit-test.js
+++ b/addon-sdk/source/test/test-unit-test.js
@@ -109,67 +109,58 @@ exports.testWaitUntilErrorInCallback = f
 
   test.expectFail(function() {
     test.waitUntil(function () {throw "oops"}, "waitUntil pass")
         .then(function () test.done());
   });
 }
 
 exports.testWaitUntilTimeoutInCallback = function(test) {
-  test.waitUntilDone(1000);
+  test.waitUntilDone();
+
+  let expected = [];
+  let message = 0;
+  if (require("@test/options").parseable) {
+    expected.push(["print", "TEST-START | wait4ever\n"]);
+    expected.push(["error", "fail:", "Timed out"]);
+    expected.push(["error", "test assertion never became true:\n", "assertion failed, value is false\n"]);
+    expected.push(["print", "TEST-END | wait4ever\n"]);
+  }
+  else {
+    expected.push(["info",  "executing 'wait4ever'"]);
+    expected.push(["error", "fail:", "Timed out"]);
+    expected.push(["error", "test assertion never became true:\n", "assertion failed, value is false\n"]);
+  }
+
+  function checkExpected(name, args) {
+    if (expected.length == 0 || expected[0][0] != name) {
+      test.fail("Saw an unexpected console." + name + "() call " + args);
+      return;
+    }
+
+    message++;
+    let expectedArgs = expected.shift().slice(1);
+    for (let i = 0; i < expectedArgs.length; i++)
+      test.assertEqual(args[i], expectedArgs[i], "Should have seen the right message in argument " + i + " of message " + message);
+    if (expected.length == 0)
+      test.done();
+  }
 
   let runner = new (require("sdk/deprecated/unit-test").TestRunner)({
     console: {
-      calls: 0,
-      error: function(msg) {
-        this.calls++;
-        if (this.calls == 2) {
-          test.assertEqual(arguments[0], "test assertion never became true:\n");
-          test.assertEqual(arguments[1], "assertion failed, value is false\n");
-          // We could additionally check that arguments[1] contains the correct
-          // stack, but it would be difficult to do so given that it contains
-          // resource: URLs with a randomly generated string embedded in them
-          // (the ID of the test addon created to run the tests). And in any
-          // case, checking the arguments seems sufficient.
-
-          test.done();
-        }
-        else {
-          test.fail("We got unexpected console.error() calls from waitUntil" +
-                    " assertion callback: '" + arguments[1] + "'");
-        }
+      error: function() {
+        checkExpected("error", Array.slice(arguments));
       },
-      info: function (msg) {
-        this.calls++;
-        if (require("@test/options").parseable) {
-          test.fail("We got unexpected console.info() calls: " + msg)
-        }
-        else if (this.calls == 1) {
-          test.assertEqual(arguments[0], "executing 'wait4ever'");
-        }
-        else {
-          test.fail("We got unexpected console.info() calls: " + msg);
-        }
+      info: function () {
+        checkExpected("info", Array.slice(arguments));
       },
       trace: function () {},
       exception: function () {},
-      print: function (str) {
-        this.calls++;
-        if (!require("@test/options").parseable) {
-          test.fail("We got unexpected console.print() calls: " + str)
-        }
-        else if (this.calls == 1) {
-          test.assertEqual(str, "TEST-START | wait4ever\n");
-        }
-        else if (this.calls == 3) {
-          test.assertEqual(str, "TEST-END | wait4ever\n");
-        }
-        else {
-          test.fail("We got unexpected console.print() calls: " + str);
-        }
+      print: function () {
+        checkExpected("print", Array.slice(arguments));
       }
     }
   });
 
   runner.start({
     test: {
       name: "wait4ever",
       testFunction: function(test) {
--- a/addon-sdk/source/test/test-url.js
+++ b/addon-sdk/source/test/test-url.js
@@ -237,8 +237,112 @@ exports.testDataURLparseBase64 = functio
   test.assertEqual(dataURL.base64, true, "base64 is true for base64 encoded data uri")
   test.assertEqual(dataURL.data, text, "data is properly decoded")
   test.assertEqual(dataURL.mimeType, "text/plain", "mimeType is set properly")
   test.assertEqual(Object.keys(dataURL.parameters).length, 1, "one parameters specified");
   test.assertEqual(dataURL.parameters["base64"], "", "parameter set without value");
 
   test.assertEqual(dataURL.toString(), "data:text/plain;base64," + encodeURIComponent(b64text));
 }
+
+exports.testIsValidURI = function (test) {
+  validURIs().forEach(function (aUri) {
+    test.assertEqual(url.isValidURI(aUri), true, aUri + ' is a valid URL');
+  });
+};
+
+exports.testIsInvalidURI = function (test) {
+  invalidURIs().forEach(function (aUri) {
+    test.assertEqual(url.isValidURI(aUri), false, aUri + ' is an invalid URL');
+  });
+};
+
+function validURIs() {
+  return [
+  'http://foo.com/blah_blah',
+  'http://foo.com/blah_blah/',
+  'http://foo.com/blah_blah_(wikipedia)',
+  'http://foo.com/blah_blah_(wikipedia)_(again)',
+  'http://www.example.com/wpstyle/?p=364',
+  'https://www.example.com/foo/?bar=baz&amp;inga=42&amp;quux',
+  'http://✪df.ws/123',
+  'http://userid:password@example.com:8080',
+  'http://userid:password@example.com:8080/',
+  'http://userid@example.com',
+  'http://userid@example.com/',
+  'http://userid@example.com:8080',
+  'http://userid@example.com:8080/',
+  'http://userid:password@example.com',
+  'http://userid:password@example.com/',
+  'http://142.42.1.1/',
+  'http://142.42.1.1:8080/',
+  'http://➡.ws/䨹',
+  'http://⌘.ws',
+  'http://⌘.ws/',
+  'http://foo.com/blah_(wikipedia)#cite-1',
+  'http://foo.com/blah_(wikipedia)_blah#cite-1',
+  'http://foo.com/unicode_(✪)_in_parens',
+  'http://foo.com/(something)?after=parens',
+  'http://☺.damowmow.com/',
+  'http://code.google.com/events/#&amp;product=browser',
+  'http://j.mp',
+  'ftp://foo.bar/baz',
+  'http://foo.bar/?q=Test%20URL-encoded%20stuff',
+  'http://مثال.إختبار',
+  'http://例子.测试',
+  'http://उदाहरण.परीक्षा',
+  'http://-.~_!$&amp;\'()*+,;=:%40:80%2f::::::@example.com',
+  'http://1337.net',
+  'http://a.b-c.de',
+  'http://223.255.255.254',
+  // Also want to validate data-uris, localhost
+  'http://localhost:8432/some-file.js',
+  'data:text/plain;base64,',
+  'data:text/html;charset=US-ASCII,%3Ch1%3EHello!%3C%2Fh1%3E',
+  'data:text/html;charset=utf-8,'
+  ];
+}
+
+// Some invalidURIs are valid according to the regex used,
+// can be improved in the future, but better to pass some
+// invalid URLs than prevent valid URLs
+
+function invalidURIs () {
+  return [
+//  'http://',
+//  'http://.',
+//  'http://..',
+//  'http://../',
+//  'http://?',
+//  'http://??',
+//  'http://??/',
+//  'http://#',
+//  'http://##',
+//  'http://##/',
+//  'http://foo.bar?q=Spaces should be encoded',
+  'not a url',
+  '//',
+  '//a',
+  '///a',
+  '///',
+//  'http:///a',
+  'foo.com',
+  'http:// shouldfail.com',
+  ':// should fail',
+//  'http://foo.bar/foo(bar)baz quux',
+//  'http://-error-.invalid/',
+//  'http://a.b--c.de/',
+//  'http://-a.b.co',
+//  'http://a.b-.co',
+//  'http://0.0.0.0',
+//  'http://10.1.1.0',
+//  'http://10.1.1.255',
+//  'http://224.1.1.1',
+//  'http://1.1.1.1.1',
+//  'http://123.123.123',
+//  'http://3628126748',
+//  'http://.www.foo.bar/',
+//  'http://www.foo.bar./',
+//  'http://.www.foo.bar./',
+//  'http://10.1.1.1',
+//  'http://10.1.1.254'
+  ];
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/test-window-events.js
@@ -0,0 +1,56 @@
+/* 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 { Loader } = require("sdk/test/loader");
+const { open, getMostRecentBrowserWindow, getOuterId } = require("sdk/window/utils");
+
+exports["test browser events"] = function(assert, done) {
+  let loader = Loader(module);
+  let { events } = loader.require("sdk/window/events");
+  let { on, off } = loader.require("sdk/event/core");
+  let actual = [];
+
+  on(events, "data", function handler(e) {
+    actual.push(e);
+    if (e.type === "load") window.close();
+    if (e.type === "close") {
+      let [ open, ready, load, close ] = actual;
+      assert.equal(open.type, "open")
+      assert.equal(open.target, window, "window is open")
+
+      assert.equal(ready.type, "DOMContentLoaded")
+      assert.equal(ready.target, window, "window ready")
+
+      assert.equal(load.type, "load")
+      assert.equal(load.target, window, "window load")
+
+      assert.equal(close.type, "close")
+      assert.equal(close.target, window, "window load")
+
+      // Note: If window is closed right after this GC won't have time
+      // to claim loader and there for this listener. It's better to remove
+      // remove listener here to avoid race conditions.
+      off(events, "data", handler);
+      loader.unload();
+      done();
+    }
+  });
+
+  // Open window and close it to trigger observers.
+  let window = open();
+};
+
+if (require("sdk/system/xul-app").is("Fennec")) {
+  module.exports = {
+    "test Unsupported Test": function UnsupportedTest (assert) {
+        assert.pass(
+          "Skipping this test until Fennec support is implemented." +
+          "See bug 793071");
+    }
+  }
+}
+
+require("test").run(exports);
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -384,21 +384,24 @@ pref("dom.sms.strict7BitEncoding", false
 
 // Temporary permission hack for WebContacts
 pref("dom.mozContacts.enabled", true);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", true);
 
 // SimplePush
+pref("services.push.enabled", true);
 // serverURL to be assigned by services team
 pref("services.push.serverURL", "");
 pref("services.push.userAgentID", "");
 // exponential back-off start is 5 seconds like in HTTP/1.1
 pref("services.push.retryBaseInterval", 5000);
+// WebSocket level ping transmit interval in seconds.
+pref("services.push.websocketPingInterval", 55);
 // exponential back-off end is 20 minutes
 pref("services.push.maxRetryInterval", 1200000);
 // How long before a DOMRequest errors as timeout
 pref("services.push.requestTimeout", 10000);
 // enable udp wakeup support
 pref("services.push.udp.wakeupEnabled", true);
 // port on which UDP server socket is bound
 pref("services.push.udp.port", 2442);
@@ -663,8 +666,13 @@ pref("memory_info_dumper.watch_fifo.enab
 pref("memory_info_dumper.watch_fifo.directory", "/data/local");
 
 pref("general.useragent.enable_overrides", true);
 
 pref("b2g.version", @MOZ_B2G_VERSION@);
 
 // Disable console buffering to save memory.
 pref("consoleservice.buffered", false);
+
+#ifdef MOZ_WIDGET_GONK
+// Performance testing suggests 2k is a better page size for SQLite.
+pref("toolkit.storage.pageSize", 2048);
+#endif
\ No newline at end of file
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -46,17 +46,17 @@
 static void Output(const char *fmt, ... )
 {
   va_list ap;
   va_start(ap, fmt);
 
 #if defined(XP_WIN) && !MOZ_WINCONSOLE
   PRUnichar msg[2048];
   _vsnwprintf(msg, sizeof(msg)/sizeof(msg[0]), NS_ConvertUTF8toUTF16(fmt).get(), ap);
-  MessageBoxW(NULL, msg, L"XULRunner", MB_OK | MB_ICONERROR);
+  MessageBoxW(nullptr, msg, L"XULRunner", MB_OK | MB_ICONERROR);
 #else
   vfprintf(stderr, fmt, ap);
 #endif
 
   va_end(ap);
 }
 
 /**
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -917,17 +917,17 @@ let IndexedDBPromptHelper = {
 
   init:
   function IndexedDBPromptHelper_init() {
     Services.obs.addObserver(this, this._quotaPrompt, false);
   },
 
   uninit:
   function IndexedDBPromptHelper_uninit() {
-    Services.obs.removeObserver(this, this._quotaPrompt, false);
+    Services.obs.removeObserver(this, this._quotaPrompt);
   },
 
   observe:
   function IndexedDBPromptHelper_observe(subject, topic, data) {
     if (topic != this._quotaPrompt) {
       throw new Error("Unexpected topic!");
     }
 
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -9,16 +9,19 @@ const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
   "@mozilla.org/childprocessmessagemanager;1", "nsIMessageSender");
 
+XPCOMUtils.defineLazyServiceGetter(this, "tm",
+  "@mozilla.org/thread-manager;1", "nsIThreadManager");
+
 // -----------------------------------------------------------------------
 // MozKeyboard
 // -----------------------------------------------------------------------
 
 function MozKeyboard() { }
 
 MozKeyboard.prototype = {
   classID: Components.ID("{397a7fdf-2254-47be-b74e-76625a1a66d5}"),
@@ -67,19 +70,29 @@ MozKeyboard.prototype = {
     this._window = null;
     this._utils = null;
     this._focusHandler = null;
     this._selectionHandler = 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));
+
+    let mainThread = tm.mainThread;
+    let utils = this._utils;
+
+    function send(type) {
+      mainThread.dispatch(function() {
+	utils.sendKeyEvent(type, keyCode, charCode, null);
+      }, mainThread.DISPATCH_NORMAL);
+    }
+
+    send("keydown");
+    send("keypress");
+    send("keyup");
   },
 
   setSelectedOption: function mozKeyboardSetSelectedOption(index) {
     cpmm.sendAsyncMessage('Keyboard:SetSelectedOption', {
       'index': index
     });
   },
 
--- a/b2g/config/panda/releng-pandaboard.tt
+++ b/b2g/config/panda/releng-pandaboard.tt
@@ -1,12 +1,12 @@
 [
 {
-"size": 677944136,
-"digest": "229b264aefa4831c7b0498097c87ae9a33baaa0ad3680b54263f4d9c8008f91bf031261f740d11259921c2805f4707cfa5f3d977e38b83c7b221b6617af8a3b1",
+"size": 678095100,
+"digest": "79cf8ecf3c8faa18c4f485eed5f611fdaea25585f2ab3203eb912185c644179708b283c6222661006c145fa67d18e39c28fdf76ebe971ef5e0fbaf348f16a1ac",
 "algorithm": "sha512",
 "filename": "gonk.tar.xz"
 },
 {
 "size": 2116507,
 "digest": "be67a012963a5c162834f9fcb989bcebd2d047dcb4e17ee23031b694dcf7cdfd6d7a6545d7a1f5e7293b6d24415403972f4ea1ab8c6c78fefcabfaf3f6875214",
 "algorithm": "sha512",
 "filename": "download-panda.tar.bz2"
--- a/b2g/config/panda/sources.xml
+++ b/b2g/config/panda/sources.xml
@@ -10,79 +10,79 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
 
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="c647d5f967a5f17aaa27c792ea0ee35a2d44b113">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <!-- Information: fake-dalvik is tagged with B2G_1_0_0_20130125190500 --><project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9429d142f7f46add49f4665ce81ac0c0416dd9c1"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5f073eb845698119b729af991a6dd0325586487d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="f634b3d50effdd42828cc757c01fdbf74e562a36"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="302ab954f16d0ad708e87a1cf5e94f5d93f174c9"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="3769dfb6566897c8dca0abdc596728602d5fabae"/>
 
   <!-- Stock Android things -->
-  <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
+  <!-- Information: platform/abi/cpp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="c7bab8cb8483e7869eabdbd4add7c9e5beeecc80"/>
   <!-- Information: platform/bootable/recovery is tagged with android-4.0.4_r2.1 --><project name="platform/bootable/recovery" path="bootable/recovery" revision="fadc5ac81d6400ebdd041f7d4ea64021596d6b7d"/>
   <!-- Information: device/common is tagged with android-sdk-adt_r20 --><project name="device/common" path="device/common" revision="7d4526582f88808a3194e1a3b304abb369d2745c"/>
   <!-- Information: device/sample is tagged with android-4.0.4_r2.1 --><project name="device/sample" path="device/sample" revision="ef228b8b377a9663e94be4b1aeb6c2bf7a07d098"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="2c3a7113299eb789a076be23449d868b3bfa07fd"/>
   <!-- Information: platform/external/bluetooth/bluez is tagged with android-4.0.4_r2.1 --><project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="966afbd88f0bfc325bf80274ad2723c238883fa1"/>
   <!-- Information: platform/external/bluetooth/glib is tagged with android-cts-4.1_r2 --><project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="1143b9918eab068401b604eb11c3f651f4e38b25"/>
   <!-- Information: platform/external/bluetooth/hcidump is tagged with android-cts-4.1_r2 --><project name="platform/external/bluetooth/hcidump" path="external/bluetooth/hcidump" revision="7322661808c2006b7848e79e6bb72b37fbcf6710"/>
-  <!-- Information: platform/external/bsdiff is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/>
+  <!-- Information: platform/external/bsdiff is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/bsdiff" path="external/bsdiff" revision="81872540236d9bb15cccf963d05b9de48baa5375"/>
   <project name="platform/external/busybox" path="external/busybox" remote="linaro" revision="2e461c8029a50d986dfe4ab07ae5a1834b5c40f0"/>
-  <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/>
+  <!-- Information: platform/external/bzip2 is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/bzip2" path="external/bzip2" revision="048dacdca43eed1534689ececcf2781c63e1e4ba"/>
   <!-- Information: platform/external/dbus is tagged with android-cts-4.1_r2 --><project name="platform/external/dbus" path="external/dbus" revision="537eaff5de9aace3348436166d4cde7adc1e488e"/>
   <!-- Information: platform/external/dhcpcd is tagged with android-sdk-adt_r20 --><project name="platform/external/dhcpcd" path="external/dhcpcd" revision="ddaa48f57b54b2862b3e6dcf18a44c9647f3baaa"/>
-  <!-- Information: platform/external/dnsmasq is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/>
+  <!-- Information: platform/external/dnsmasq is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/dnsmasq" path="external/dnsmasq" revision="f621afad94df46204c25fc2593a19d704d2637f5"/>
   <project name="platform_external_elfcopy" path="external/elfcopy" remote="b2g" revision="62c1bed1c4505369cac2e72fbe30452a598fb690"/>
   <project name="platform_external_elfutils" path="external/elfutils" remote="b2g" revision="72940dec691fa3255e13df01f8c53b620e446066"/>
-  <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/>
-  <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/>
-  <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
-  <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
-  <!-- Information: platform/external/giflib is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/>
+  <!-- Information: platform/external/expat is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/expat" path="external/expat" revision="6df134250feab71edb5915ecaa6268210bca76c5"/>
+  <!-- Information: platform/external/fdlibm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/fdlibm" path="external/fdlibm" revision="988ffeb12a6e044ae3504838ef1fee3fe0716934"/>
+  <!-- Information: platform/external/flac is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/flac" path="external/flac" revision="5893fbe890f5dab8e4146d2baa4bd2691c0739e0"/>
+  <!-- Information: platform/external/freetype is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/freetype" path="external/freetype" revision="aeb407daf3711a10a27f3bc2223c5eb05158076e"/>
+  <!-- Information: platform/external/giflib is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/giflib" path="external/giflib" revision="b2597268aef084202a8c349d1cc072c03c6e22eb"/>
   <project name="platform/external/gtest" path="external/gtest" revision="8c212ebe53bb2baab3575f03069016f1fb11e449"/>
   <!-- Information: platform/external/harfbuzz is tagged with android-sdk-adt_r20 --><project name="platform/external/harfbuzz" path="external/harfbuzz" revision="bae491c03a00757d83ede8d855b7d85d246bde3d"/>
   <!-- icu4c is missing the default tag in caf, that's the *only* reason for the hardcode -->
-  <!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/>
-  <!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/>
-  <!-- Information: platform/external/jhead is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/jhead" path="external/jhead" revision="754078052c687f6721536009c816644c73e4f145"/>
+  <!-- Information: platform/external/icu4c is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/icu4c" path="external/icu4c" revision="0fa67b93b831c6636ca18b152a1b1b14cc99b034"/>
+  <!-- Information: platform/external/iptables is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/iptables" path="external/iptables" revision="3b2deb17f065c5664bb25e1a28489e5792eb63ff"/>
+  <!-- Information: platform/external/jhead is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/jhead" path="external/jhead" revision="754078052c687f6721536009c816644c73e4f145"/>
   <!-- Information: platform/external/jpeg is tagged with android-cts-4.1_r2 --><project name="platform/external/jpeg" path="external/jpeg" revision="d4fad7f50f79626455d88523207e05b868819cd8"/>
-  <!-- Information: platform/external/libgsm is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/>
-  <!-- Information: platform/external/liblzf is tagged with AU_LINUX_ANDROID_JB_MR1.04.02.02.49.187 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
+  <!-- Information: platform/external/libgsm is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/libgsm" path="external/libgsm" revision="5e4516958690b9a1b2c98f88eeecba3edd2dbda4"/>
+  <!-- Information: platform/external/liblzf is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/liblzf" path="external/liblzf" revision="6946aa575b0949d045722794850896099d937cbb"/>
   <!-- Information: platform/external/libnfc-nxp is tagged with android-4.0.4_r2.1 --><project name="platform/external/libnfc-nxp" path="external/libnfc-nxp" revision="533c14450e6239cce8acb74f4e4dea2c89f8f219"/>
-  <!-- Information: platform/external/libnl-headers is tagged with AU_LINUX_ANDROID_JB_MR1.04.02.02.49.187 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
+  <!-- Information: platform/external/libnl-headers is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/libnl-headers" path="external/libnl-headers" revision="6ccf7349d61f73ac26a0675d735d903ab919c658"/>
   <!-- Information: platform/external/libpng is tagged with android-4.0.4_r2.1 --><project name="platform/external/libpng" path="external/libpng" revision="84d92c718ab9f48faec0f640747c4b6f7a995607"/>
-  <!-- Information: platform/external/libvpx is tagged with M8960AAAAANLYA1519349 --><project name="platform/external/libvpx" path="external/libvpx" revision="3a40da0d96da5c520e7707aa14f48a80956e20d7"/>
+  <!-- Information: platform/external/libvpx is tagged with AU_LINUX_ANDROID_ICS_STRAWBERRY_RB5.04.00.04.29.023 --><project name="platform/external/libvpx" path="external/libvpx" revision="3a40da0d96da5c520e7707aa14f48a80956e20d7"/>
   <!-- Information: platform/external/mksh is tagged with M8960AAAAANLYA1099D --><project name="platform/external/mksh" path="external/mksh" revision="5155f1c7438ef540d7b25eb70aa1639579795b07"/>
   <!-- Information: platform_external_opensans is tagged with B2G_1_0_0_20130125190500 --><project name="platform_external_opensans" path="external/opensans" remote="b2g" revision="b5b4c226ca1d71e936153cf679dda6d3d60e2354"/>
   <!-- Information: platform/external/openssl is tagged with android-4.0.4_r2.1 --><project name="platform/external/openssl" path="external/openssl" revision="ce96fb211b9a44bbd7fb5ef7ed0e6c1244045c2e"/>
-  <!-- Information: platform/external/protobuf is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/>
-  <!-- Information: platform/external/safe-iop is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/>
+  <!-- Information: platform/external/protobuf is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/protobuf" path="external/protobuf" revision="e217977611c52bccde7f7c78e1d3c790c6357431"/>
+  <!-- Information: platform/external/safe-iop is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/safe-iop" path="external/safe-iop" revision="07073634e2e3aa4f518e36ed5dec3aabc549d5fb"/>
   <!-- Information: screencap-gonk is tagged with B2G_1_0_0_20130125190500 --><project name="screencap-gonk" path="external/screencap-gonk" remote="b2g" revision="e6403c71e9eca8cb943739d5a0a192deac60fc51"/>
   <!-- Information: platform/external/skia is tagged with android-4.0.4_r2.1 --><project name="platform/external/skia" path="external/skia" revision="5c67a309e16bffe7013defda8f1217b3ce2420b4"/>
   <!-- Information: platform/external/sonivox is tagged with android-sdk-adt_r20 --><project name="platform/external/sonivox" path="external/sonivox" revision="5f9600971859fe072f31b38a51c38157f5f9b381"/>
-  <!-- Information: platform/external/speex is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/>
+  <!-- Information: platform/external/speex is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/speex" path="external/speex" revision="ebe6230a7f7c69f5a4389f2b09b7b19ef9e94f32"/>
   <!-- Information: platform/external/sqlite is tagged with android-4.0.4_r2.1 --><project name="platform/external/sqlite" path="external/sqlite" revision="c999ff8c12a4cf81cb9ad628f47b2720effba5e5"/>
-  <!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/>
-  <!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/>
-  <!-- Information: platform/external/tagsoup is tagged with AU_LINUX_ANDROID_JB_MR1.04.02.02.49.187 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
+  <!-- Information: platform/external/stlport is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/stlport" path="external/stlport" revision="a6734e0645fce81c9610de0488b729207bfa576e"/>
+  <!-- Information: platform/external/strace is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/strace" path="external/strace" revision="c9fd2e5ef7d002e12e7cf2512506c84a9414b0fd"/>
+  <!-- Information: platform/external/tagsoup is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/tagsoup" path="external/tagsoup" revision="68c2ec9e0acdb3214b7fb91dbab8c9fab8736817"/>
   <!-- Information: platform/external/tinyalsa is tagged with android-4.0.4_r2.1 --><project name="platform/external/tinyalsa" path="external/tinyalsa" revision="495239e683a728957c890c124b239f9b7b8ef5a8"/>
-  <!-- Information: platform/external/tremolo is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/>
-  <!-- Information: platform/external/webp is tagged with AU_LINUX_ANDROID_JB_REL_2.0.3.04.01.02.21.123 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/>
+  <!-- Information: platform/external/tremolo is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/tremolo" path="external/tremolo" revision="25bd78d2392dbdc879ae53382cde9d019f79cf6f"/>
+  <!-- Information: platform/external/webp is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/webp" path="external/webp" revision="88fe2b83c4b9232cd08729556fd0485d6a6a92cd"/>
   <!-- Information: platform/external/webrtc is tagged with android-sdk-adt_r20 --><project name="platform/external/webrtc" path="external/webrtc" revision="4b6dc1ec58105d17dc8c2f550124cc0621dc93b7"/>
-  <!-- Information: platform/external/wpa_supplicant is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/>
+  <!-- Information: platform/external/wpa_supplicant is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/external/wpa_supplicant" path="external/wpa_supplicant" revision="a01d37870bbf9892d43e792e5de0683ca41c5497"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="6dd24fc3792d71edccef9b09140f9a44b063a553"/>
   <!-- Information: platform/external/zlib is tagged with android-4.0.4_r2.1 --><project name="platform/external/zlib" path="external/zlib" revision="69e5801bd16a495e1c1666669fe827b1ddb8d56b"/>
   <!-- Information: platform/external/yaffs2 is tagged with android-4.0.4-aah_r1 --><project name="platform/external/yaffs2" path="external/yaffs2" revision="6232e2d5ab34a40d710e4b05ab0ec6e3727804e7"/>
   <!-- Information: platform/frameworks/base is tagged with android-4.0.4_r2.1 --><project name="platform/frameworks/base" path="frameworks/base" revision="df331873c8576e0ae34ae1ee3cc258beed373535"/>
-  <!-- Information: platform/frameworks/opt/emoji is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.035 --><project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/>
+  <!-- Information: platform/frameworks/opt/emoji is tagged with AU_LINUX_GECKO_ICS_STRAWBERRY.01.01.00.19.052 --><project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="a95d8db002770469d72dfaf59ff37ac96db29a87"/>
   <!-- Information: platform/frameworks/support is tagged with android-4.0.4_r2.1 --><project name="platform/frameworks/support" path="frameworks/support" revision="bfc8e01b7b0d5ea70ce89d0409b72b7f7d540f43"/>
   <!-- Information: platform/hardware/libhardware is tagged with android-4.0.4_r2.1 --><project name="platform/hardware/libhardware" path="hardware/libhardware" revision="a9b677fce432b29ab8f61e13796f34880dc0fe0f"/>
   <!-- Information: platform/hardware/libhardware_legacy is tagged with android-4.0.4_r2.1 --><project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="153d0f1a27e0a157cabb6ca9d0d88248630f5695"/>
   <!-- Information: platform/hardware/ril is tagged with android-4.0.4_r2.1 --><project name="platform/hardware/ril" path="hardware/ril" revision="300105d1487f5238940c18792b879793826b61f4"/>
   <!-- Information: platform/libcore is tagged with android-4.0.4_r2.1 --><project name="platform/libcore" path="libcore" revision="fc294a48d80d9e2b2ac126edf93ad316f5f6cf72"/>
   <!-- Information: platform/ndk is tagged with android-4.0.4_r2.1 --><project name="platform/ndk" path="ndk" revision="2d77f5a05f60029c981f299b222cfe28db18ccf7"/>
   <!-- Information: platform/prebuilt is tagged with tungsten-bootloader-ics-aah --><project name="platform/prebuilt" path="prebuilt" revision="0e104261b6d33f87e9f86ff4249bcc0306ab278b"/>
   <!-- Information: platform/system/bluetooth is tagged with android-4.0.4_r2.1 --><project name="platform/system/bluetooth" path="system/bluetooth" revision="2588cd802f322650ed737dfb7a10e9ad94064e99"/>
@@ -92,12 +92,12 @@
   <!-- Information: platform/system/netd is tagged with android-4.0.4_r2.1 --><project name="platform/system/netd" path="system/netd" revision="3c903b555975fa59d6688a0a6417ac7512c202e7"/>
   <!-- Information: platform/system/vold is tagged with android-4.0.4_r2.1 --><project name="platform/system/vold" path="system/vold" revision="3ad9072a5d6f6bda32123b367545649364e3c11d"/>
 
   <!-- Pandaboard specific things -->
   <project name="android-device-panda" path="device/ti/panda" remote="b2g" revision="b0cde710220dc884fbf92934a4d54456ecc0c693"/>
   <!-- Information: platform/hardware/ti/omap4xxx is tagged with android-4.0.4_r2.1 --><project name="platform/hardware/ti/omap4xxx" path="hardware/ti/omap4xxx" revision="8be8e9a68c96b6cf43c08a58e7ecd7708737c599"/>
   <project name="platform/hardware/ti/wlan" path="hardware/ti/wlan" revision="60dfeb6e4448bfed707946ebca6612980f525e69"/>
   <project name="platform/hardware/ti/wpan" path="hardware/ti/wpan" revision="3ece7d9e08052989401e008bc397dbcd2557cfd0"/>
-  <project name="Negatus" path="external/negatus" remote="mozilla" revision="83e11def08ae4bc590adda8dfc1de661585adb53"/>
+  <project name="Negatus" path="external/negatus" remote="mozilla" revision="5009c0738def17e68855b1c7084fd38ac8fd7545"/>
   <project name="orangutan" path="external/orangutan" remote="b2g" revision="1735c3c4d6008d7f9e929d55ed0e06b995156fa2"/>
 
 </manifest>
\ No newline at end of file
--- a/b2g/gaia/run-b2g.cpp
+++ b/b2g/gaia/run-b2g.cpp
@@ -14,61 +14,61 @@
 #ifndef B2G_NAME
 #define B2G_NAME L"b2g.exe"
 #endif
 #ifndef GAIA_PATH
 #define GAIA_PATH L"gaia\\profile"
 #endif
 
 void error(wchar_t* msg){
-    MessageBoxW(NULL, msg, L"Error starting program", MB_OK | MB_ICONERROR);
+    MessageBoxW(nullptr, msg, L"Error starting program", MB_OK | MB_ICONERROR);
 }
 
 /* This function takes a string which represents a windows path, orig.
  * The file portion of the path is stripped off and replaced with the
  * path component, file.  This function returns a string which represents
  * a windows path with the modifications requested and needs to be freed
  * explicitly by the calling function.
  */
 wchar_t* make_path_with_leaf_file_name(wchar_t* orig, wchar_t* file){
     wchar_t* buffer = (wchar_t*) malloc(NUM_MAX_PATH_BYTES);
     if (!buffer) {
-        return NULL;
+        return nullptr;
     }
     if (FAILED(StringCchCopyW(buffer, NUM_MAX_PATH_BYTES, orig))) {
         error(L"Error copying string");
         free(buffer);
-        buffer = NULL;
+        buffer = nullptr;
     }
     PathRemoveFileSpecW(buffer);
     if (!PathAppendW(buffer, file)) {
         error(L"Unable to append file to directory");
         free(buffer);
-        buffer = NULL;
+        buffer = nullptr;
     }
     return buffer;
 }
 
 BOOL execute(wchar_t* binary_path, wchar_t* args, int cp_flags) {
     STARTUPINFOW si;
     PROCESS_INFORMATION pi;
 
     ZeroMemory(&si, sizeof(si));
     si.cb = sizeof(si);
     ZeroMemory(&pi, sizeof(pi));
     
     if (!CreateProcessW(
         binary_path,
         args,
-        NULL,
-        NULL,
+        nullptr,
+        nullptr,
         FALSE,
         cp_flags,
-        NULL,
-        NULL,
+        nullptr,
+        nullptr,
         &si,
         &pi)){
             error(L"Could not execute program");
             return FALSE;
     }
 
     WaitForInputIdle(pi.hProcess, 0);
     CloseHandle(pi.hProcess);
@@ -92,11 +92,11 @@ int wmain(int argc, wchar_t *argv[], wch
     cp_flags = DETACHED_PROCESS;
 #endif
     if (!execute(b2g_path, args, cp_flags)) {
         error(L"Failed to launch program");
     }
     free(profile_path);
     free(b2g_path);
     free(args);
-    profile_path = b2g_path = args = NULL;
+    profile_path = b2g_path = args = nullptr;
     
 }
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -209,17 +209,17 @@
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_mobilemessage.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_views.xpt
 #ifdef MOZ_WEBSPEECH
-@BINPATH@/components/dom_webspeech.xpt
+@BINPATH@/components/dom_webspeechrecognition.xpt
 #endif
 @BINPATH@/components/dom_xbl.xpt
 @BINPATH@/components/dom_xpath.xpt
 @BINPATH@/components/dom_xul.xpt
 @BINPATH@/components/dom_time.xpt
 @BINPATH@/components/downloads.xpt
 @BINPATH@/components/editor.xpt
 @BINPATH@/components/embed_base.xpt
@@ -746,16 +746,20 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 @BINPATH@/components/YoutubeProtocolHandler.js
 @BINPATH@/components/RecoveryService.js
 @BINPATH@/components/MailtoProtocolHandler.js
 @BINPATH@/components/SmsProtocolHandler.js
 @BINPATH@/components/TelProtocolHandler.js
 @BINPATH@/components/B2GAboutRedirector.js
 @BINPATH@/components/FilePicker.js
 
+#ifdef MOZ_WEBSPEECH
+@BINPATH@/components/dom_webspeechsynth.xpt
+#endif
+
 #ifdef XP_MACOSX
 @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
 #endif
 
 #ifdef PACKAGE_GAIA
 [gaia]
 @BINPATH@/gaia/*
 @BINPATH@/b2g-bin@BIN_SUFFIX@
--- a/b2g/installer/removed-files.in
+++ b/b2g/installer/removed-files.in
@@ -6,16 +6,17 @@ run-mozilla.sh
 #endif
 #ifdef XP_WIN
   mozcrt19.dll
   mozcpp19.dll
 #endif
 defaults/preferences/services-sync.js
 defaults/preferences/healthreport-prefs.js
 components/dom_sms.xpt
+components/dom_webspeech.xpt
 #ifdef MOZ_FOLD_LIBS
 @DLL_PREFIX@nspr4@DLL_SUFFIX@
 @DLL_PREFIX@plds4@DLL_SUFFIX@
 @DLL_PREFIX@plc4@DLL_SUFFIX@
 @DLL_PREFIX@ssl3@DLL_SUFFIX@
 @DLL_PREFIX@smime3@DLL_SUFFIX@
 @DLL_PREFIX@nssutil3@DLL_SUFFIX@
 @DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/components/TestPilot.js
@@ -24,17 +24,17 @@ TestPilotComponent.prototype = {
         getService(Ci.nsIObserverService);
     switch (topic) {
     case "profile-after-change":
       os.addObserver(this, "sessionstore-windows-restored", true);
       break;
     case "sessionstore-windows-restored":
       /* Stop oberver, to ensure that globalStartup doesn't get
        * called more than once. */
-      os.removeObserver(this, "sessionstore-windows-restored", false);
+      os.removeObserver(this, "sessionstore-windows-restored");
       /* Call global startup on a timer so that it's off of the main
        * thread... delay a few seconds to give firefox time to finish
        * starting up.
        */
       this._startupTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
       this._startupTimer.initWithCallback(
         {notify: function(timer) {
            Cu.import("resource://testpilot/modules/setup.js");
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback.css
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/linux/feedback.css
@@ -1,17 +1,17 @@
 /* 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/. */
 
 #pilot-notification-popup {
   -moz-appearance: none;
   border-image: none;
   background-color: Menu;
-  background-image: -moz-linear-gradient(hsla(0,0%,100%,.2), transparent);
+  background-image: linear-gradient(hsla(0,0%,100%,.2), transparent);
   box-shadow: inset 0 0 7px hsla(0,0%,100%,.2),
                    inset 0 1px 0 hsla(0,0%,100%,.3);
   border-radius: 4px;
   border: 1px solid Menu;
   margin: -6px 0 0 0;
   width: 480px;
 }
 
--- a/browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback.css
+++ b/browser/app/profile/extensions/testpilot@labs.mozilla.com/skin/mac/feedback.css
@@ -2,31 +2,31 @@
  * 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/. */
 
 /* Submit Button Style */
 
 #pilot-notification-submit {
   -moz-appearance: none;
   background: #666
-              -moz-linear-gradient(rgba(110,110,110,.9), rgba(70,70,70,.9) 49%,
-                                   rgba(60,60,60,.9) 51%, rgba(50,50,50,.9));
+              linear-gradient(rgba(110,110,110,.9), rgba(70,70,70,.9) 49%,
+                              rgba(60,60,60,.9) 51%, rgba(50,50,50,.9));
   background-clip: padding-box;
   background-origin: padding-box;
   border-radius: 12px;
   border: 1px solid rgba(0,0,0,.65);
   box-shadow: inset 0 1px 0 rgba(255,255,255,.2),
                    inset 0 0 1px rgba(255,255,255,.1),
                    0 1px 0 rgba(255,255,255,.1);
   color: #fff;
   text-shadow: 0 -1px 0 rgba(0,0,0,.5);
 }
 
 #pilot-notification-submit:hover:active {
-  background: -moz-linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9));
+  background: linear-gradient(rgba(40,40,40,.9), rgba(70,70,70,.9));
   box-shadow: inset 0 0 2px rgba(0,0,0,.2),
                    inset 0 1px 5px rgba(0,0,0,.4),
                    0 1px 0 rgba(255,255,255,.1);
 }
 
 /* Text Colors */
 
 .pilot-notification-popup-container {
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -396,17 +396,16 @@ pref("browser.link.open_newwindow.restri
 // Disable opening a new window via window.open if browser is in fullscreen mode
 #ifdef XP_MACOSX
 pref("browser.link.open_newwindow.disabled_in_fullscreen", true);
 #else
 pref("browser.link.open_newwindow.disabled_in_fullscreen", false);
 #endif
 
 // Tabbed browser
-pref("browser.tabs.autoHide", false);
 pref("browser.tabs.closeWindowWithLastTab", true);
 pref("browser.tabs.insertRelatedAfterCurrent", true);
 pref("browser.tabs.warnOnClose", true);
 pref("browser.tabs.warnOnCloseOtherTabs", true);
 pref("browser.tabs.warnOnOpen", true);
 pref("browser.tabs.maxOpenBeforeWarn", 15);
 pref("browser.tabs.loadInBackground", true);
 pref("browser.tabs.opentabfor.middleclick", true);
@@ -970,17 +969,16 @@ pref("services.sync.prefs.sync.browser.l
 pref("services.sync.prefs.sync.browser.offline-apps.notify", true);
 pref("services.sync.prefs.sync.browser.safebrowsing.enabled", true);
 pref("services.sync.prefs.sync.browser.safebrowsing.malware.enabled", true);
 pref("services.sync.prefs.sync.browser.search.selectedEngine", true);
 pref("services.sync.prefs.sync.browser.search.update", true);
 pref("services.sync.prefs.sync.browser.sessionstore.restore_on_demand", true);
 pref("services.sync.prefs.sync.browser.startup.homepage", true);
 pref("services.sync.prefs.sync.browser.startup.page", true);
-pref("services.sync.prefs.sync.browser.tabs.autoHide", true);
 pref("services.sync.prefs.sync.browser.tabs.closeButtons", true);
 pref("services.sync.prefs.sync.browser.tabs.loadInBackground", true);
 pref("services.sync.prefs.sync.browser.tabs.warnOnClose", true);
 pref("services.sync.prefs.sync.browser.tabs.warnOnOpen", true);
 pref("services.sync.prefs.sync.browser.urlbar.autocomplete.enabled", true);
 pref("services.sync.prefs.sync.browser.urlbar.default.behavior", true);
 pref("services.sync.prefs.sync.browser.urlbar.maxRichResults", true);
 pref("services.sync.prefs.sync.dom.disable_open_during_load", true);
@@ -1074,16 +1072,22 @@ pref("devtools.debugger.ui.pause-on-exce
 pref("devtools.debugger.ui.panes-visible-on-startup", false);
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-only-enum-visible", false);
 pref("devtools.debugger.ui.variables-searchbox-visible", false);
 
 // Enable the Profiler
 pref("devtools.profiler.enabled", true);
 
+// Enable the Network Monitor
+pref("devtools.netmonitor.enabled", true);
+
+// The default Network Monitor UI settings
+pref("devtools.netmonitor.panes-network-details-width", 450);
+
 // Enable the Tilt inspector
 pref("devtools.tilt.enabled", true);
 pref("devtools.tilt.intro_transition", true);
 pref("devtools.tilt.outro_transition", true);
 
 // Enable the Scratchpad tool.
 pref("devtools.scratchpad.enabled", true);
 
@@ -1199,36 +1203,40 @@ pref("pdfjs.previousHandler.preferredAct
 pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bug 746055.)
 pref("image.mem.max_decoded_image_kb", 256000);
 
 // Default social providers
-pref("social.manifest.facebook", "{\"origin\":\"https://www.facebook.com\",\"name\":\"Facebook Messenger\",\"workerURL\":\"https://www.facebook.com/desktop/fbdesktop2/socialfox/fbworker.js.php\",\"iconURL\":\"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAX0lEQVQ4jWP4%2F%2F8%2FAyUYTFhHzjgDxP9JxGeQDSBVMxgTbUBCxer%2Fr999%2BQ8DJBuArJksA9A10s8AXIBoA0B%2BR%2FY%2FjD%2BEwoBoA1yT5v3PbdmCE8MAshhID%2FUMoDgzUYIBj0Cgi7ar4coAAAAASUVORK5CYII%3D\",\"sidebarURL\":\"https://www.facebook.com/desktop/fbdesktop2/?socialfox=true\",\"icon32URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADbklEQVRYCc1Xv08UQRj99tctexAuCEFjRE0kGBEtLDSGqIWNxkYKbTAxNlY2JhaGWltNtNFeKgsKKxITK43/gCYW+IsoRhA4D47bH7fn9+bcvdm5JR7sefolC3Ozu9978+bNN7PayUv3HN3umdY0Y6IWBtSJ0HSTarXqTOiuTep6Lj+tdxAcA8RAgSmwdd2aCDs0clldYALb/FvgYVhjmfliVA2XpjEgWo0Attn42Z6WH1RFor5ehwo9XQIUZMoVn4qlCoVMSo62EvD8Kh0b3U2Xz43R2PBO6mUCGDlAf65V6MadZzT/rUimoccc2kYA4BfPHqJb105RzjJigKhRq9kEJUBIjgYVuXeL7SAI6eD+Abp5dTwVHOmEHxT50d8WBYJqSOdPj5BjW8gZR8UNqFR2xagx/65XFYaMH+BGWwiYpi4UkBPPLxTp9v1Z+lHc4DWvCQXWmIy6EjITgKowVd5Jjv7N3Hd6y5esigoOwpkJIAmMpZpLJGdiaaC4F0UmAj6bD84GCEwmB/qxMmRilmnwb/mpjAocHh4UEoNAt5NLZB7oy9OJo0PxqkAtePdhiSqunyC1LQUwWMPQaOr6GRre258Ajn4cP7KHcEXhsxpXbj+lT19X2TMNGTLVAcjcalS8gDwsQ2UOMhH4k8FkcrEn5E5ub2sKohxLK2VR77Hl9RUcsrgeRIEiVOT6z+tDbIeLy+vk+kGTCbXxycet6xhl//3f6bJEkdHYhA+mLtDIvoH4ieev5+juoxdk5+pjhALYEdXIpEB5w+NlSKSzqVQ/+H7IO6BLtl3fngGMiqhGJgIwlM6qpyUGFjySdk8m0Zg0ubeD7X9OIDEFajltRQgUJaUKx69tdgaQa0FMADuahZPMFtcEwNPm2hA7ZI5sK4aoE2NvYI+o8hkCIe7CwTv68zS0q9Dk5vpbm/8FXxitSzmMFHpsGj0wyLUheTwD2Y9fVgh1Ae0EPUgD9241ZEnld+v5kgnVZ/8fE0brVh5BK+1oCqKKF72Dk7HwBsssB/pklU1dfChy3S659H5+uelgIb+8WRv1/uGTV9Sdb5wJFlfW6fPCalMhwhSU1j2xKwKbP838GcOwJja4TqO0bjdmXxYTy1EYjFdCWoCEYZhseH/GDL3yJPHnuW6YmT7P1SlIA4768Hke4vOcsX8BE346lLHhDUQAAAAASUVORK5CYII=\", \"icon64URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAACNNJREFUeNrtm3tw1NUVxz/399hHHkgCaCBGEFEEREVFYFQcSoOKdkZay4z+4dDpYIsjHWx1WoTMhFi1gzBSpVgVGbU4U1sHfPESKODwEEnRYDFAICEIeZIQshs2u/v73ds/drMsyW7YLEkl2Z6Z32yy+9v7u+fc7znne8+5KzgvAjDunzlv0M13PjDZ6c4cARj0WhEoaZ1tOn3yq9XLf/tNU0O1D5Ad7wq/OpxpaXOL1j5uZAwuaGlVgwNBhULRm0XXBG6HZrlNa9uRrzfM+3DlgjIgGMsA7rl/XDdHOnNf9vosTfVuvTsaQhdkZ4iykh2rHtqydvkxwI58BhjTfv7MmP55E9/1nLNdfU15ACkVvoAaMCRvRPa+re9+DgTaPjMAx+DrJv3M67Mz+6LybWLb4NfTHhxzx31DDhZvOtqGAgNwWbjGICV9XQJB0e/KobcOP1i8qTzaAEYgaDtNU/V5A9hSaUFLuQEt2gVQSgml+j4CUAIppYgK/m0GkCjZ9xGAUNAu0LUhgJRAAAIVzwBSqVRQH4hlAClRKZAFhOgEASoFECBR8QwgUyQGdJT/B8HzCEiBNKhUJzEgBYIgQsTJAkohe9oFZHgHKvQoHtZ9K3tewfiixXABLdoFeuSSEmkF+PH4QTz7+M3o+ENptzvGtS36uSwmjMpAYF10XCllHCYoe84FlLS555Zs5jx6J6ahY+iCl98pJiDNS1hwSZop+cm91zJmxEBefGsPlu1AxKC67V3gf5oGlZSMuz6Dp2fdhWnoAEwaN5T5hsYLb+4hKB1dcgelFDpB8ifk8thDt3DO5+fZxRvxBV0IjQR0EB3KfD1GhJS0GZnnYuGcKTgdF9ZWx4/No/BJjUUrdtJqm4iL+K5SCmSAiWMHMevhcQzNzaa6ron5SzfQ7HeiaSKx+au4m6HupcJKSYZdZVI4dypuV2yo3zoql0VP3cOiFV/Q4jdiGkGhQFqMGpbJL346kbE3DEYIQWNTC39Ysp4Gr4HQtZDyiRhA0NlmSHZbRM7pr1H0m6lckeHqdGXG3jCYoqfupeC17bT49fNRXIFSNrkDTGbNGM9dtw1D10M1DI/Xx3NLP6OqETRdDy1eglPT4rqA7K56gCIrXfHCvHwGZqUnBMtR113FS/N+xHPLtuJpDa1mVobg0emjmX7vqEjsUErhaw1Q8Mo6yk4F0A1HeOW7kIlFx/u7jworRabLpmhuPjmD+iG7YNDrrhnIS09P5cW/buOeO67lkftvJt3tDE06PE7Qsnh++QYOHPOim86wcVUS0+whJug0ghTMmcK1V2eH8m2UHP++nrwhAyIwjiXDcrN5vXAGhqGhFBeMYUvJ0re2sPfgGTTDGUZrEogVopMgmGQWUCgMEWTBE5MZPSLngnGqas/w9j92s31fJfmThvPM7HyMMKRj+qgmOiBHSsnr73/B5r1V6A53KD4k3bFS8dNgckFQoWPxu1kTGDc6N7JqzR4ff/+smE+2H8FSLkx3FluLawhaG3n2iXwcppGoV/Hemt18tK0c3UwLIfUS2nVafBeQJNUXkAF+/dht3H37cKSUBC2bTTv+w98++YazPg1dT0NoIUhruoMd+2sJrtjI7381rQM3iCVrN33N++tL0c30xFNdp0GQeFRYQhcRIO0gv5xxE/fdfSO2bfNVSTmrPtxLZW0A3XSh6VporaLG1XQHu0pOU/TaOhY8+QAuZ3w6vHnnQd74536EkZ50wOsSE0zcugolbWZOG8GM/LGUVdSw6sM97D/UgGa60QxXzMJDZAq6yb7SJgr//CkLn5pOmsvR4Z5dxUdZ9t6XoKfFjNyXkqZjuoBUCpGgCyhp8eDdQ5k++UaWrdrMlr2VSFxoZlpE8YtNWGgGXx9ppnDZpxTMfTCS8gAOlJ5g8ds7kCItTIi6j6FqMVxAC2sV2RB1ekmLCTcNpH+myeyFH7BxT1Voopoe4RKJXQqhmxw45mXh0o/xeH0opThcXs2iv2wmoFyhAnbC4yX+3PgISMDShrA5XHGa3d9UITRniIeTfHASmsGhEz7mL/mI2TPv4sU3t+KzHAnu7JKpCosOkcSIICAB5hZE0OiRCM0Iwb0b6LPQdI5W+Zn/yucoYYayRk+16eK1xqRMDAHtA0r3lep0lNAjO8kfpCpMqpTF4xZEUqA7rIlOCiKpgADVWXc4FQwgEfHPB5AiByTixIDUCYJx+wJoqdIcJV5VOAWygEZcF7BToT2upFDKtuz2BrAtf8v3mju972cBJX2exso6ok6N64BhOtM11xXXPBz6v6340PcuO+DZfaJkzWqgqY3L64Bqaaz0ZV45Mkc308dG2kd97FLSaq4v317gazr5HeCLRoACFTxbfeBw+oDhWYYj4/rw+30H+rb/VMPxXQsbKnbuABqJOi4vogyRiRB5/XNvvz3zytFTDEf61eF9b0dCKTS36c4afymTsgLeQ9Ly13X/aYnzE1Uy6PV7679trNy1xe+tKwPqAH/0Vla0qw65gH7AFeG/Y3Uy9P45o0bm3PTIaplM6lTK9jWf/OBUyQcrpdXaTIyfsXQb9QcLaAn7vJd2vxY5XxBpo8pwDmgFGsLKx1oeh8OVmUUSLXUlrWZPzbdLag9v+BjUqfDzepKAyDDcZbznGHG+1NmqSKHpVlfbadJqLW+o2LHobNX+PUB1WPkfnHwYyTmX6lI7Lehr3F576NM/+T3V3wH17f2w1xkg2ggXuSvga6p8p+bgmpVKWpXAmVh+2AsNEKogdYYAJa0GT03J4obyf60HTgKe6PTTqw0QOpcQ3wXs4LlDZyq2FXrrS4uBmjDxuCw3G5eIgA46yeC5ho11pWsWW35PWTibBC4Xf+9eBLRPg0q2+s5UvHG6bMNqJYPHw7nXutxZYvIIiMoCSgbrPVX/fv7syS+3AKfC5MOmF4iRpP6RjrId8O5vrNhS1NpUWQLUholUr6muXEoatP3emrWNR9e/avk9R8P+HuxNypPkrk93pGdnK0VtXemaN6UdOHo55vdE5b/0NKx+K4AxtAAAAABJRU5ErkJggg==\", \"description\":\"Keep up with friends wherever you go on the web.\",\"author\":\"Facebook\",\"homepageURL\":\"https://www.facebook.com/about/messenger-for-firefox\"}");
+pref("social.manifest.facebook", "{\"origin\":\"https://www.facebook.com\",\"name\":\"Facebook Messenger\",\"workerURL\":\"https://www.facebook.com/desktop/fbdesktop2/socialfox/fbworker.js.php\",\"iconURL\":\"data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAAX0lEQVQ4jWP4%2F%2F8%2FAyUYTFhHzjgDxP9JxGeQDSBVMxgTbUBCxer%2Fr999%2BQ8DJBuArJksA9A10s8AXIBoA0B%2BR%2FY%2FjD%2BEwoBoA1yT5v3PbdmCE8MAshhID%2FUMoDgzUYIBj0Cgi7ar4coAAAAASUVORK5CYII%3D\",\"sidebarURL\":\"https://www.facebook.com/desktop/fbdesktop2/?socialfox=true\",\"icon32URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADbklEQVRYCc1Xv08UQRj99tctexAuCEFjRE0kGBEtLDSGqIWNxkYKbTAxNlY2JhaGWltNtNFeKgsKKxITK43/gCYW+IsoRhA4D47bH7fn9+bcvdm5JR7sefolC3Ozu9978+bNN7PayUv3HN3umdY0Y6IWBtSJ0HSTarXqTOiuTep6Lj+tdxAcA8RAgSmwdd2aCDs0clldYALb/FvgYVhjmfliVA2XpjEgWo0Attn42Z6WH1RFor5ehwo9XQIUZMoVn4qlCoVMSo62EvD8Kh0b3U2Xz43R2PBO6mUCGDlAf65V6MadZzT/rUimoccc2kYA4BfPHqJb105RzjJigKhRq9kEJUBIjgYVuXeL7SAI6eD+Abp5dTwVHOmEHxT50d8WBYJqSOdPj5BjW8gZR8UNqFR2xagx/65XFYaMH+BGWwiYpi4UkBPPLxTp9v1Z+lHc4DWvCQXWmIy6EjITgKowVd5Jjv7N3Hd6y5esigoOwpkJIAmMpZpLJGdiaaC4F0UmAj6bD84GCEwmB/qxMmRilmnwb/mpjAocHh4UEoNAt5NLZB7oy9OJo0PxqkAtePdhiSqunyC1LQUwWMPQaOr6GRre258Ajn4cP7KHcEXhsxpXbj+lT19X2TMNGTLVAcjcalS8gDwsQ2UOMhH4k8FkcrEn5E5ub2sKohxLK2VR77Hl9RUcsrgeRIEiVOT6z+tDbIeLy+vk+kGTCbXxycet6xhl//3f6bJEkdHYhA+mLtDIvoH4ieev5+juoxdk5+pjhALYEdXIpEB5w+NlSKSzqVQ/+H7IO6BLtl3fngGMiqhGJgIwlM6qpyUGFjySdk8m0Zg0ubeD7X9OIDEFajltRQgUJaUKx69tdgaQa0FMADuahZPMFtcEwNPm2hA7ZI5sK4aoE2NvYI+o8hkCIe7CwTv68zS0q9Dk5vpbm/8FXxitSzmMFHpsGj0wyLUheTwD2Y9fVgh1Ae0EPUgD9241ZEnld+v5kgnVZ/8fE0brVh5BK+1oCqKKF72Dk7HwBsssB/pklU1dfChy3S659H5+uelgIb+8WRv1/uGTV9Sdb5wJFlfW6fPCalMhwhSU1j2xKwKbP838GcOwJja4TqO0bjdmXxYTy1EYjFdCWoCEYZhseH/GDL3yJPHnuW6YmT7P1SlIA4768Hke4vOcsX8BE346lLHhDUQAAAAASUVORK5CYII=\", \"icon64URL\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAACNNJREFUeNrtm3tw1NUVxz/399hHHkgCaCBGEFEEREVFYFQcSoOKdkZay4z+4dDpYIsjHWx1WoTMhFi1gzBSpVgVGbU4U1sHfPESKODwEEnRYDFAICEIeZIQshs2u/v73ds/drMsyW7YLEkl2Z6Z32yy+9v7u+fc7znne8+5KzgvAjDunzlv0M13PjDZ6c4cARj0WhEoaZ1tOn3yq9XLf/tNU0O1D5Ad7wq/OpxpaXOL1j5uZAwuaGlVgwNBhULRm0XXBG6HZrlNa9uRrzfM+3DlgjIgGMsA7rl/XDdHOnNf9vosTfVuvTsaQhdkZ4iykh2rHtqydvkxwI58BhjTfv7MmP55E9/1nLNdfU15ACkVvoAaMCRvRPa+re9+DgTaPjMAx+DrJv3M67Mz+6LybWLb4NfTHhxzx31DDhZvOtqGAgNwWbjGICV9XQJB0e/KobcOP1i8qTzaAEYgaDtNU/V5A9hSaUFLuQEt2gVQSgml+j4CUAIppYgK/m0GkCjZ9xGAUNAu0LUhgJRAAAIVzwBSqVRQH4hlAClRKZAFhOgEASoFECBR8QwgUyQGdJT/B8HzCEiBNKhUJzEgBYIgQsTJAkohe9oFZHgHKvQoHtZ9K3tewfiixXABLdoFeuSSEmkF+PH4QTz7+M3o+ENptzvGtS36uSwmjMpAYF10XCllHCYoe84FlLS555Zs5jx6J6ahY+iCl98pJiDNS1hwSZop+cm91zJmxEBefGsPlu1AxKC67V3gf5oGlZSMuz6Dp2fdhWnoAEwaN5T5hsYLb+4hKB1dcgelFDpB8ifk8thDt3DO5+fZxRvxBV0IjQR0EB3KfD1GhJS0GZnnYuGcKTgdF9ZWx4/No/BJjUUrdtJqm4iL+K5SCmSAiWMHMevhcQzNzaa6ron5SzfQ7HeiaSKx+au4m6HupcJKSYZdZVI4dypuV2yo3zoql0VP3cOiFV/Q4jdiGkGhQFqMGpbJL346kbE3DEYIQWNTC39Ysp4Gr4HQtZDyiRhA0NlmSHZbRM7pr1H0m6lckeHqdGXG3jCYoqfupeC17bT49fNRXIFSNrkDTGbNGM9dtw1D10M1DI/Xx3NLP6OqETRdDy1eglPT4rqA7K56gCIrXfHCvHwGZqUnBMtR113FS/N+xHPLtuJpDa1mVobg0emjmX7vqEjsUErhaw1Q8Mo6yk4F0A1HeOW7kIlFx/u7jworRabLpmhuPjmD+iG7YNDrrhnIS09P5cW/buOeO67lkftvJt3tDE06PE7Qsnh++QYOHPOim86wcVUS0+whJug0ghTMmcK1V2eH8m2UHP++nrwhAyIwjiXDcrN5vXAGhqGhFBeMYUvJ0re2sPfgGTTDGUZrEogVopMgmGQWUCgMEWTBE5MZPSLngnGqas/w9j92s31fJfmThvPM7HyMMKRj+qgmOiBHSsnr73/B5r1V6A53KD4k3bFS8dNgckFQoWPxu1kTGDc6N7JqzR4ff/+smE+2H8FSLkx3FluLawhaG3n2iXwcppGoV/Hemt18tK0c3UwLIfUS2nVafBeQJNUXkAF+/dht3H37cKSUBC2bTTv+w98++YazPg1dT0NoIUhruoMd+2sJrtjI7381rQM3iCVrN33N++tL0c30xFNdp0GQeFRYQhcRIO0gv5xxE/fdfSO2bfNVSTmrPtxLZW0A3XSh6VporaLG1XQHu0pOU/TaOhY8+QAuZ3w6vHnnQd74536EkZ50wOsSE0zcugolbWZOG8GM/LGUVdSw6sM97D/UgGa60QxXzMJDZAq6yb7SJgr//CkLn5pOmsvR4Z5dxUdZ9t6XoKfFjNyXkqZjuoBUCpGgCyhp8eDdQ5k++UaWrdrMlr2VSFxoZlpE8YtNWGgGXx9ppnDZpxTMfTCS8gAOlJ5g8ds7kCItTIi6j6FqMVxAC2sV2RB1ekmLCTcNpH+myeyFH7BxT1Voopoe4RKJXQqhmxw45mXh0o/xeH0opThcXs2iv2wmoFyhAnbC4yX+3PgISMDShrA5XHGa3d9UITRniIeTfHASmsGhEz7mL/mI2TPv4sU3t+KzHAnu7JKpCosOkcSIICAB5hZE0OiRCM0Iwb0b6LPQdI5W+Zn/yucoYYayRk+16eK1xqRMDAHtA0r3lep0lNAjO8kfpCpMqpTF4xZEUqA7rIlOCiKpgADVWXc4FQwgEfHPB5AiByTixIDUCYJx+wJoqdIcJV5VOAWygEZcF7BToT2upFDKtuz2BrAtf8v3mju972cBJX2exso6ok6N64BhOtM11xXXPBz6v6340PcuO+DZfaJkzWqgqY3L64Bqaaz0ZV45Mkc308dG2kd97FLSaq4v317gazr5HeCLRoACFTxbfeBw+oDhWYYj4/rw+30H+rb/VMPxXQsbKnbuABqJOi4vogyRiRB5/XNvvz3zytFTDEf61eF9b0dCKTS36c4afymTsgLeQ9Ly13X/aYnzE1Uy6PV7679trNy1xe+tKwPqAH/0Vla0qw65gH7AFeG/Y3Uy9P45o0bm3PTIaplM6lTK9jWf/OBUyQcrpdXaTIyfsXQb9QcLaAn7vJd2vxY5XxBpo8pwDmgFGsLKx1oeh8OVmUUSLXUlrWZPzbdLag9v+BjUqfDzepKAyDDcZbznGHG+1NmqSKHpVlfbadJqLW+o2LHobNX+PUB1WPkfnHwYyTmX6lI7Lehr3F576NM/+T3V3wH17f2w1xkg2ggXuSvga6p8p+bgmpVKWpXAmVh+2AsNEKogdYYAJa0GT03J4obyf60HTgKe6PTTqw0QOpcQ3wXs4LlDZyq2FXrrS4uBmjDxuCw3G5eIgA46yeC5ho11pWsWW35PWTibBC4Xf+9eBLRPg0q2+s5UvHG6bMNqJYPHw7nXutxZYvIIiMoCSgbrPVX/fv7syS+3AKfC5MOmF4iRpP6RjrId8O5vrNhS1NpUWQLUholUr6muXEoatP3emrWNR9e/avk9R8P+HuxNypPkrk93pGdnK0VtXemaN6UdOHo55vdE5b/0NKx+K4AxtAAAAABJRU5ErkJggg==\", \"description\":\"Keep up with friends wherever you go on the web.\",\"author\":\"Facebook\",\"homepageURL\":\"https://www.facebook.com/about/messenger-for-firefox\",\"builtin\":\"true\"}");
 
 // comma separated list of domain origins (e.g. https://domain.com) for
 // providers that can install from their own website without user warnings.
 // entries are
-pref("social.whitelist", "");
+pref("social.whitelist", "https://mozsocial.cliqz.com,https://now.msn.com,https://mixi.jp");
 // omma separated list of domain origins (e.g. https://domain.com) for directory
 // websites (e.g. AMO) that can install providers for other sites
 pref("social.directories", "https://addons.mozilla.org");
 // remote-install allows any website to activate a provider, with extended UI
 // notifying user of installation. we can later pref off remote install if
 // necessary. This does not affect whitelisted and directory installs.
 pref("social.remote-install.enabled", true);
 
 pref("social.sidebar.open", true);
 pref("social.sidebar.unload_timeout_ms", 10000);
 pref("social.toast-notifications.enabled", true);
 
 pref("dom.identity.enabled", false);
 
+// Block insecure active content on https pages
+pref("security.mixed_content.block_active_content", true);
+
+
 // Override the Gecko-default value of false for Firefox.
 pref("plain_text.wrap_long_lines", true);
 
 #ifndef RELEASE_BUILD
 // Enable Web Audio for Firefox Desktop in Nightly and Aurora
 pref("media.webaudio.enabled", true);
 #endif
 
--- a/browser/base/content/aboutDialog.js
+++ b/browser/base/content/aboutDialog.js
@@ -90,19 +90,16 @@ function appUpdater()
                                      "@mozilla.org/updates/update-service;1",
                                      "nsIApplicationUpdateService");
   XPCOMUtils.defineLazyServiceGetter(this, "checker",
                                      "@mozilla.org/updates/update-checker;1",
                                      "nsIUpdateChecker");
   XPCOMUtils.defineLazyServiceGetter(this, "um",
                                      "@mozilla.org/updates/update-manager;1",
                                      "nsIUpdateManager");
-  XPCOMUtils.defineLazyServiceGetter(this, "bs",
-                                     "@mozilla.org/extensions/blocklist;1",
-                                     "nsIBlocklistService");
 
   this.bundle = Services.strings.
                 createBundle("chrome://browser/locale/browser.properties");
 
   this.updateBtn = document.getElementById("updateButton");
 
   // The button label value must be set so its height is correct.
   this.setupUpdateButton("update.checkInsideButton");
@@ -428,19 +425,19 @@ appUpdater.prototype =
       }
     }
   },
 
   /**
    * See XPIProvider.jsm
    */
   onUpdateAvailable: function(aAddon, aInstall) {
-    if (!this.bs.isAddonBlocklisted(aAddon.id, aInstall.version,
-                                    this.update.appVersion,
-                                    this.update.platformVersion)) {
+    if (!Services.blocklist.isAddonBlocklisted(aAddon.id, aInstall.version,
+                                               this.update.appVersion,
+                                               this.update.platformVersion)) {
       // Compatibility or new version updates mean the same thing here.
       this.onCompatibilityUpdateAvailable(aAddon);
     }
   },
 
   /**
    * See XPIProvider.jsm
    */
--- a/browser/base/content/abouthome/aboutHome.css
+++ b/browser/base/content/abouthome/aboutHome.css
@@ -340,18 +340,21 @@ body[narrow] #restorePreviousSession::be
   display: block;
   position: absolute;
   top: 12px;
   right: 12px;
   width: 69px;
   height: 19px;
 }
 
-%ifdef XP_MACOSX
-@media (min-resolution: 2dppx) {
+/* [HiDPI]
+ * At resolutions above 1dppx, prefer downscaling the 2x Retina graphics
+ * rather than upscaling the original-size ones (bug 818940).
+ */
+@media not all and (max-resolution: 1dppx) {
   #defaultSnippet1,
   #defaultSnippet2 {
     background-size: 40px;
   }
 
   #defaultSnippet1 {
     background-image: url("chrome://browser/content/abouthome/snippet1@2x.png");
   }
@@ -401,9 +404,9 @@ body[narrow] #restorePreviousSession::be
   body[narrow] #restorePreviousSession::before {
     content: url("chrome://browser/content/abouthome/restore@2x.png");
   }
 
   #aboutMozilla::before {
     content: url("chrome://browser/content/abouthome/mozilla@2x.png");
   }
 }
-%endif
+
--- a/browser/base/content/abouthome/aboutHome.js
+++ b/browser/base/content/abouthome/aboutHome.js
@@ -1,76 +1,139 @@
 /* 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/. */
 
 const SEARCH_ENGINES = {
   "Google": {
+    // This is the "2x" image designed for OS X retina resolution, Windows at 192dpi, etc.;
+    // it will be scaled down as necessary on lower-dpi displays.
     image: "data:image/png;base64," +
-           "iVBORw0KGgoAAAANSUhEUgAAAEYAAAAcCAYAAADcO8kVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ" +
-           "bWFnZVJlYWR5ccllPAAADHdJREFUeNrsWQl0VNUZvve9NzNJJpnsIkuEJMoqAVJAodCKoFUsAUFQ" +
-           "qhig0npaRUE8Viv1FFtQWxSwLXVhEawbhOWobOICFCGiEIIQRGIgCSFjMslsb9567+1/Z+7gmIYK" +
-           "Vivt6Ztzz5y5b+7yf//3f/9/38PoW7gYY+i7uDDG39heJfT/q91LGTiTIcWJkCxzxDmCCBGCkBEO" +
-           "FDCm5CPs+CGWYvcliRxEzDwgu9I/IzZClonQgT/jC9Eu3GFTz6sdKc57kIzHWKaFjIA2wz++Zhkn" +
-           "yblMIDkAFIcDDFcQ+vtjGJuaOlKPkB2G4V4U9kcu8zfWlPtPVX/g9zZ7QwE03jDTqzWVndBUc57a" +
-           "Up91gToce0cf3R05El5u6gYyNQ0BKK/x/nNmjKwwxBmx8/eSNHiWsVLXlBJ/7UdTazcN3gn3bYEw" +
-           "FmG3pvOobRuScoc+ibEyF6GsUugrgEYuMGD4nqltmJjqFBkt+gcJ/ed0SZIA5crZ+gumrpQ0H319" +
-           "ogBFh6aJFoGmQguf2n7tu62HnvgJ1cPBcN3m6dAnX4CM4QAQigmxdQthm9EEJ58bY3bOl/CQ2YE5" +
-           "pu24LdBwZE7De+M+4gBAs/IntETphOHD4FOzNoNPbjuzBkn+48/9qKXywWPcM99Edvh2siPfHeyc" +
-           "nH8mU/pM2pJLsfshI0KCNRv7viiYYXW7sRnmxTFQhCp3G9/CTqzLsht3jtkrmGJdgGF0xmYpQx5G" +
-           "KBEInWdWSs4pnm6bLD3i95WJsDG7jmtiXFYwlmF2WXATmCPROE05IGa3G33sxPrsL014tGRMVo5D" +
-           "uVdirD/8zJBluQgC9qSF2JKcV9cuPwudsbq1YLqCydjYGOkSngYtKq36vJUs6jqhuqXtgCvursty" +
-           "uHOnSZIMWROnc/dR2J5pYAZO3tF0rOwvAXI/jvKZ/vN6zVNuHQGWjYNx/SWGiohtH9R1Y17HDRvf" +
-           "4XtUCEoaQwyGbEOr5QZ3HeeLbRwrosnRNB5lHNwpuBn+HK2KWFsLcd34scWpGJd5g6Ener61faoQ" +
-           "bOXk6OsWpycnP98yYdzMrLINxYks+3h1fvZlHfE6M6LXu0oa4mPko8s7TL70kuSnOmVIMxvW5n2v" +
-           "00111fF1htzXWiwpnrJAw8FbD60qXtHn9o9LUrJ6r2CUBoOnDpQeKxu0ncPhntgRwKLRcErUVd9t" +
-           "k1falinlvLLmLr7WHfndsh/t0WOdg9Dt1cOHTyrctWutRGzH5ZbNjcQ0FpEce+lMQwCnpMRqnSQ3" +
-           "Qu50hFIzMXJnSsjt+aI+fG/kiOwUStcFQuG9AMor0GUI0da6btoyKxIKnWKaXlR/zajFCYWlXNBB" +
-           "WslMKz+tpOEezkIxJtJzuvfl5ia1DCiQnuki6+MiXzRlR47s9Lwdaa1bCKAc4uscXnX5mwFvzdO6" +
-           "JnlQSv8lgiOUERZ1QYLG4PqJE+ZItl2y4MDB3wjma8/XnGiuavSuUMNhKNOshdyZkmViD7EAGBrX" +
-           "K9gzA1CYqPZEfEoAEK91eN3jTELIlRT7jnuhm9M5mxrmJZVNvjUio0VEC3Exr2ryLTbVCJI0/ZfL" +
-           "e/TI5ZusfbXbKAcjP2706msTQRHiH3pxa2ghgIlkU+9b91zqRA6OK6MIQh+nG8HP6wT4PPzD3n3z" +
-           "lxoRiohl5eVd/1G/qC2Ug8LBOcMYh5PYd6mqemTRJ8d88axb3r//NTkYT2tQ1e27W3yzo+aamh0k" +
-           "NoWIcfeJ1Ss8A2EU0xgqflEkYQBGBuYAe3hByAHiNVBcqyRdLzEjYLhpEGFk/CaHXFtZX79RD4WR" +
-           "Bl4plOWR3MhkbI0DMOHfFhNjaEK6Neas1D9Rg3qVHQFwLHIV9DkN01miaxD6LNUjQpKPMQLHl522" +
-           "jWAVtQxELTM7agBN+AdcGwYNvJREtDwjrOL5hQWpVf36TTtcVFRhGMaAlxsbpw+prCwt/fRTHoZE" +
-           "MVS1Sna5r5CUpKExisc0RVFix4BoKEFHlDES78dIcYjdf0FRhapqH5tQxAyTtiOwZHVTk3dWdnaV" +
-           "zFgv27a5RzfKlt6PAiOZFQWmrUTy2Y3WFntPdgruhXVWxIFRA2ZIBq9QqeP18PvlBPAtRq0gHGNQ" +
-           "uHbN4ej+qJDDmMZIaaZZYASC/MzTe1RScmmdqlZce/z4CLFfW7RoppWsSP1Wy7R5NeTpfMNnU+s2" +
-           "pGIZ2KC4oEGoOOCb/7aNpkKbWKsswhhoUrQZBmPdp/hXcWDUQCjIGZFByLB2Su9ogaUaRhAa8hsG" +
-           "DxXFCmlB8CBKleyhZynXiWkwv6VRpEVYkBtnBGq28bMPZcmjC0rKCxPLFqy4GDWbVwSOPemLGhvP" +
-           "SMJNlc2+es0fQGYo5HnH59sCoMQLWVU0LV4ISqHjf/obtbQQxCbMnPngRcM25MbCB5giDo+Hl6Xg" +
-           "qtVd6yqWeu7e91RyR++Rd28OthAUaLZRa+0Rrg+SNxQqD0dDyRx9lmqY6brOVDi7HFHV9/mWvV5z" +
-           "r63aSCF0yDOlcla7NZrFmA3AeH2E1052/ebi1ZZ6ej3oh8eZ2fe1vtPqOTi495SaHygOOc1/dOFj" +
-           "QnsYhdMw44lFaMysU6dOBCBvRcCB35fl+0X4am3COCaakdoVjVaoZgW1dESJnSd5hiz/7NU02Qbd" +
-           "4dpDYdLL7wizOLW5OGoRTAM+G0VCBrg0yDOMXRGJPB8GNpim2efF7Ozi9hgA4Hfxm0b53NbW/Zyy" +
-           "i7bQlyJBFjIjDF1ViKe29xhEJizP0Flw6S76klhfrX+j8C7dt/8BPRxpsGnGyqKfGRQ7O20OVr80" +
-           "NVT9bIMIBwhrygMsLr7RcKvT9bUq1zXLumVtdvaAs56V+GK+3UMXEK15HzU1jvANHa47/YIGJ2cT" +
-           "DmAWSIZtUdT9tiDpNjEQpZ1pJpumqiKih0AfSHTB2X7/2w2GsT4CNM8k5NlnPJ7Eyg+vT0+faVqW" +
-           "Z2tEu1cYaC3fQxsPnaS/swAYN2K/qnhQHpgAKC6/Xx6Qgtmkilo2Z9WHrFHQnO/Bf/rtoctPlOVM" +
-           "az35/pKIyhCAh6SUQre4H/M+L7lAqJl+RvKsVeHw0pBlntJME2VQunVzRsaERCfuyMzMfyszMzN+" +
-           "ak52XTQ2333prxdJzuyRXGSw7KjFEnlUwYF1zrROLbxO4umwcVOWkjV0z51YyXqaEQsR9djYQMX4" +
-           "TTwVQst8NiVlPqS+Upj0EAyZB9+tcB4ZByJ71V5C7ntcj550Q4KBTl7pvjFVmtbnYvSQ7ACcEZoD" +
-           "fTUwbgDE490fN6B5o5fRjdAXiDNBGKLwNVMLZnTJLPrDh1hypAFHAkTzXnNqc+GHfG75oYxVYN0k" +
-           "YEwQXPEAcuF9ZIH/01ku1/ChivJHkNCeMk8sCNXChCdhQr7+6uvC4RU4d8RJ1PRuV64JKdDSU3su" +
-           "HuHMuKJUcuWMhMU4QHwflWBHgFEb4tXuSs3gEaLV7bdDlXvU6rm7hKH8SobmmawohUNkeSDUghdD" +
-           "0vfXMrbnYdOoSij6Eg108TFje6EOMwbjwZ0zUHeXA5GGANoz6jm2VwCotikBcN7YpvHEtvrDnoqh" +
-           "t58kuzpDJcoPhQDO6YGn3+pTK/007QYUoClgOUHpWAUuldPV4VYYn8rXfMDpHN4NS4McOBpsJ7fZ" +
-           "9utrbNvLWYdzrq5H3PO+Hfmy8GCKaI7U7o/3wq6ObklOIkhykcD+sbuFMeKAcKYos8RvSczhEgLM" +
-           "EioJknDoTEznWLDNJb5RO2POPBfqf2frdFN3LAz6Im+agU9e+Xzn8HLod+dcueXnDk/vX2DZlQaK" +
-           "/ebpLV0miPmcCXs1xZySWC9JMA/Fz3/CeXZbgcTCIEVMqiSAkFguxQ0mX06IX9KueIuPpV/xPCS+" +
-           "ttQGnDMs6Tej8SaseF4LN9c9cnxNj6VxI8Q+3em9Hx+c3PmW1UDztMZtXVLEfdymbGAJ60kJGZQm" +
-           "tH99bE8YGN/wd/mgxdG7NFDb8/ZohryYA5HguHhI5uYO27vyoqtrmAiXr31JX/V48CuY8R8FJhxE" +
-           "eeEAQWk9HnYlFmMJoRKG03QLtUJ7/93FvpXXJ7wM/6Za4l71UEu5pWkoucv0Be0tm95vmUdy5t5k" +
-           "tpbPbe8B2vmsi7+rl2Nf4yVaUlLHSQXu7r8tw1JyT+ivhQBaAhZUxBSC5EPpPtMKVDzi3z/+HZHJ" +
-           "7K/7IvC/CRhZ6Ep6evGGyXJS3kAsp3SGcgLKc7uSktBhrW7ZFq32r/HHCVbb0P9fBSYOTpIoJ5SE" +
-           "7GUnpHbrbG8EzsfWfwgwAEfC/ToQIhkhAAAAAElFTkSuQmCC"
-#ifdef XP_MACOSX
-  , imageHD: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAAA4CAYAAAAvmxBdAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAGrFJREFUeNrtfHt4VdW172+utZOASLJ5+BaIFrUeXkFsa0Fl++gDnznVVlvFxt7aqvUUarXtse3Bau35ak/rZ9XT26NtfOvV6wFET+FYCQEKWqsQIT5RCAgSXnlnrzXneNw/1lphJSSQ8BB7bub3zW+LO3uN+fiNMcf4jTEX0N/6W3/rb/2tv30smtnXB3zmRi2FQakxQNKX3WkW9S/tgW3HLpmQM543A0BWVSHMYGIwOTDxzxrOf3/RQQfMZ2/SLAvKhTFVBGUqKFONH2QAzwOMF38awHhYZAxWAqhe/iszp3+b970d/sInc57vz/J8L2eMB2MAEYkBQ6DQ3dRw4dq7AUjcP3rAfPZmLWXCLHKoIAcQAUxaB5EaEfc6AEBhjDEwmcx43/fO9HxT4vkReBIAAZgjgodW3NcPnn1sHgD/iHknn+0d6s8XEUhsXXac/34WAAGw8afuT8GZ3X055YeSJcIsG+pMZwFn0UihezRofPt3G54f/0E8cNMN+Myo8jVTCgYd823PLzrPeIBnABiUQ1F+UoWsVOYb33mkoKp/7/dKyT0AGc47X4s0sjBEoLxbBqAQAMfWRfe38B4BM+VHUkYOs8mi1FrABbK4dcvK73zwp1M3xYPOxANKBqbpCdXNGb0UwPKRF74xpfDQ0t+K54+IvlKoahmAhaO/mv/ZmicG3tqPgT61ZM2dZMQJOYhIdByRM/F3dCCOox4Bc3oEliqyyNoQCPPusXceKZqRsigu7pwaWBowiRb46+f9Q1V2wl1nDx09/R7jF30x9adNlN8yPx4DHwht+B/cBIBoRqeIE4hE/oshTcB0wNbT6/o/zrhFyohR5ZxmrVWE+fDxdx4puhGAH4OkPe5B6pykeJAc/7cDEMZ/095Y870P339m+BXs2v4kbCFsm9u2vnpJ3bzR7wAo2B/R2v+PjSnyXcRxtOLUSXFxwAFz5i2SZUIVO82SBWye/vLOIwNvjL8OYqCEfXCmJAZPHkC7sK1REbj2+lmbq86qTVmmfuuyN2cTiREWKCvACgml9kDL7HQksehsZmSdA6yVpsa6P38v3swg7m4vN1dGXrThKGP8yS5fP33j/LEvxKDbl2f2A0YFCtkZQDOaPjLAnP4jrmBGjh1AVhG2ttxfX33++vjY2eeNXf/siLUAzgEwMJZrY2vF/Vu/t4BRqCqgCmj07wMVHXUCzJQfUlZE72ICnANcqNj21h8eiK1AX46gXh29KT9H+rd9XxBjYGCgig7QHOgjPgMAKigXQZYpsi4uCOc3v35zY2wF9ufGSgxA7fdd9g8ho9ol4P4ojiQWnSUMMANECrJNy1NWYH8eGfsEvJbLv1IK1XIAUwEtA0xplJMwjcaYlTDeShg8dOgjj6/cJxNYfWIWkHJoh5yyjkSZ8RbB89YBZq4/pXafGeuzb9WciXJxo2B2houqgAjABJCLOwFMqFv57+bBxMIAJm1det3avnl1OYCLAeSgWhofaY1QXQSRuYc+/OiD3QLmUzNdqTBKhRVMADsF5beuToXJB90KtFz+lVIVniXOVUAUqjpXVB4WwPjGTPB8/0zjeTnjezl43szmKy6vNkDF4MeeXNc3oJyUhfAMkJsJkSxUVrLos6o6z/O8Ucb3phrPzyHKeVTwkpPXseg3Cqe+1SfG+swfaw6KGTAoJ5eyGF3IBeEIJB2AcXxb0FI/L45uFQBMGiu6Z3ai9eqrclBUClFWVatV5GERNT5wEVQnQLUcIuVNX75kFjn60rA5c1d0AoywlkcxfdwZ2LSgbOmBZAv70povu7RcyFUqcZYdPbxix44fnLv8pbYUOWh+P3ZM9uJRo34xoLDgq8b3YTxvqhqsaPzyJTdmn36msjdyqPqkMhWqBFGZMtV8uDX4zMjp2zemyEoPgGn4zyOvGzy48A54GcD3Sz1jFrqqE+4uOOvdmb0ASlYEs5mQE9afUdhy0yv3lHzwya/8ZcjgI0+5yssU3QKYkgQ4Ivp60LL1n8kBQfOWuvdnj6uLldgHQKoKxU7HV/eg2y1XXXmXEs1U0ZVb29o//4k5c5P5eQB+s+68aVeUFBTcCxUoS6kRWfjhueecc9SfX3ytA9QTr7eVACqYFDYEwnbB2qcHHg6gLY6ODhpomi77coUyVaojhKH9+ZHzF/wqXiztEg34APxNX/jCvQOLCi83fpy8UsCJXHLYnGdn785S0uKTyyBUBXJZcW5x4bSN56ciyLQcD4Bf/+ThVwwbUvRb+JkoswqAWX5b9Lm1M3uSM/UnUiaCKiZk2blvvnxX0ePxuBNAmpMur51wyLBPzjVeBBoVwIXBk6vuP+SG+LkcuwkWAA96/JjZKnKxkACkkFb5Nztz220xX9bJlWi+6opKFalQlpqlmzZNu6B6SaJ0knKJ/DW5qd8p8TO3x6ABqza1EE06cdmy9wDAY5LjmBTMkQnUnZ42H0ywNF52aU6FK4UY5NySI+cv+E3MCnMM5HyqtwFoO3rBgmuDMFjGjiCOIEQwzH9c+7lzju+JTaYlJ2ehUqXMWWFqeurFxqsAFMVf25Ss9kTOEZdvebClJbxTyUGZoEzwlL/b9tzRX+pOztSfSBZApSqyIrL45buKnkaUJEzLCN5+csxr+ab6fyILkI2OIZYBlx9/2bYvpLgw2+EqKLKdwoceVKJp+tfuEpYKZcaW1tZbLqheEsbj3GV+oxdV3x0GwQZrHUIiWKIST3VmDG54zFrKrBBWiGgSyx9Uv6Xh0n/MKlGlOII4h80trQ+kuJt8HGklZHg6FZF/Y/uOb7O1YOvAzkGtKxmoehe6SYNEpkErwZIFC4I2fuLKf2tLtDOPzumPhA6wAPJDLt1yuzjaAEcAMUCMApXfvPP7IcO6gkYFs4RRpgy49qanUsAPu/T8W48e/YwL6S/kYtBYwM8U/yu6KVlQUShr9CkKyK7b1vDVy0qVeaYygaxbdeK85/8a/z7sYR3zgXM1gXUInEPoCEw8PR6z8YQxaidQPh6RrgrPEOZS4chKjFuydEEKFD1xQgrAnfO3V98Jw/B5dhFgmByU+MK/nnrq6K6gcQtPyqlIubJAibCxPv/fsVVNgCI9yGEAQdBq71NHUEdQIoBo5PBBeklazuQfSpYFM0UAFsDmd2yMf9+1XkUT3otc8AiRwpFChCBCI0detGbSLtYr5uw6tk26XctZwgxhRt65ZSmr1t389M1Jk85wzKcHRAiJkCfasDnI/0sMGN+jlLMrAigMhp0+f+TBBIw4milEYOcQBHZZAoZeEIgKgIIgeJbD2MqEFhxaDAFmdAWMisxQFigzlAUnX9e4rA9yeHuTna3koBQBRogxwOPvxNbQAAA7VHQEFKSQKEFIu4lA5d3HiiuFNB4XQZlhUHBK11QO0oRdD7ouROVCkeJZG7ak/KBOYHlz4sTy1WVlVY5oYego2+bs82+3tFw6YcVrp01dteqpxNfyhKQuGlxCMSsKBh570ABT/8XP5dhRVpyDWAd2Ns0O9yrhWdfcMpvCEByEoNCCwhBgvgBdM+PM5TH5FPW+1ZLo8de2viehe12dhVoHOAtDPO61O4o+kYCTnE5wVuGsxlzKHul7BUDKdomKgwpB2QHAyNiP2Dl+0Z2WRXZ9YP0F55WJczvX0jp09U3fLiurWD1+/NqQaHZIVNbu3O1vt7aM+fSqVRWXvPvu0pRldwAkQ5brjO+NMh0kgMIvGjYZwIKETPxIrYt1U5M8iThKJil9yZGc++ab298dP36Jb8wZohqhQHRErKEeAA6fG5FT5yIlYYI6tzfOvtiQni3MYDw0ChqEgUMyejyAdwGwDeW4ZI9FAGQOmwzgv/cERmZbDXhnKBNUGMJkUhGVduSSJJ1P6rw8HIalJo7ilBkchgCgL48fVzLceDc4kZnWUdap1AQi10x+660n4jXyk1M7ZXEZgHhMUkMO4NjphQGMf8h56Fx++ZE1a+1xZC2Szjs3sk9uUEhUbSMvP3LeyOGZ0tKJiearo1J1DHVRPYmS7JUcG2g1pxxUsooBnpmQWAOb10YbKGygcKFCZOC0XqxrRKokCBQG5euX77In2k1P+2hhWEZBAAoCuCCEcW7E2xMn/m6oYo0jyjnmuc3Off6UN96YMvmtt5LILSmQ61r3xAA0I+xqPBiIejAd1f7e2MPPfvm4LQs/89a+bP6nZuSzfsaU+T7g+UBixYQVRFGS01kFO22srRy0EgA4CEvFRHS3MANMY/fGbybmlQqAFSBVsCp8kWwCGA5dqefFShnnRV77ecHYU37iXuqLoB0tsuIo34v3NfJR1GlJsrnOuiXGy1y8k+rwxh573srSD/6rbLdra7yMqgjUCGAULR8uWr0LJPYAGApCeCbKNygLPKIxJ65YOSU+YpLUUCYGiqBzQVy3Ft1zbevnJl60UARqACgcVDo9ZZr63Mqua68QxlpmrWJC1FmrmLSKCFVktcpZrbKhzg4D26E5Lgjg8vnoMwwh1hU/dvTRo/qcDyJqcESw5Dp6o3XNHVrqLDSubAdFjuXwwWZcX+Wc9APboKxQUoiLurXaIYfCpjlCDsoxZ6OCouLRt+xpbY3nA8aDMR6E2+9vffOWxl02cQ+Bbdjevt7l83D5ABRaKNHYO484YmgMkoJ4jElCOL8Lz9NN87YumrRDxc2DElQZKgIVhZcZcO1hZ74wtK/H0thvtuXGXdM2S0S/ziQ1FPJiG7pHwvbgDhtKnQ0VNhCEeUHQLmiuf2fymieGvJGY8DCfX+yCEC5xWIlwtO+P6+s4VESJGS4+liwxKjZ/2FGRZvPhYgktxEZdHWOAr2P34ihWIQWTgJ2CnWJbo9Ymz1g/5+h1QsF9wgKJ19Z4hV874fKNE3cnx8v4V8H4UOjqhvce+zW6qdWVlOvSjQsDlw/WUT4A5QNQGIJDizMPHXR+CiRBb4GSzlYr26Z7vYKSC42nUOPBqA9VU1I0ZOJPEYWj1NvVW/3AoEUAFgO4IzZ1hYk2jf9WUw7IjCIXHUVhXrFp/sQtKZPIoXXr/PjoSkZeoHo6gP/bFyeciECqcHG3IrXp37a2SF3xQNPxRAXgq5nS1bHsDWCYALYAu+h0W/impI8Pad9ec/vAoWVTjV84Nsn5FAwcvmDMN5rOqf1jyatdHzjuGjvThloKYH3b5qVXt77544ZuN1QEKknF3a6ImfDee4tWjBrV6R5Qoeq1AP6Avaxx8gDolhdPXAh2qzQmZFQ4ZhALrj/mvLpT+qhxya0BP5VVZQBkA6jNR0AJ2xUUcjKGjsx4k3PVYUwaJU6rJ3reLiHlHppjBjF3fLYSzU/noEZ83611VusoVJBVsFWAdezim/3jemSFe+SNIsvCpAhCXf7TBZI+PnTr4nO2t2xcME3ZroYKIouEEqDoxfHfav/GxOttFgBOucGWll0XVqrqXYDWNLz3aG7bsovWp4i2TvkhScLqNBezq/M/zxLBxV2Yx/75yCPP6usc04CJ+B3bcLMwQTiK+0UIwgz1ip8+4pyaYX0x0SnWMkjnYGygkm9nBO0MGzoI2TTDyQBw7ubNawPmeZYZNt5wZhrxX8OHX9yXSTJzGcVgIWasbs8/hc7XRzXM670cg0Vs5H+MHm6u74ucrb/KlAlFPoySoqFFn+rm+OCGV762df2cYWe4fP0M5qDWhoowRIm1/h+s1YZx3wrVOV1LDhXMaGzfXntF46vXtMQRS/clsqRRT9SNd0GMBo6edRStZbKeg4D//ciQIcP2CTDbqsdVKQePq1JMFkXxv4qO9AaMfPGoaeuG9kXp0LkU0wGgMFC1gYAdAeyg0m3IrE3W3mtTvodjRpHq9X3xL4h5Qsq63P/z9ra6LqScvvmBPkwOTex2lnf4wNee/47fa99NGGVJ8Zl1qP3UPfwkdr15mDDV+Y3Pf+Kh9c9kz9pee89J7dvevaRt+7qLbVv47y5UUKggp3BB/okNz0/aHI8332OaIgELxWDpptQtt6X+Qcu03nVYGQYxjxzl+7/eGyvjdYrCtv31JiW7QTjy6qWj83jF4AeP/MLaodiHRtZBXAihEEIWkq4eSgGmvKGhqpX5d1YEVhiWBaI6Zf6QITN7s5ELhw4tZZavkwhIZMOC1rZfo5s64nPv4+1NzXot2/hYiqKckglH4/7eRojCOospSt6u2ijfS1Hv3I0SdVy5aam9ecumBeOqN8w7aRkxSlMVdRDmRHa4m5xWPKPEusUA6maIrcy/cCKwInASKaCoXrlo2LAH+xpMpAEjLauu2ObaNnxVmZqUHaI8SaR+KnIhTPHCo6ZtOn6vk4qUPNNGnV2PJ0ptENweMq92zHBMcMwwIrfMLS6etKdJEnMlCYOZm9YE4dUPkWvsIUckJ/+SZwd5PCEOEBc5rh7jgrqf+VfvSc7mO/xZSihVAra3YMY/PqqrUhZVe7C8yRHTBqAVQJuQN5idgJ2ASQAz4PJjptWevKc0RZQ0TQATRWDd/dmFDQ2VeaLH0z4dRVTK9EXZ7IqFJSXH7W6eLw0blntp2NAydGOSqPGVs/5mW9ZcJGKbRSxELIRDCFuIuAmiBa8eMW37rcdc1JDtM+3PYdSp43k9/ulPgmDrsnz+vFBktRWBZYEVKSlUfeH5wYPP7u5Hfy4uzi4oLq50IjkSaXrf2vIfBPnV6PlKiwKg0XfyNe2BPkmJ8+oUGeh/bLjNu7En0Gy+w5sppLcyKRra9IZJ98hTvciop9MPSSFUwGTnEjHICsgpyKHYHzjquWMvrJ+wewUENPFjCIAxk3uStyIMbw5FVieWJvJpBE5kgqq+X1VcPGdRcfHMxSUluSUlJbmlUZ+1tKRkLRGVnrZ9Rw12rSLtsDpFg8vmfbpw0HH3wcuMMSaiao2XAbwMjPFhPL/ReN6DfsY8tHHekN0WXR929vqsCpWruFshPEqFo3IyADuWTxgea1rYTbRVeEMmc+SnCwp+OcB4l3kmLq0D4BnzkA/MMUBjvDMXC1DBqlkCFr9N9E//HIZpPyDsQVuTFwsMfP273k8GFeLbvo9izwe8DGA8VMPgIc/D2piALlPFDGWUMqNuazOun/RbeQU7L/zl0cfC+SPOXjG84NBRawCvJNoSE7PiBgr5Xx/MKf7jLnzIbUPKlHVF5C11KgJfD9+shY8Vxjd30780rEvP8bFDDvnVQGO+lU5MeTDwzM5aTbOzNyrw/XNbWx9JFLknk+sjqjobUHJq9XS/cNj3jZcZAc9PwBIDyAeMD2O8RhhvpTFYqYpGqMQOM2UhlFOhsvjfgNJ6ofxyoZaXbHPt8mDNjDU9ACYBbyGAAT/KZEZ/MpO5qciYyRlgROeJGSh0nQCL21Ufmx4EL8dMpqScRt4DFVAAYMCtORx+0Rhz7aFF+GJBBmNM/JKklGo1KlBtHZ474U79P9hZOZcQYb0unD/mwu05qADCZwE4C8Y7I3kTk4kFx+mUuzfMKf5e+rn+rUMq4PR4hFII0gw0xpdvGAWGoDqHf9m8IuV8m2Qtf1pQMPok37+50JhpHlC8EzwRcAzwOqs+Vkv06I+da04nInd3RvuxgCIAhcUTF5zvFQ79oucP+Cy8zIjE6qQnt5Pviu5IqAogVKNCNSrBUte6blnrqi/Vo3O9rI3Pc7cbP6sgGQcAf7rvl3zK908uBKjAGK5jrrmNKKHj/RS3E6L3V2USLUzkZAB4i75pTivwwQMyoKYQ685+QOtScvzUHPbIlJ54ZVsuDPTrZDmnQqUQggo1qkoNRDyFeJ6XGQfjF0fW3O9YWxW6adNzw36Dzm/JKEJ0k7QgtfiSygd1vSrkdZ3jlb6fneT7Y+MN1xrmVX9gbkw9q1MdsemFU5wkpwqSRSw49gfZAcPPHOsVlIww/sBjjPEVnqfGZEQlWKVCjWK31TW/dv56pCruU126TGxPl+USIrAgNQ7TQ+pNukQqfalLNimApvMt6CZMTvsiu3VOJ17XnrNWZ9m85oK8Qmz4sFB+CeXrF29dfOqG1PwKs6fOKyvKjrnb8wrHGD8TWfCOEoX85zb96dgXY9leN2NM+y3SJZG4u7XsSldIykFPz09NHxbRT2U3M11AsKf8aRqtnBqQoG91oWkGOS0/XaQo2Pf3u5mUDK9LukD7Mv5Tv9teSQ4VzipsINUtW9Zct/mFiRu7WbcOuQNP+MXQ4hGX3mEKBl1mjB9bbwAqSz6cf+TZ8Qaabta/u6hM92ItpZs5dvyor5R/dwvp9QAa6eFzfxRlpVMk2mXh93czeyPn1Bn5ShWtYAJsyEve+OPgC7Hzmgx3USDtejQedlbtDX7h0Ns6HChV5LcvP7rpb1+qx/690dHrtewL05c2c7ZLtrM91fOpDGjXyvT9+WYBPQAg3NPcey1n4vVtFUJSIfGNjJZNy2ekkqzpazIJOefSoTaA9q1VY+5Wbvs9NAoYVBkFh5Sesi9lJ/u6lt5+WETpoi2MPpZU/k9szmKGtVGRWBjQ6g3zP78pxfSGKb+tJ4LPAsi31S/+uXCUlVZmCIc+DlI15L4Cpr/1FA1d0VLqAilzgcCGChdQc5eoTXqpkNS66hv1YLsUElURiG1sOZj7lunf3v3fwlBKjRfX9EjEHKcscV98D40zRKIqgEpz4yvTVnfjU/VbmL/r4yhwTTbPCNsZNi8g50/OnvbCsXu5wQqVURCBuOb7seu98n7A/L23Tc8NX8mW6pL73UoOhYPH/GJv/I7Dzlqbg5pRUG1q++A//+Ng+4f9gDlATVzLHfErZiHioKrnH37uhgeG597sdYnIYeeszypQqQawre9dHNbd0Yj9/5KnfsB8DJpuXXj8Q+ryj3dUZglD1Uz3MsWvHX7uh1fv6QGHn7upAmrWQpEV2zSt+bVptamw+6C9VaP/hcoHrvkABgydUjPLywy6Oboh6HW6PgLjLYqStqYRQHKDMQflMhXOQrnata27tvGvufrEn8ZBfmdPP2AO7NpmAAw85B8qTyjKlt1svAHTjPGLk4w0jAcTAyllnBoh9Kxw/tEdS8cuT0WyH4vX1PYD5qMBzQDE2eFDxz09zsscWuwVHX6a8YwaFAiMNAkHr4vdUdf82rQN6JwnSl4N4vAxeKdxP2A+mjXuKTvcXcY9TdOnyxPk4zKZ/vbRAqe75C3QfZZY0P/y6/7299z+H4QrdGsoib8JAAAAAElFTkSuQmCC"
-#endif
+           "iVBORw0KGgoAAAANSUhEUgAAAIwAAAA4CAYAAAAvmxBdAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ" +
+           "bWFnZVJlYWR5ccllPAAAGrFJREFUeNrtfHt4VdW172+utZOASLJ5+BaIFrUeXkFsa0Fl++gDnznV" +
+           "VlvFxt7aqvUUarXtse3Bau35ak/rZ9XT26NtfOvV6wFET+FYCQEKWqsQIT5RCAgSXnlnrzXneNw/" +
+           "1lphJSSQ8BB7bub3zW+LO3uN+fiNMcf4jTEX0N/6W3/rb/2tv30smtnXB3zmRi2FQakxQNKX3WkW" +
+           "9S/tgW3HLpmQM543A0BWVSHMYGIwOTDxzxrOf3/RQQfMZ2/SLAvKhTFVBGUqKFONH2QAzwOMF38a" +
+           "wHhYZAxWAqhe/iszp3+b970d/sInc57vz/J8L2eMB2MAEYkBQ6DQ3dRw4dq7AUjcP3rAfPZmLWXC" +
+           "LHKoIAcQAUxaB5EaEfc6AEBhjDEwmcx43/fO9HxT4vkReBIAAZgjgodW3NcPnn1sHgD/iHknn+0d" +
+           "6s8XEUhsXXac/34WAAGw8afuT8GZ3X055YeSJcIsG+pMZwFn0UihezRofPt3G54f/0E8cNMN+Myo" +
+           "8jVTCgYd823PLzrPeIBnABiUQ1F+UoWsVOYb33mkoKp/7/dKyT0AGc47X4s0sjBEoLxbBqAQAMfW" +
+           "Rfe38B4BM+VHUkYOs8mi1FrABbK4dcvK73zwp1M3xYPOxANKBqbpCdXNGb0UwPKRF74xpfDQ0t+K" +
+           "54+IvlKoahmAhaO/mv/ZmicG3tqPgT61ZM2dZMQJOYhIdByRM/F3dCCOox4Bc3oEliqyyNoQCPPu" +
+           "sXceKZqRsigu7pwaWBowiRb46+f9Q1V2wl1nDx09/R7jF30x9adNlN8yPx4DHwht+B/cBIBoRqeI" +
+           "E4hE/oshTcB0wNbT6/o/zrhFyohR5ZxmrVWE+fDxdx4puhGAH4OkPe5B6pykeJAc/7cDEMZ/095Y" +
+           "870P339m+BXs2v4kbCFsm9u2vnpJ3bzR7wAo2B/R2v+PjSnyXcRxtOLUSXFxwAFz5i2SZUIVO82S" +
+           "BWye/vLOIwNvjL8OYqCEfXCmJAZPHkC7sK1REbj2+lmbq86qTVmmfuuyN2cTiREWKCvACgml9kDL" +
+           "7HQksehsZmSdA6yVpsa6P38v3swg7m4vN1dGXrThKGP8yS5fP33j/LEvxKDbl2f2A0YFCtkZQDOa" +
+           "PjLAnP4jrmBGjh1AVhG2ttxfX33++vjY2eeNXf/siLUAzgEwMJZrY2vF/Vu/t4BRqCqgCmj07wMV" +
+           "HXUCzJQfUlZE72ICnANcqNj21h8eiK1AX46gXh29KT9H+rd9XxBjYGCgig7QHOgjPgMAKigXQZYp" +
+           "si4uCOc3v35zY2wF9ufGSgxA7fdd9g8ho9ol4P4ojiQWnSUMMANECrJNy1NWYH8eGfsEvJbLv1IK" +
+           "1XIAUwEtA0xplJMwjcaYlTDeShg8dOgjj6/cJxNYfWIWkHJoh5yyjkSZ8RbB89YBZq4/pXafGeuz" +
+           "b9WciXJxo2B2houqgAjABJCLOwFMqFv57+bBxMIAJm1det3avnl1OYCLAeSgWhofaY1QXQSRuYc+" +
+           "/OiD3QLmUzNdqTBKhRVMADsF5beuToXJB90KtFz+lVIVniXOVUAUqjpXVB4WwPjGTPB8/0zjeTnj" +
+           "ezl43szmKy6vNkDF4MeeXNc3oJyUhfAMkJsJkSxUVrLos6o6z/O8Ucb3phrPzyHKeVTwkpPXseg3" +
+           "Cqe+1SfG+swfaw6KGTAoJ5eyGF3IBeEIJB2AcXxb0FI/L45uFQBMGiu6Z3ai9eqrclBUClFWVatV" +
+           "5GERNT5wEVQnQLUcIuVNX75kFjn60rA5c1d0AoywlkcxfdwZ2LSgbOmBZAv70povu7RcyFUqcZYd" +
+           "Pbxix44fnLv8pbYUOWh+P3ZM9uJRo34xoLDgq8b3YTxvqhqsaPzyJTdmn36msjdyqPqkMhWqBFGZ" +
+           "MtV8uDX4zMjp2zemyEoPgGn4zyOvGzy48A54GcD3Sz1jFrqqE+4uOOvdmb0ASlYEs5mQE9afUdhy" +
+           "0yv3lHzwya/8ZcjgI0+5yssU3QKYkgQ4Ivp60LL1n8kBQfOWuvdnj6uLldgHQKoKxU7HV/eg2y1X" +
+           "XXmXEs1U0ZVb29o//4k5c5P5eQB+s+68aVeUFBTcCxUoS6kRWfjhueecc9SfX3ytA9QTr7eVACqY" +
+           "FDYEwnbB2qcHHg6gLY6ODhpomi77coUyVaojhKH9+ZHzF/wqXiztEg34APxNX/jCvQOLCi83fpy8" +
+           "UsCJXHLYnGdn785S0uKTyyBUBXJZcW5x4bSN56ciyLQcD4Bf/+ThVwwbUvRb+JkoswqAWX5b9Lm1" +
+           "M3uSM/UnUiaCKiZk2blvvnxX0ePxuBNAmpMur51wyLBPzjVeBBoVwIXBk6vuP+SG+LkcuwkWAA96" +
+           "/JjZKnKxkACkkFb5Nztz220xX9bJlWi+6opKFalQlpqlmzZNu6B6SaJ0knKJ/DW5qd8p8TO3x6AB" +
+           "qza1EE06cdmy9wDAY5LjmBTMkQnUnZ42H0ywNF52aU6FK4UY5NySI+cv+E3MCnMM5HyqtwFoO3rB" +
+           "gmuDMFjGjiCOIEQwzH9c+7lzju+JTaYlJ2ehUqXMWWFqeurFxqsAFMVf25Ss9kTOEZdvebClJbxT" +
+           "yUGZoEzwlL/b9tzRX+pOztSfSBZApSqyIrL45buKnkaUJEzLCN5+csxr+ab6fyILkI2OIZYBlx9/" +
+           "2bYvpLgw2+EqKLKdwoceVKJp+tfuEpYKZcaW1tZbLqheEsbj3GV+oxdV3x0GwQZrHUIiWKIST3Vm" +
+           "DG54zFrKrBBWiGgSyx9Uv6Xh0n/MKlGlOII4h80trQ+kuJt8HGklZHg6FZF/Y/uOb7O1YOvAzkGt" +
+           "Kxmoehe6SYNEpkErwZIFC4I2fuLKf2tLtDOPzumPhA6wAPJDLt1yuzjaAEcAMUCMApXfvPP7IcO6" +
+           "gkYFs4RRpgy49qanUsAPu/T8W48e/YwL6S/kYtBYwM8U/yu6KVlQUShr9CkKyK7b1vDVy0qVeaYy" +
+           "gaxbdeK85/8a/z7sYR3zgXM1gXUInEPoCEw8PR6z8YQxaidQPh6RrgrPEOZS4chKjFuydEEKFD1x" +
+           "QgrAnfO3V98Jw/B5dhFgmByU+MK/nnrq6K6gcQtPyqlIubJAibCxPv/fsVVNgCI9yGEAQdBq71NH" +
+           "UEdQIoBo5PBBeklazuQfSpYFM0UAFsDmd2yMf9+1XkUT3otc8AiRwpFChCBCI0detGbSLtYr5uw6" +
+           "tk26XctZwgxhRt65ZSmr1t389M1Jk85wzKcHRAiJkCfasDnI/0sMGN+jlLMrAigMhp0+f+TBBIw4" +
+           "milEYOcQBHZZAoZeEIgKgIIgeJbD2MqEFhxaDAFmdAWMisxQFigzlAUnX9e4rA9yeHuTna3koBQB" +
+           "RogxwOPvxNbQAAA7VHQEFKSQKEFIu4lA5d3HiiuFNB4XQZlhUHBK11QO0oRdD7ouROVCkeJZG7ak" +
+           "/KBOYHlz4sTy1WVlVY5oYego2+bs82+3tFw6YcVrp01dteqpxNfyhKQuGlxCMSsKBh570ABT/8XP" +
+           "5dhRVpyDWAd2Ns0O9yrhWdfcMpvCEByEoNCCwhBgvgBdM+PM5TH5FPW+1ZLo8de2viehe12dhVoH" +
+           "OAtDPO61O4o+kYCTnE5wVuGsxlzKHul7BUDKdomKgwpB2QHAyNiP2Dl+0Z2WRXZ9YP0F55WJczvX" +
+           "0jp09U3fLiurWD1+/NqQaHZIVNbu3O1vt7aM+fSqVRWXvPvu0pRldwAkQ5brjO+NMh0kgMIvGjYZ" +
+           "wIKETPxIrYt1U5M8iThKJil9yZGc++ab298dP36Jb8wZohqhQHRErKEeAA6fG5FT5yIlYYI6tzfO" +
+           "vtiQni3MYDw0ChqEgUMyejyAdwGwDeW4ZI9FAGQOmwzgv/cERmZbDXhnKBNUGMJkUhGVduSSJJ1P" +
+           "6rw8HIalJo7ilBkchgCgL48fVzLceDc4kZnWUdap1AQi10x+660n4jXyk1M7ZXEZgHhMUkMO4Njp" +
+           "hQGMf8h56Fx++ZE1a+1xZC2Szjs3sk9uUEhUbSMvP3LeyOGZ0tKJiearo1J1DHVRPYmS7JUcG2g1" +
+           "pxxUsooBnpmQWAOb10YbKGygcKFCZOC0XqxrRKokCBQG5euX77In2k1P+2hhWEZBAAoCuCCEcW7E" +
+           "2xMn/m6oYo0jyjnmuc3Off6UN96YMvmtt5LILSmQ61r3xAA0I+xqPBiIejAd1f7e2MPPfvm4LQs/" +
+           "89a+bP6nZuSzfsaU+T7g+UBixYQVRFGS01kFO22srRy0EgA4CEvFRHS3MANMY/fGbybmlQqAFSBV" +
+           "sCp8kWwCGA5dqefFShnnRV77ecHYU37iXuqLoB0tsuIo34v3NfJR1GlJsrnOuiXGy1y8k+rwxh57" +
+           "3srSD/6rbLdra7yMqgjUCGAULR8uWr0LJPYAGApCeCbKNygLPKIxJ65YOSU+YpLUUCYGiqBzQVy3" +
+           "Ft1zbevnJl60UARqACgcVDo9ZZr63Mqua68QxlpmrWJC1FmrmLSKCFVktcpZrbKhzg4D26E5Lgjg" +
+           "8vnoMwwh1hU/dvTRo/qcDyJqcESw5Dp6o3XNHVrqLDSubAdFjuXwwWZcX+Wc9APboKxQUoiLurXa" +
+           "IYfCpjlCDsoxZ6OCouLRt+xpbY3nA8aDMR6E2+9vffOWxl02cQ+Bbdjevt7l83D5ABRaKNHYO484" +
+           "YmgMkoJ4jElCOL8Lz9NN87YumrRDxc2DElQZKgIVhZcZcO1hZ74wtK/H0thvtuXGXdM2S0S/ziQ1" +
+           "FPJiG7pHwvbgDhtKnQ0VNhCEeUHQLmiuf2fymieGvJGY8DCfX+yCEC5xWIlwtO+P6+s4VESJGS4+" +
+           "liwxKjZ/2FGRZvPhYgktxEZdHWOAr2P34ihWIQWTgJ2CnWJbo9Ymz1g/5+h1QsF9wgKJ19Z4hV87" +
+           "4fKNE3cnx8v4V8H4UOjqhvce+zW6qdWVlOvSjQsDlw/WUT4A5QNQGIJDizMPHXR+CiRBb4GSzlYr" +
+           "26Z7vYKSC42nUOPBqA9VU1I0ZOJPEYWj1NvVW/3AoEUAFgO4IzZ1hYk2jf9WUw7IjCIXHUVhXrFp" +
+           "/sQtKZPIoXXr/PjoSkZeoHo6gP/bFyeciECqcHG3IrXp37a2SF3xQNPxRAXgq5nS1bHsDWCYALYA" +
+           "u+h0W/impI8Pad9ec/vAoWVTjV84Nsn5FAwcvmDMN5rOqf1jyatdHzjuGjvThloKYH3b5qVXt775" +
+           "44ZuN1QEKknF3a6ImfDee4tWjBrV6R5Qoeq1AP6Avaxx8gDolhdPXAh2qzQmZFQ4ZhALrj/mvLpT" +
+           "+qhxya0BP5VVZQBkA6jNR0AJ2xUUcjKGjsx4k3PVYUwaJU6rJ3reLiHlHppjBjF3fLYSzU/noEZ8" +
+           "3611VusoVJBVsFWAdezim/3jemSFe+SNIsvCpAhCXf7TBZI+PnTr4nO2t2xcME3ZroYKIouEEqDo" +
+           "xfHfav/GxOttFgBOucGWll0XVqrqXYDWNLz3aG7bsovWp4i2TvkhScLqNBezq/M/zxLBxV2Yx/75" +
+           "yCPP6usc04CJ+B3bcLMwQTiK+0UIwgz1ip8+4pyaYX0x0SnWMkjnYGygkm9nBO0MGzoI2TTDyQBw" +
+           "7ubNawPmeZYZNt5wZhrxX8OHX9yXSTJzGcVgIWasbs8/hc7XRzXM670cg0Vs5H+MHm6u74ucrb/K" +
+           "lAlFPoySoqFFn+rm+OCGV762df2cYWe4fP0M5qDWhoowRIm1/h+s1YZx3wrVOV1LDhXMaGzfXntF" +
+           "46vXtMQRS/clsqRRT9SNd0GMBo6edRStZbKeg4D//ciQIcP2CTDbqsdVKQePq1JMFkXxv4qO9AaM" +
+           "fPGoaeuG9kXp0LkU0wGgMFC1gYAdAeyg0m3IrE3W3mtTvodjRpHq9X3xL4h5Qsq63P/z9ra6LqSc" +
+           "vvmBPkwOTex2lnf4wNee/47fa99NGGVJ8Zl1qP3UPfwkdr15mDDV+Y3Pf+Kh9c9kz9pee89J7dve" +
+           "vaRt+7qLbVv47y5UUKggp3BB/okNz0/aHI8332OaIgELxWDpptQtt6X+Qcu03nVYGQYxjxzl+7/e" +
+           "GyvjdYrCtv31JiW7QTjy6qWj83jF4AeP/MLaodiHRtZBXAihEEIWkq4eSgGmvKGhqpX5d1YEVhiW" +
+           "BaI6Zf6QITN7s5ELhw4tZZavkwhIZMOC1rZfo5s64nPv4+1NzXot2/hYiqKckglH4/7eRojCOosp" +
+           "St6u2ijfS1Hv3I0SdVy5aam9ecumBeOqN8w7aRkxSlMVdRDmRHa4m5xWPKPEusUA6maIrcy/cCKw" +
+           "InASKaCoXrlo2LAH+xpMpAEjLauu2ObaNnxVmZqUHaI8SaR+KnIhTPHCo6ZtOn6vk4qUPNNGnV2P" +
+           "J0ptENweMq92zHBMcMwwIrfMLS6etKdJEnMlCYOZm9YE4dUPkWvsIUckJ/+SZwd5PCEOEBc5rh7j" +
+           "grqf+VfvSc7mO/xZSihVAra3YMY/PqqrUhZVe7C8yRHTBqAVQJuQN5idgJ2ASQAz4PJjptWevKc0" +
+           "RZQ0TQATRWDd/dmFDQ2VeaLH0z4dRVTK9EXZ7IqFJSXH7W6eLw0blntp2NAydGOSqPGVs/5mW9Zc" +
+           "JGKbRSxELIRDCFuIuAmiBa8eMW37rcdc1JDtM+3PYdSp43k9/ulPgmDrsnz+vFBktRWBZYEVKSlU" +
+           "feH5wYPP7u5Hfy4uzi4oLq50IjkSaXrf2vIfBPnV6PlKiwKg0XfyNe2BPkmJ8+oUGeh/bLjNu7En" +
+           "0Gy+w5sppLcyKRra9IZJ98hTvciop9MPSSFUwGTnEjHICsgpyKHYHzjquWMvrJ+wewUENPFjCIAx" +
+           "k3uStyIMbw5FVieWJvJpBE5kgqq+X1VcPGdRcfHMxSUluSUlJbmlUZ+1tKRkLRGVnrZ9Rw12rSLt" +
+           "sDpFg8vmfbpw0HH3wcuMMSaiao2XAbwMjPFhPL/ReN6DfsY8tHHekN0WXR929vqsCpWruFshPEqF" +
+           "o3IyADuWTxgea1rYTbRVeEMmc+SnCwp+OcB4l3kmLq0D4BnzkA/MMUBjvDMXC1DBqlkCFr9N9E//" +
+           "HIZpPyDsQVuTFwsMfP273k8GFeLbvo9izwe8DGA8VMPgIc/D2piALlPFDGWUMqNuazOun/RbeQU7" +
+           "L/zl0cfC+SPOXjG84NBRawCvJNoSE7PiBgr5Xx/MKf7jLnzIbUPKlHVF5C11KgJfD9+shY8Vxjd3" +
+           "0780rEvP8bFDDvnVQGO+lU5MeTDwzM5aTbOzNyrw/XNbWx9JFLknk+sjqjobUHJq9XS/cNj3jZcZ" +
+           "Ac9PwBIDyAeMD2O8RhhvpTFYqYpGqMQOM2UhlFOhsvjfgNJ6ofxyoZaXbHPt8mDNjDU9ACYBbyGA" +
+           "AT/KZEZ/MpO5qciYyRlgROeJGSh0nQCL21Ufmx4EL8dMpqScRt4DFVAAYMCtORx+0Rhz7aFF+GJB" +
+           "BmNM/JKklGo1KlBtHZ474U79P9hZOZcQYb0unD/mwu05qADCZwE4C8Y7I3kTk4kFx+mUuzfMKf5e" +
+           "+rn+rUMq4PR4hFII0gw0xpdvGAWGoDqHf9m8IuV8m2Qtf1pQMPok37+50JhpHlC8EzwRcAzwOqs+" +
+           "Vkv06I+da04nInd3RvuxgCIAhcUTF5zvFQ79oucP+Cy8zIjE6qQnt5Pviu5IqAogVKNCNSrBUte6" +
+           "blnrqi/Vo3O9rI3Pc7cbP6sgGQcAf7rvl3zK908uBKjAGK5jrrmNKKHj/RS3E6L3V2USLUzkZAB4" +
+           "i75pTivwwQMyoKYQ685+QOtScvzUHPbIlJ54ZVsuDPTrZDmnQqUQggo1qkoNRDyFeJ6XGQfjF0fW" +
+           "3O9YWxW6adNzw36Dzm/JKEJ0k7QgtfiSygd1vSrkdZ3jlb6fneT7Y+MN1xrmVX9gbkw9q1MdsemF" +
+           "U5wkpwqSRSw49gfZAcPPHOsVlIww/sBjjPEVnqfGZEQlWKVCjWK31TW/dv56pCruU126TGxPl+US" +
+           "IrAgNQ7TQ+pNukQqfalLNimApvMt6CZMTvsiu3VOJ17XnrNWZ9m85oK8Qmz4sFB+CeXrF29dfOqG" +
+           "1PwKs6fOKyvKjrnb8wrHGD8TWfCOEoX85zb96dgXY9leN2NM+y3SJZG4u7XsSldIykFPz09NHxbR" +
+           "T2U3M11AsKf8aRqtnBqQoG91oWkGOS0/XaQo2Pf3u5mUDK9LukD7Mv5Tv9teSQ4VzipsINUtW9Zc" +
+           "t/mFiRu7WbcOuQNP+MXQ4hGX3mEKBl1mjB9bbwAqSz6cf+TZ8Qaabta/u6hM92ItpZs5dvyor5R/" +
+           "dwvp9QAa6eFzfxRlpVMk2mXh93czeyPn1Bn5ShWtYAJsyEve+OPgC7Hzmgx3USDtejQedlbtDX7h" +
+           "0Ns6HChV5LcvP7rpb1+qx/690dHrtewL05c2c7ZLtrM91fOpDGjXyvT9+WYBPQAg3NPcey1n4vVt" +
+           "FUJSIfGNjJZNy2ekkqzpazIJOefSoTaA9q1VY+5Wbvs9NAoYVBkFh5Sesi9lJ/u6lt5+WETpoi2M" +
+           "PpZU/k9szmKGtVGRWBjQ6g3zP78pxfSGKb+tJ4LPAsi31S/+uXCUlVZmCIc+DlI15L4Cpr/1FA1d" +
+           "0VLqAilzgcCGChdQc5eoTXqpkNS66hv1YLsUElURiG1sOZj7lunf3v3fwlBKjRfX9EjEHKcscV98" +
+           "D40zRKIqgEpz4yvTVnfjU/VbmL/r4yhwTTbPCNsZNi8g50/OnvbCsXu5wQqVURCBuOb7seu98n7A" +
+           "/L23Tc8NX8mW6pL73UoOhYPH/GJv/I7Dzlqbg5pRUG1q++A//+Ng+4f9gDlATVzLHfErZiHioKrn" +
+           "H37uhgeG597sdYnIYeeszypQqQawre9dHNbd0Yj9/5KnfsB8DJpuXXj8Q+ryj3dUZglD1Uz3MsWv" +
+           "HX7uh1fv6QGHn7upAmrWQpEV2zSt+bVptamw+6C9VaP/hcoHrvkABgydUjPLywy6Oboh6HW6PgLj" +
+           "LYqStqYRQHKDMQflMhXOQrnata27tvGvufrEn8ZBfmdPP2AO7NpmAAw85B8qTyjKlt1svAHTjPGL" +
+           "k4w0jAcTAyllnBoh9Kxw/tEdS8cuT0WyH4vX1PYD5qMBzQDE2eFDxz09zsscWuwVHX6a8YwaFAiM" +
+           "NAkHr4vdUdf82rQN6JwnSl4N4vAxeKdxP2A+mjXuKTvcXcY9TdOnyxPk4zKZ/vbRAqe75C3QfZZY" +
+           "0P/y6/7299z+H4QrdGsoib8JAAAAAElFTkSuQmCC"
   }
 };
 
 // The process of adding a new default snippet involves:
 //   * add a new entity to aboutHome.dtd
 //   * add a <span/> for it in aboutHome.xhtml
 //   * add an entry here in the proper ordering (based on spans)
 // The <a/> part of the snippet will be linked to the corresponding url.
@@ -198,20 +261,16 @@ function setupSearchEngine()
   if (!searchEngineInfo) {
     return;
   }
 
   // Add search engine logo.
   if (searchEngineInfo.image) {
     let logoElt = document.getElementById("searchEngineLogo");
     logoElt.src = searchEngineInfo.image;
-#ifdef XP_MACOSX
-    if (searchEngineInfo.imageHD && window.matchMedia("(min-resolution: 2dppx)"))
-      logoElt.src = searchEngineInfo.imageHD;
-#endif
     logoElt.alt = searchEngineName;
   }
 
   // The "autofocus" attribute doesn't focus the form element
   // immediately when the element is first drawn, so the
   // attribute is also used for styling when the page first loads.
   let searchText = document.getElementById("searchText");
   searchText.addEventListener("blur", function searchText_onBlur() {
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -561,24 +561,19 @@ var FullScreen = {
       document.documentElement.removeAttribute("inFullscreen");
     } else {
       gNavToolbox.setAttribute("inFullscreen", true);
       document.documentElement.setAttribute("inFullscreen", true);
     }
 
     // In tabs-on-top mode, move window controls to the tab bar,
     // and in tabs-on-bottom mode, move them back to the navigation toolbar.
-    // When there is a chance the tab bar may be collapsed, put window
-    // controls on nav bar.
     var fullscreenctls = document.getElementById("window-controls");
     var navbar = document.getElementById("nav-bar");
-    var ctlsOnTabbar = window.toolbar.visible &&
-                       (navbar.collapsed ||
-                          (TabsOnTop.enabled &&
-                           !gPrefService.getBoolPref("browser.tabs.autoHide")));
+    var ctlsOnTabbar = window.toolbar.visible && (navbar.collapsed || TabsOnTop.enabled);
     if (fullscreenctls.parentNode == navbar && ctlsOnTabbar) {
       fullscreenctls.removeAttribute("flex");
       document.getElementById("TabsToolbar").appendChild(fullscreenctls);
     }
     else if (fullscreenctls.parentNode.id == "TabsToolbar" && !ctlsOnTabbar) {
       fullscreenctls.setAttribute("flex", "1");
       navbar.appendChild(fullscreenctls);
     }
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -249,52 +249,58 @@ SocialUI = {
     // Enable the social functionality, and indicate that it was activated
     Social.activateFromOrigin(origin, function(provider) {
       // Provider to activate may not have been found
       if (!provider)
         return;
 
       // Show a warning, allow undoing the activation
       let description = document.getElementById("social-activation-message");
-      let brandShortName = document.getElementById("bundle_brand").getString("brandShortName");
-      let message = gNavigatorBundle.getFormattedString("social.activated.description",
-                                                        [provider.name, brandShortName]);
-      description.value = message;
+      let labels = description.getElementsByTagName("label");
+      let uri = Services.io.newURI(provider.origin, null, null)
+      labels[0].setAttribute("value", uri.host);
+      labels[1].setAttribute("onclick", "BrowserOpenAddonsMgr('addons://list/service'); SocialUI.activationPanel.hidePopup();")
 
       let icon = document.getElementById("social-activation-icon");
       if (provider.icon64URL || provider.icon32URL) {
         icon.setAttribute('src', provider.icon64URL || provider.icon32URL);
         icon.hidden = false;
       } else {
         icon.removeAttribute('src');
         icon.hidden = true;
       }
 
-      let notificationPanel = SocialUI.notificationPanel;
+      let notificationPanel = SocialUI.activationPanel;
       // Set the origin being activated and the previously active one, to allow undo
       notificationPanel.setAttribute("origin", provider.origin);
       notificationPanel.setAttribute("oldorigin", oldOrigin);
 
       // Show the panel
       notificationPanel.hidden = false;
       setTimeout(function () {
         notificationPanel.openPopup(SocialToolbar.button, "bottomcenter topright");
       }, 0);
     });
   },
 
   undoActivation: function SocialUI_undoActivation() {
-    let origin = this.notificationPanel.getAttribute("origin");
-    let oldOrigin = this.notificationPanel.getAttribute("oldorigin");
+    let origin = this.activationPanel.getAttribute("origin");
+    let oldOrigin = this.activationPanel.getAttribute("oldorigin");
     Social.deactivateFromOrigin(origin, oldOrigin);
-    this.notificationPanel.hidePopup();
+    this.activationPanel.hidePopup();
     Social.uninstallProvider(origin);
   },
 
-  get notificationPanel() {
+  showLearnMore: function() {
+    this.activationPanel.hidePopup();
+    let url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api";
+    openUILinkIn(url, "tab");
+  },
+
+  get activationPanel() {
     return document.getElementById("socialActivatedNotification");
   },
 
   closeSocialPanelForLinkTraversal: function (target, linkNode) {
     // No need to close the panel if this traversal was not retargeted
     if (target == "" || target == "_self")
       return;
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6142,19 +6142,19 @@ var IndexedDBPromptHelper = {
   function IndexedDBPromptHelper_init() {
     Services.obs.addObserver(this, this._permissionsPrompt, false);
     Services.obs.addObserver(this, this._quotaPrompt, false);
     Services.obs.addObserver(this, this._quotaCancel, false);
   },
 
   uninit:
   function IndexedDBPromptHelper_uninit() {
-    Services.obs.removeObserver(this, this._permissionsPrompt, false);
-    Services.obs.removeObserver(this, this._quotaPrompt, false);
-    Services.obs.removeObserver(this, this._quotaCancel, false);
+    Services.obs.removeObserver(this, this._permissionsPrompt);
+    Services.obs.removeObserver(this, this._quotaPrompt);
+    Services.obs.removeObserver(this, this._quotaCancel);
   },
 
   observe:
   function IndexedDBPromptHelper_observe(subject, topic, data) {
     if (topic != this._permissionsPrompt &&
         topic != this._quotaPrompt &&
         topic != this._quotaCancel) {
       throw new Error("Unexpected topic!");
@@ -6339,18 +6339,19 @@ function warnAboutClosingWindow() {
     exitingCanceled.data = false;
     Services.obs.notifyObservers(exitingCanceled,
                                  "last-pb-context-exiting",
                                  null);
     if (exitingCanceled.data)
       return false;
   }
 
-  if (!isPBWindow && nonPopupPresent)
-    return gBrowser.warnAboutClosingTabs(true);
+  if (nonPopupPresent) {
+    return isPBWindow || gBrowser.warnAboutClosingTabs(true);
+  }
 
   let os = Services.obs;
 
   let closingCanceled = Cc["@mozilla.org/supports-PRBool;1"].
                         createInstance(Ci.nsISupportsPRBool);
   os.notifyObservers(closingCanceled,
                      "browser-lastwindow-close-requested", null);
   if (closingCanceled.data)
@@ -6546,19 +6547,17 @@ function convertFromUnicode(charset, str
  * Re-open a closed tab.
  * @param aIndex
  *        The index of the tab (via nsSessionStore.getClosedTabData)
  * @returns a reference to the reopened tab.
  */
 function undoCloseTab(aIndex) {
   // wallpaper patch to prevent an unnecessary blank tab (bug 343895)
   var blankTabToRemove = null;
-  if (gBrowser.tabs.length == 1 &&
-      !gPrefService.getBoolPref("browser.tabs.autoHide") &&
-      isTabEmpty(gBrowser.selectedTab))
+  if (gBrowser.tabs.length == 1 && isTabEmpty(gBrowser.selectedTab))
     blankTabToRemove = gBrowser.selectedTab;
 
   var tab = null;
   var ss = Cc["@mozilla.org/browser/sessionstore;1"].
            getService(Ci.nsISessionStore);
   if (ss.getClosedTabCount(window) > (aIndex || 0)) {
     TabView.prepareUndoCloseTab(blankTabToRemove);
     tab = ss.undoCloseTab(window, aIndex || 0);
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -177,47 +177,37 @@
       </hbox>
     </panel>
 
     <panel id="socialActivatedNotification"
            type="arrow"
            hidden="true"
            consumeoutsideclicks="true"
            align="start"
+           orient="horizontal"
            role="alert">
-      <hbox flex="1">
-        <image id="social-activation-icon" class="popup-notification-icon"/>
-        <vbox flex="1">
-          <description id="social-activation-message" class="popup-notification-description"/>
+      <image id="social-activation-icon" class="popup-notification-icon"/>
+      <vbox flex="1">
+        <description id="social-activation-message" class="popup-notification-description">&social.activated.description;</description>
+        <spacer flex="1"/>
+        <hbox pack="start" align="center" class="popup-notification-button-container">
+          <label  id="social-undoactivation-button"
+                  class="text-link"
+                  value="&social.activated.undobutton.label;"
+                  accesskey="&social.activated.undobutton.accesskey;"
+                  onclick="SocialUI.undoActivation(this);"/>
           <spacer flex="1"/>
-          <hbox pack="end" align="center" class="popup-notification-button-container">
-#ifdef XP_UNIX
-        <button id="social-undoactivation-button"
-                label="&social.activated.undobutton.label;"
-                accesskey="&social.activated.undobutton.accesskey;"
-                onclick="SocialUI.undoActivation(this);"/>
-        <button default="true"
-                autofocus="autofocus"
-                label="&social.ok.label;"
-                accesskey="&social.ok.accesskey;"
-                oncommand="SocialUI.notificationPanel.hidePopup();"/>
-#else
-        <button default="true"
-                autofocus="autofocus"
-                label="&social.ok.label;"
-                accesskey="&social.ok.accesskey;"
-                oncommand="SocialUI.notificationPanel.hidePopup();"/>
-        <button id="social-undoactivation-button"
-                label="&social.activated.undobutton.label;"
-                accesskey="&social.activated.undobutton.accesskey;"
-                onclick="SocialUI.undoActivation(this);"/>
-#endif
-          </hbox>
-        </vbox>
-      </hbox>
+          <button id="social-activation-button"
+                  default="true"
+                  autofocus="autofocus"
+                  label="&social.ok.label;"
+                  accesskey="&social.ok.accesskey;"
+                  oncommand="SocialUI.activationPanel.hidePopup();"/>
+        </hbox>
+      </vbox>
     </panel>
 
     <panel id="unsharePopup"
            type="arrow"
            orient="vertical"
            ignorekeys="true"
            hidden="true"
            onpopupshown="SocialShareButton.panelShown(event);"
@@ -445,16 +435,23 @@
 
     <popupnotification id="geolocation-notification" hidden="true">
       <popupnotificationcontent orient="vertical" align="start">
         <separator class="thin"/>
         <label id="geolocation-learnmore-link" class="text-link"/>
       </popupnotificationcontent>
     </popupnotification>
 
+    <popupnotification id="servicesInstall-notification" hidden="true">
+      <popupnotificationcontent orient="vertical" align="start">
+        <separator class="thin"/>
+        <label id="servicesInstall-learnmore-link" class="text-link"/>
+      </popupnotificationcontent>
+    </popupnotification>
+
     <popupnotification id="pointerLock-notification" hidden="true">
       <popupnotificationcontent orient="vertical" align="start">
         <separator class="thin"/>
         <label id="pointerLock-cancel" value="&pointerLock.notification.message;"/>
       </popupnotificationcontent>
     </popupnotification>
 
     <popupnotification id="mixed-content-blocked-notification" hidden="true">
@@ -583,16 +580,17 @@
             <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="web-notifications-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="mixed-content-blocked-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="webRTC-shareDevices-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="webRTC-sharingDevices-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="pointerLock-notification-icon" class="notification-anchor-icon" role="button"/>
+            <image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button"/>
           </box>
           <!-- Use onclick instead of normal popup= syntax since the popup
                code fires onmousedown, and hence eats our favicon drag events.
                We only add the identity-box button to the tab order when the location bar
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                align="center"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
@@ -721,16 +719,19 @@
                       command="Social:ToggleNotifications"
                       label="&social.toggleNotifications.label;"
                       accesskey="&social.toggleNotifications.accesskey;"/>
             <menuitem class="social-toggle-menuitem" command="Social:Toggle"/>
             <menuseparator class="social-statusarea-separator"/>
             <menuseparator class="social-provider-menu" hidden="true"/>
             <menuitem class="social-addons-menuitem" command="Social:Addons"
                       label="&social.addons.label;"/>
+            <menuitem label="&social.learnMore.label;"
+                      accesskey="&social.learnMore.accesskey;"
+                      oncommand="SocialUI.showLearnMore();"/>
           </menupopup>
         </toolbarbutton>
       </toolbaritem>
 
       <toolbaritem id="bookmarks-menu-button-container"
                    class="chromeclass-toolbar-additional"
                    removable="true"
                    title="&bookmarksMenuButton.label;">
--- a/browser/base/content/pageinfo/pageInfo.xul
+++ b/browser/base/content/pageinfo/pageInfo.xul
@@ -412,17 +412,17 @@
               <radio id="fullscreen#0" command="cmd_fullscreenToggle" label="&permAskAlways;"/>
               <radio id="fullscreen#1" command="cmd_fullscreenToggle" label="&permAllow;"/>
               <radio id="fullscreen#2" command="cmd_fullscreenToggle" label="&permBlock;"/>
             </radiogroup>
           </hbox>
         </vbox>
         <vbox class="permission" id="permPointerLockRow" >
           <label class="permissionLabel" id="permPointerLockLabel"
-                 value="&permPointerLock;" control="pointerLockRadioGroup"/>
+                 value="&permPointerLock2;" control="pointerLockRadioGroup"/>
           <hbox id="permPointerLockBox" role="group" aria-labelledby="permPointerLockLabel">
             <checkbox id="pointerLockDef" command="cmd_pointerLockDef" label="&permAskAlways;"/>
             <spacer flex="1"/>
             <radiogroup id="pointerLockRadioGroup" orient="horizontal">
               <radio id="pointerLock#1" command="cmd_pointerLockToggle" label="&permAllow;"/>
               <radio id="pointerLock#2" command="cmd_pointerLockToggle" label="&permBlock;"/>
             </radiogroup>
           </hbox>
--- a/browser/base/content/socialchat.xml
+++ b/browser/base/content/socialchat.xml
@@ -22,18 +22,20 @@
 
     <implementation implements="nsIDOMEventListener">
       <constructor><![CDATA[
         let Social = Components.utils.import("resource:///modules/Social.jsm", {}).Social;
         Social.setErrorListener(this.iframe, function(iframe) {
           iframe.webNavigation.loadURI("about:socialerror?mode=compactInfo", null, null, null, null);
         });
         let iframeWindow = this.iframe.contentWindow;
-        this.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
-          this.removeEventListener("DOMContentLoaded", DOMContentLoaded);
+        this.addEventListener("DOMContentLoaded", function DOMContentLoaded(event) {
+          if (event.target != this.iframe.contentDocument)
+            return;
+          this.removeEventListener("DOMContentLoaded", DOMContentLoaded, true);
           this.isActive = !this.minimized;
           // process this._callbacks, then set to null so the chatbox creator
           // knows to make new callbacks immediately.
           for (let callback of this._callbacks) {
             if (callback)
               callback(iframeWindow);
           }
           this._callbacks = null;
@@ -43,17 +45,17 @@
             this.setAttribute("activity", true);
             this.parentNode.updateTitlebar(this);
           }.bind(this);
           iframeWindow.addEventListener("socialChatActivity", chatActivity);
           iframeWindow.addEventListener("unload", function unload() {
             iframeWindow.removeEventListener("unload", unload);
             iframeWindow.removeEventListener("socialChatActivity", chatActivity);
           });
-        });
+        }, true);
         this.setAttribute("src", this.src);
       ]]></constructor>
 
       <field name="iframe" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "iframe");
       </field>
 
       <property name="minimized">
--- a/browser/base/content/sync/progress.js
+++ b/browser/base/content/sync/progress.js
@@ -26,20 +26,20 @@ function onLoad(event) {
 }
 
 function onUnload(event) {
   cleanUpObservers();
 }
 
 function cleanUpObservers() {
   try {
-    Services.obs.removeObserver(onEngineSync, "weave:engine:sync:finish", false);
-    Services.obs.removeObserver(onEngineSync, "weave:engine:sync:error", false);
-    Services.obs.removeObserver(onServiceSync, "weave:service:sync:finish", false);
-    Services.obs.removeObserver(onServiceSync, "weave:service:sync:error", false);
+    Services.obs.removeObserver(onEngineSync, "weave:engine:sync:finish");
+    Services.obs.removeObserver(onEngineSync, "weave:engine:sync:error");
+    Services.obs.removeObserver(onServiceSync, "weave:service:sync:finish");
+    Services.obs.removeObserver(onServiceSync, "weave:service:sync:error");
   }
   catch (e) {
     // may be double called by unload & exit. Ignore.
   }
 }
 
 function onEngineSync(subject, topic, data) {
   // The Clients engine syncs first. At this point we don't necessarily know
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1449,27 +1449,28 @@
                 this._lastRelatedTab.owner = null;
               else
                 t.owner = this.selectedTab;
               this.moveTabTo(t, newTabPos);
               this._lastRelatedTab = t;
             }
 
             if (animate) {
-              this.tabContainer._handleTabTelemetryStart(t, aURI);
-
-              // kick the animation off
-              t.clientTop;
-              t.setAttribute("fadein", "true");
-
-              // This call to adjustTabstrip is redundant but needed so that
-              // when opening a second tab, the first tab's close buttons
-              // appears immediately rather than when the transition ends.
-              if (this.tabContainer.childNodes.length == 2)
-                this.tabContainer.adjustTabstrip();
+              mozRequestAnimationFrame(function () {
+                this.tabContainer._handleTabTelemetryStart(t, aURI);
+
+                // kick the animation off
+                t.setAttribute("fadein", "true");
+
+                // This call to adjustTabstrip is redundant but needed so that
+                // when opening a second tab, the first tab's close buttons
+                // appears immediately rather than when the transition ends.
+                if (this.tabContainer.childNodes.length == 2)
+                  this.tabContainer.adjustTabstrip();
+              }.bind(this));
             }
 
             return t;
           ]]>
         </body>
       </method>
 
       <method name="warnAboutClosingTabs">
@@ -3036,19 +3037,16 @@
         tabContainer: this,
 
         observe: function (subject, topic, data) {
           switch (data) {
             case "browser.tabs.closeButtons":
               this.tabContainer.mCloseButtons = Services.prefs.getIntPref(data);
               this.tabContainer.adjustTabstrip();
               break;
-            case "browser.tabs.autoHide":
-              this.tabContainer.updateVisibility();
-              break;
             case "browser.tabs.closeWindowWithLastTab":
               this.tabContainer._closeWindowWithLastTab = Services.prefs.getBoolPref(data);
               this.tabContainer.adjustTabstrip();
               break;
           }
         }
       });]]></field>
       <field name="_blockDblClick">false</field>
@@ -3116,18 +3114,17 @@
 
           TabsInTitlebar.allowedBy("tabs-visible", visible);
         ]]></body>
       </method>
 
       <method name="updateVisibility">
         <body><![CDATA[
           if (this.childNodes.length - this.tabbrowser._removingTabs.length == 1)
-            this.visible = window.toolbar.visible &&
-                           !Services.prefs.getBoolPref("browser.tabs.autoHide");
+            this.visible = window.toolbar.visible;
           else
             this.visible = true;
         ]]></body>
       </method>
 
       <method name="adjustTabstrip">
         <body><![CDATA[
           // modes for tabstrip
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -155,16 +155,17 @@ endif
                  browser_bug767836_perwindowpb.js \
                  browser_bug771331.js \
                  browser_bug783614.js \
                  browser_bug797677.js \
                  browser_bug816527.js \
                  browser_bug817947.js \
                  browser_bug822367.js \
                  browser_bug832435.js \
+                 browser_bug839103.js \
                  browser_canonizeURL.js \
                  browser_customize.js \
                  browser_findbarClose.js \
                  browser_homeDrop.js \
                  browser_keywordBookmarklets.js \
                  browser_contextSearchTabPosition.js \
                  browser_ctrlTab.js \
                  browser_customize_popupNotification.js \
@@ -204,16 +205,18 @@ endif
                  browser_tabMatchesInAwesomebar_perwindowpb.js \
                  browser_tab_drag_drop_perwindow.js \
                  bug564387.html \
                  bug564387_video1.ogv \
                  bug564387_video1.ogv^headers^ \
                  bug792517.html \
                  bug792517-2.html \
                  bug792517.sjs \
+                 test_bug839103.html \
+                 bug839103.css \
                  browser_scope.js \
                  browser_selectTabAtIndex.js \
                  browser_tab_dragdrop.js \
                  browser_tab_dragdrop2.js \
                  browser_tab_dragdrop2_frame1.xul \
                  browser_tabfocus.js \
                  browser_tabs_isActive.js \
                  browser_tabs_owner.js \
--- a/browser/base/content/test/browser_bug585785.js
+++ b/browser/base/content/test/browser_bug585785.js
@@ -1,21 +1,23 @@
 var tab;
 
 function test() {
   waitForExplicitFinish();
 
   tab = gBrowser.addTab();
-  is(tab.getAttribute("fadein"), "true", "tab opening animation initiated");
+  isnot(tab.getAttribute("fadein"), "true", "newly opened tab is yet to fade in");
 
   // Try to remove the tab right before the opening animation's first frame
   window.mozRequestAnimationFrame(checkAnimationState);
 }
 
 function checkAnimationState() {
+  is(tab.getAttribute("fadein"), "true", "tab opening animation initiated");
+
   info(window.getComputedStyle(tab).maxWidth);
   gBrowser.removeTab(tab, { animate: true });
   if (!tab.parentNode) {
     ok(true, "tab removed synchronously since the opening animation hasn't moved yet");
     finish();
     return;
   }
 
--- a/browser/base/content/test/browser_bug812562.js
+++ b/browser/base/content/test/browser_bug812562.js
@@ -63,17 +63,17 @@ function testPart2() {
   var plugin = gTestBrowser.contentDocument.getElementById("test");
   ok(!plugin, "test part 2: Should not have a plugin in this page");
 
   Services.obs.addObserver(testPart3, "PopupNotifications-updateNotShowing", false);
   gTestBrowser.contentWindow.history.back();
 }
 
 function testPart3() {
-  Services.obs.removeObserver(testPart3, "PopupNotifications-updateNotShowing", false);
+  Services.obs.removeObserver(testPart3, "PopupNotifications-updateNotShowing");
   var condition = function() PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   waitForCondition(condition, testPart4, "test part 3: waited too long for click-to-play-plugin notification");
 }
 
 function testPart4() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "test part 4: Should have a click-to-play notification");
   var plugin = gTestBrowser.contentDocument.getElementById("test");
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug839103.js
@@ -0,0 +1,85 @@
+const gTestRoot = getRootDirectory(gTestPath);
+const gStyleSheet = "bug839103.css";
+
+var gTab = null;
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.addEventListener("StyleSheetAdded", initialStylesheetAdded, true);
+  gTab = gBrowser.selectedTab = gBrowser.addTab(gTestRoot + "test_bug839103.html");
+  gTab.linkedBrowser.addEventListener("load", tabLoad, true);
+}
+
+function initialStylesheetAdded(evt) {
+  gBrowser.removeEventListener("StyleSheetAdded", initialStylesheetAdded, true);
+  ok(true, "received initial style sheet event");
+  is(evt.target, gBrowser.contentDocument, "event targets correct document");
+  ok(evt.stylesheet, "evt.stylesheet is defined");
+  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.documentSheet, "style sheet is a document sheet");
+}
+
+function tabLoad(evt) {
+  gTab.linkedBrowser.removeEventListener(evt.type, tabLoad, true);
+  executeSoon(continueTest);
+}
+
+var gLinkElement = null;
+
+function unexpectedContentEvent(evt) {
+  ok(false, "Received a " + evt.type + " event on content");
+}
+
+// We've seen the original stylesheet in the document.
+// Now add a stylesheet on the fly and make sure we see it.
+function continueTest() {
+  info("continuing test");
+
+  let doc = gBrowser.contentDocument;
+  doc.addEventListener("StyleSheetAdded", unexpectedContentEvent, false);
+  doc.addEventListener("StyleSheetRemoved", unexpectedContentEvent, false);
+  doc.defaultView.addEventListener("StyleSheetAdded", unexpectedContentEvent, false);
+  doc.defaultView.addEventListener("StyleSheetRemoved", unexpectedContentEvent, false);
+  let link = doc.createElement('link');
+  link.setAttribute('rel', 'stylesheet');
+  link.setAttribute('type', 'text/css');
+  link.setAttribute('href', gTestRoot + gStyleSheet);
+  gLinkElement = link;
+
+  gBrowser.addEventListener("StyleSheetAdded", dynamicStylesheetAdded, true);
+  doc.body.appendChild(link);
+}
+
+function dynamicStylesheetAdded(evt) {
+  gBrowser.removeEventListener("StyleSheetAdded", dynamicStylesheetAdded, true);
+  ok(true, "received dynamic style sheet event");
+  is(evt.target, gBrowser.contentDocument, "event targets correct document");
+  ok(evt.stylesheet, "evt.stylesheet is defined");
+  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.documentSheet, "style sheet is a document sheet");
+
+  gBrowser.addEventListener("StyleSheetRemoved", dynamicStylesheetRemoved, true);
+  gBrowser.contentDocument.body.removeChild(gLinkElement);
+}
+
+function dynamicStylesheetRemoved(evt) {
+  gBrowser.removeEventListener("StyleSheetRemoved", dynamicStylesheetRemoved, true);
+  ok(true, "received dynamic style sheet removal");
+  is(evt.target, gBrowser.contentDocument, "event targets correct document");
+  ok(evt.stylesheet, "evt.stylesheet is defined");
+  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.href.contains(gStyleSheet), "evt.stylesheet is the removed stylesheet");
+  executeSoon(concludeTest);
+}
+
+function concludeTest() {
+  let doc = gBrowser.contentDocument;
+  doc.removeEventListener("StyleSheetAdded", unexpectedContentEvent, false);
+  doc.removeEventListener("StyleSheetRemoved", unexpectedContentEvent, false);
+  doc.defaultView.removeEventListener("StyleSheetAdded", unexpectedContentEvent, false);
+  doc.defaultView.removeEventListener("StyleSheetRemoved", unexpectedContentEvent, false);
+  gBrowser.removeCurrentTab();
+  gLinkElement = null;
+  gTab = null;
+  finish();
+}
\ No newline at end of file
--- a/browser/base/content/test/browser_pluginnotification.js
+++ b/browser/base/content/test/browser_pluginnotification.js
@@ -349,17 +349,17 @@ function test11b() {
   ok(!popupNotification, "Test 11b, Should not have a click-to-play notification");
 
   Services.obs.addObserver(test11c, "PopupNotifications-updateNotShowing", false);
   gTestBrowser.contentWindow.history.back();
 }
 
 // Tests that the going back will reshow the notification for click-to-play plugins (part 3/4)
 function test11c() {
-  Services.obs.removeObserver(test11c, "PopupNotifications-updateNotShowing", false);
+  Services.obs.removeObserver(test11c, "PopupNotifications-updateNotShowing");
   var condition = function() PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   waitForCondition(condition, test11d, "Test 11c, waited too long for click-to-play-plugin notification");
 }
 
 // Tests that the going back will reshow the notification for click-to-play plugins (part 4/4)
 function test11d() {
   var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(popupNotification, "Test 11d, Should have a click-to-play notification");
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -695,17 +695,17 @@ var tests = [
       executeSoon(function delayedDismissal() {
         dismissNotification(popup);
       });
 
     },
     onHidden: function (popup) {
       ok(!this.notifyObj.mainActionClicked, "mainAction was not clicked because it was too soon");
       ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback was triggered");
-    },
+    }
   },
   { // Test #24  - test security delay - after delay
     run: function () {
       // Set the security delay to 10ms
       PopupNotifications.buttonDelay = 10;
 
       this.notifyObj = new basicNotification();
       showNotification(this.notifyObj);
@@ -718,17 +718,17 @@ var tests = [
         triggerMainCommand(popup);
       }, 500);
 
     },
     onHidden: function (popup) {
       ok(this.notifyObj.mainActionClicked, "mainAction was clicked after the delay");
       ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback was not triggered");
       PopupNotifications.buttonDelay = PREF_SECURITY_DELAY_INITIAL;
-    },
+    }
   },
   { // Test #25 - reload removes notification
     run: function () {
       loadURI("http://example.com/", function() {
         let notifyObj = new basicNotification();
         notifyObj.options.eventCallback = function (eventName) {
           if (eventName == "removed") {
             ok(true, "Notification removed in background tab after reloading");
@@ -822,16 +822,47 @@ var tests = [
         };
         showNotification(notifyObj);
         executeSoon(function () {
           content.document.getElementById("iframe")
                           .setAttribute("src", "http://example.org/");
         });
       });
     }
+  },
+  { // Test #29 -  Existing popup notification shouldn't disappear when adding a dismissed notification
+    run: function () {
+      this.notifyObj1 = new basicNotification();
+      this.notifyObj1.id += "_1";
+      this.notifyObj1.anchorID = "default-notification-icon";
+      this.notification1 = showNotification(this.notifyObj1);
+    },
+    onShown: function (popup) {
+      // Now show a dismissed notification, and check that it doesn't clobber
+      // the showing one.
+      this.notifyObj2 = new basicNotification();
+      this.notifyObj2.id += "_2";
+      this.notifyObj2.anchorID = "geo-notification-icon";
+      this.notifyObj2.options.dismissed = true;
+      this.notification2 = showNotification(this.notifyObj2);
+
+      checkPopup(popup, this.notifyObj1);
+
+      // check that both anchor icons are showing
+      is(document.getElementById("default-notification-icon").getAttribute("showing"), "true",
+         "notification1 anchor should be visible");
+      is(document.getElementById("geo-notification-icon").getAttribute("showing"), "true",
+         "notification2 anchor should be visible");
+
+      dismissNotification(popup);
+    },
+    onHidden: function(popup) {
+      this.notification1.remove();
+      this.notification2.remove();
+    }
   }
 ];
 
 function showNotification(notifyObj) {
   return PopupNotifications.show(notifyObj.browser,
                                  notifyObj.id,
                                  notifyObj.message,
                                  notifyObj.anchorID,
@@ -841,18 +872,20 @@ function showNotification(notifyObj) {
 }
 
 function checkPopup(popup, notificationObj) {
   info("[Test #" + gTestIndex + "] checking popup");
 
   ok(notificationObj.shownCallbackTriggered, "shown callback was triggered");
 
   let notifications = popup.childNodes;
-  is(notifications.length, 1, "only one notification displayed");
+  is(notifications.length, 1, "one notification displayed");
   let notification = notifications[0];
+  if (!notification)
+    return;
   let icon = document.getAnonymousElementByAttribute(notification, "class", "popup-notification-icon");
   if (notificationObj.id == "geolocation") {
     isnot(icon.boxObject.width, 0, "icon for geo displayed");
     is(popup.anchorNode.className, "notification-anchor-icon", "notification anchored to icon");
   }
   is(notification.getAttribute("label"), notificationObj.message, "message matches");
   is(notification.id, notificationObj.id + "-notification", "id matches");
   if (notificationObj.mainAction) {
--- a/browser/base/content/test/browser_save_link-perwindowpb.js
+++ b/browser/base/content/test/browser_save_link-perwindowpb.js
@@ -41,17 +41,20 @@ function triggerSave(aWindow, aCallback)
     MockFilePicker.displayDirectory = destDir;
     MockFilePicker.showCallback = function(fp) {
       fileName = fp.defaultString;
       destFile.append (fileName);
       MockFilePicker.returnFiles = [destFile];
       MockFilePicker.filterIndex = 1; // kSaveAsType_URL
     };
 
-    mockTransferCallback = function(a) onTransferComplete(aWindow, a, destFile, destDir);
+    mockTransferCallback = function(a) {
+      onTransferComplete(aWindow, a, destFile, destDir);
+      mockTransferCallback = function(){};
+    }
 
     // Select "Save Link As" option from context menu
     var saveLinkCommand = aWindow.document.getElementById("context-savelink");
     saveLinkCommand.doCommand();
 
     event.target.hidePopup();
   }
 
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/bug839103.css
@@ -0,0 +1,1 @@
+* {}
--- a/browser/base/content/test/social/Makefile.in
+++ b/browser/base/content/test/social/Makefile.in
@@ -10,16 +10,17 @@ relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 _BROWSER_FILES = \
                  head.js \
 		 blocklist.xml \
 		 blocklistEmpty.xml \
 		 browser_blocklist.js \
+		 browser_defaults.js \
 		 browser_addons.js \
                  browser_social_activation.js \
                  browser_social_perwindowPB.js \
                  browser_social_toolbar.js \
                  browser_social_shareButton.js \
                  browser_social_sidebar.js \
                  browser_social_flyout.js \
                  browser_social_mozSocial_API.js \
--- a/browser/base/content/test/social/browser_addons.js
+++ b/browser/base/content/test/social/browser_addons.js
@@ -3,17 +3,17 @@
 let AddonManager = Cu.import("resource://gre/modules/AddonManager.jsm", {}).AddonManager;
 let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
 
 const ADDON_TYPE_SERVICE     = "service";
 const ID_SUFFIX              = "@services.mozilla.org";
 const STRING_TYPE_NAME       = "type.%ID%.name";
 const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
 
-let manifest = { // normal provider
+let manifest = { // builtin provider
   name: "provider 1",
   origin: "https://example.com",
   sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
   workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
   iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
 };
 let manifest2 = { // used for testing install
   name: "provider 2",
@@ -21,78 +21,70 @@ let manifest2 = { // used for testing in
   sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html",
   workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
   iconURL: "https://test1.example.com/browser/browser/base/content/test/moz.png"
 };
 
 function test() {
   waitForExplicitFinish();
 
-  Services.prefs.setCharPref("social.manifest.good", JSON.stringify(manifest));
+  let prefname = getManifestPrefname(manifest);
+  setBuiltinManifestPref(prefname, manifest);
+  // ensure that manifest2 is NOT showing as builtin
+  is(SocialService.getOriginActivationType(manifest.origin), "builtin", "manifest is builtin");
+  is(SocialService.getOriginActivationType(manifest2.origin), "foreign", "manifest2 is not builtin");
+
   Services.prefs.setBoolPref("social.remote-install.enabled", true);
   runSocialTests(tests, undefined, undefined, function () {
     Services.prefs.clearUserPref("social.remote-install.enabled");
-    Services.prefs.clearUserPref("social.manifest.good");
+    // clear our builtin pref
+    ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
+    resetBuiltinManifestPref(prefname);
     // just in case the tests failed, clear these here as well
     Services.prefs.clearUserPref("social.whitelist");
     Services.prefs.clearUserPref("social.directories");
     finish();
   });
 }
 
-function installListener(next) {
+function installListener(next, aManifest) {
   let expectEvent = "onInstalling";
+  let prefname = getManifestPrefname(aManifest);
   return {
     onInstalling: function(addon) {
       is(expectEvent, "onInstalling", "install started");
-      is(addon.manifest.origin, manifest2.origin, "provider about to be installed");
+      is(addon.manifest.origin, aManifest.origin, "provider about to be installed");
+      ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
       expectEvent = "onInstalled";
     },
     onInstalled: function(addon) {
-      is(addon.manifest.origin, manifest2.origin, "provider installed");
+      is(addon.manifest.origin, aManifest.origin, "provider installed");
+      ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
       expectEvent = "onUninstalling";
     },
     onUninstalling: function(addon) {
       is(expectEvent, "onUninstalling", "uninstall started");
-      is(addon.manifest.origin, manifest2.origin, "provider about to be uninstalled");
+      is(addon.manifest.origin, aManifest.origin, "provider about to be uninstalled");
+      ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
       expectEvent = "onUninstalled";
     },
     onUninstalled: function(addon) {
       is(expectEvent, "onUninstalled", "provider has been uninstalled");
-      is(addon.manifest.origin, manifest2.origin, "provider uninstalled");
+      is(addon.manifest.origin, aManifest.origin, "provider uninstalled");
+      ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
       AddonManager.removeAddonListener(this);
       next();
     }
   };
 }
 
 var tests = {
-  testInstalledProviders: function(next) {
-    // tests that our builtin manfests are actually available to the addon
-    // manager.  We may have interference from the real builtin providers, so
-    // we will expect our test provider above to be in the list
-    AddonManager.getAddonsByTypes([ADDON_TYPE_SERVICE], function(addons) {
-      for (let addon of addons) {
-        if (addon.manifest.origin == manifest.origin) {
-          ok(true, "test addon is installed");
-          next();
-          return;
-        }
-      }
-      // failure state
-      ok(false, "test addon is not installed");
-      next();
-    });
-  },
   testAddonEnableToggle: function(next) {
-    // take the first addon in the list, and toggle its enabled state via the
-    // addon interface to see that we get events. restore the enabled state at
-    // the end.
-
     let expectEvent;
+    let prefname = getManifestPrefname(manifest);
     let listener = {
       onEnabled: function(addon) {
         is(expectEvent, "onEnabled", "provider onEnabled");
         ok(!addon.userDisabled, "provider enabled");
         executeSoon(function() {
           // restore previous state
           expectEvent = "onDisabling";
           addon.userDisabled = !addon.userDisabled;
@@ -104,42 +96,49 @@ var tests = {
       },
       onDisabled: function(addon) {
         is(expectEvent, "onDisabled", "provider onDisabled");
         ok(addon.userDisabled, "provider disabled");
         executeSoon(function() {
           // restore previous state
           AddonManager.removeAddonListener(listener);
           addon.userDisabled = !addon.userDisabled;
+          // clear the provider user-level pref
+          Services.prefs.clearUserPref(prefname);
           next();
         });
       },
       onDisabling: function(addon) {
         is(expectEvent, "onDisabling", "provider onDisabling");
         expectEvent = "onDisabled";
       }
     };
     AddonManager.addAddonListener(listener);
 
+    // we're only testing enable disable, so we quickly set the user-level pref
+    // for this provider and test enable/disable toggling
+    setManifestPref(prefname, manifest);
+    ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
     AddonManager.getAddonsByTypes([ADDON_TYPE_SERVICE], function(addons) {
       for (let addon of addons) {
         expectEvent = addon.userDisabled ? "onEnabling" : "onDisabling";
         addon.userDisabled = !addon.userDisabled;
         // only test with one addon
         return;
       }
       ok(false, "no addons toggled");
       next();
     });
   },
   testProviderEnableToggle: function(next) {
     // enable and disabel a provider from the SocialService interface, check
     // that the addon manager is updated
 
     let expectEvent;
+    let prefname = getManifestPrefname(manifest);
 
     let listener = {
       onEnabled: function(addon) {
         is(expectEvent, "onEnabled", "provider onEnabled");
         is(addon.manifest.origin, manifest.origin, "provider enabled");
         ok(!addon.userDisabled, "provider !userDisabled");
       },
       onEnabling: function(addon) {
@@ -156,65 +155,96 @@ var tests = {
         is(expectEvent, "onDisabling", "provider onDisabling");
         is(addon.manifest.origin, manifest.origin, "provider about to be disabled");
         expectEvent = "onDisabled";
       }
     };
     AddonManager.addAddonListener(listener);
 
     expectEvent = "onEnabling";
+    setManifestPref(prefname, manifest);
     SocialService.addBuiltinProvider(manifest.origin, function(provider) {
       expectEvent = "onDisabling";
       SocialService.removeProvider(provider.origin, function() {
         AddonManager.removeAddonListener(listener);
+        Services.prefs.clearUserPref(prefname);
         next();
       });
     });
   },
   testForeignInstall: function(next) {
-    AddonManager.addAddonListener(installListener(next));
+    AddonManager.addAddonListener(installListener(next, manifest2));
 
     // we expect the addon install dialog to appear, we need to accept the
     // install from the dialog.
     info("Waiting for install dialog");
-    Services.wm.addListener({
-      onWindowTitleChange: function() {},
-      onCloseWindow: function() {},
-      onOpenWindow: function(xulwindow) {
-        Services.wm.removeListener(this);
-        var domwindow = xulwindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
-                              .getInterface(Components.interfaces.nsIDOMWindow);
-        waitForFocus(function() {
-          info("Saw install dialog");
-          is(domwindow.document.location.href, XPINSTALL_URL, "Should have seen the right window open");
-          // Initially the accept button is disabled on a countdown timer
-          var button = domwindow.document.documentElement.getButton("accept");
-          button.disabled = false;
-          domwindow.document.documentElement.acceptDialog();
-        }, domwindow);
-      }
-    });
+    let panel = document.getElementById("servicesInstall-notification");
+    PopupNotifications.panel.addEventListener("popupshown", function onpopupshown() {
+      PopupNotifications.panel.removeEventListener("popupshown", onpopupshown);
+      info("servicesInstall-notification panel opened");
+      panel.button.click();
+    })
 
     let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
     addTab(activationURL, function(tab) {
       let doc = tab.linkedBrowser.contentDocument;
       let installFrom = doc.nodePrincipal.origin;
       Services.prefs.setCharPref("social.whitelist", "");
       is(SocialService.getOriginActivationType(installFrom), "foreign", "testing foriegn install");
       Social.installProvider(doc, manifest2, function(addonManifest) {
         Services.prefs.clearUserPref("social.whitelist");
         SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
           Social.uninstallProvider(addonManifest.origin);
           gBrowser.removeTab(tab);
         });
       });
     });
   },
+  testBuiltinInstallWithoutManifest: function(next) {
+    // send installProvider null for the manifest
+    AddonManager.addAddonListener(installListener(next, manifest));
+
+    let prefname = getManifestPrefname(manifest);
+    let activationURL = manifest.origin + "/browser/browser/base/content/test/social/social_activate.html"
+    addTab(activationURL, function(tab) {
+      let doc = tab.linkedBrowser.contentDocument;
+      let installFrom = doc.nodePrincipal.origin;
+      is(SocialService.getOriginActivationType(installFrom), "builtin", "testing builtin install");
+      ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
+      Social.installProvider(doc, null, function(addonManifest) {
+        ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
+        SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
+          Social.uninstallProvider(addonManifest.origin);
+          gBrowser.removeTab(tab);
+        });
+      });
+    });
+  },
+  testBuiltinInstall: function(next) {
+    // send installProvider a json object for the manifest
+    AddonManager.addAddonListener(installListener(next, manifest));
+
+    let prefname = getManifestPrefname(manifest);
+    let activationURL = manifest.origin + "/browser/browser/base/content/test/social/social_activate.html"
+    addTab(activationURL, function(tab) {
+      let doc = tab.linkedBrowser.contentDocument;
+      let installFrom = doc.nodePrincipal.origin;
+      is(SocialService.getOriginActivationType(installFrom), "builtin", "testing builtin install");
+      ok(!Services.prefs.prefHasUserValue(prefname), "manifest is not in user-prefs");
+      Social.installProvider(doc, manifest, function(addonManifest) {
+        ok(Services.prefs.prefHasUserValue(prefname), "manifest is in user-prefs");
+        SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
+          Social.uninstallProvider(addonManifest.origin);
+          gBrowser.removeTab(tab);
+        });
+      });
+    });
+  },
   testWhitelistInstall: function(next) {
-    AddonManager.addAddonListener(installListener(next));
+    AddonManager.addAddonListener(installListener(next, manifest2));
 
     let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
     addTab(activationURL, function(tab) {
       let doc = tab.linkedBrowser.contentDocument;
       let installFrom = doc.nodePrincipal.origin;
       Services.prefs.setCharPref("social.whitelist", installFrom);
       is(SocialService.getOriginActivationType(installFrom), "whitelist", "testing whitelist install");
       Social.installProvider(doc, manifest2, function(addonManifest) {
@@ -222,17 +252,17 @@ var tests = {
         SocialService.addBuiltinProvider(addonManifest.origin, function(provider) {
           Social.uninstallProvider(addonManifest.origin);
           gBrowser.removeTab(tab);
         });
       });
     });
   },
   testDirectoryInstall: function(next) {
-    AddonManager.addAddonListener(installListener(next));
+    AddonManager.addAddonListener(installListener(next, manifest2));
 
     let activationURL = manifest2.origin + "/browser/browser/base/content/test/social/social_activate.html"
     addTab(activationURL, function(tab) {
       let doc = tab.linkedBrowser.contentDocument;
       let installFrom = doc.nodePrincipal.origin;
       Services.prefs.setCharPref("social.directories", installFrom);
       is(SocialService.getOriginActivationType(installFrom), "directory", "testing directory install");
       Social.installProvider(doc, manifest2, function(addonManifest) {
--- a/browser/base/content/test/social/browser_blocklist.js
+++ b/browser/base/content/test/social/browser_blocklist.js
@@ -32,34 +32,32 @@ function test() {
     resetBlocklist(); //restore to original pref
     finish();
   });
 }
 
 var tests = {
   testSimpleBlocklist: function(next) {
     // this really just tests adding and clearing our blocklist for later tests
-    var blocklist = Components.classes["@mozilla.org/extensions/blocklist;1"]
-                        .getService(Components.interfaces.nsIBlocklistService);
     setAndUpdateBlocklist(blocklistURL, function() {
-      ok(blocklist.isAddonBlocklisted("test1.example.com@services.mozilla.org", "0", "0", "0"), "blocking 'blocked'");
-      ok(!blocklist.isAddonBlocklisted("example.com@services.mozilla.org", "0", "0", "0"), "not blocking 'good'");
+      ok(Services.blocklist.isAddonBlocklisted("test1.example.com@services.mozilla.org", "0", "0", "0"), "blocking 'blocked'");
+      ok(!Services.blocklist.isAddonBlocklisted("example.com@services.mozilla.org", "0", "0", "0"), "not blocking 'good'");
       setAndUpdateBlocklist(blocklistEmpty, function() {
-        ok(!blocklist.isAddonBlocklisted("test1.example.com@services.mozilla.org", "0", "0", "0"), "blocklist cleared");
+        ok(!Services.blocklist.isAddonBlocklisted("test1.example.com@services.mozilla.org", "0", "0", "0"), "blocklist cleared");
         next();
       });
     });
   },
   testAddingNonBlockedProvider: function(next) {
     function finish(isgood) {
       ok(isgood, "adding non-blocked provider ok");
       Services.prefs.clearUserPref("social.manifest.good");
       setAndUpdateBlocklist(blocklistEmpty, next);
     }
-    Services.prefs.setCharPref("social.manifest.good", JSON.stringify(manifest));
+    setManifestPref("social.manifest.good", manifest);
     setAndUpdateBlocklist(blocklistURL, function() {
       try {
         SocialService.addProvider(manifest, function(provider) {
           if (provider) {
             SocialService.removeProvider(provider.origin, function() {
               ok(true, "added and removed provider");
               finish(true);
             });
@@ -74,17 +72,17 @@ var tests = {
     });
   },
   testAddingBlockedProvider: function(next) {
     function finish(good) {
       ok(good, "Unable to add blocklisted provider");
       Services.prefs.clearUserPref("social.manifest.blocked");
       setAndUpdateBlocklist(blocklistEmpty, next);
     }
-    Services.prefs.setCharPref("social.manifest.blocked", JSON.stringify(manifest_bad));
+    setManifestPref("social.manifest.blocked", manifest_bad);
     setAndUpdateBlocklist(blocklistURL, function() {
       try {
         SocialService.addProvider(manifest_bad, function(provider) {
           if (provider) {
             SocialService.removeProvider(provider.origin, function() {
               finish(false);
             });
           } else {
@@ -131,17 +129,17 @@ var tests = {
       ok(true, "window closed");
     });
 
     function finish(good) {
       ok(good, "blocklisted provider removed");
       Services.prefs.clearUserPref("social.manifest.blocked");
       setAndUpdateBlocklist(blocklistEmpty, next);
     }
-    Services.prefs.setCharPref("social.manifest.blocked", JSON.stringify(manifest_bad));
+    setManifestPref("social.manifest.blocked", manifest_bad);
     SocialService.addProvider(manifest_bad, function(provider) {
       if (provider) {
         setAndUpdateBlocklist(blocklistURL, function() {
           SocialService.getProvider(provider.origin, function(p) {
             finish(p==null);
           })
         });
       } else {
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/browser_defaults.js
@@ -0,0 +1,14 @@
+
+let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+
+// this test ensures that any builtin providers have the builtin flag that we
+// need to help with "install" of a builtin.
+function test() {
+  let manifestPrefs = Services.prefs.getDefaultBranch("social.manifest.");
+  let prefs = manifestPrefs.getChildList("", []);
+  ok(prefs.length > 0, "we have builtin providers");
+  for (let pref of prefs) {
+    let manifest = JSON.parse(manifestPrefs.getComplexValue(pref, Ci.nsISupportsString).data);
+    ok(manifest.builtin, "manifest is builtin " + manifest.origin);
+  }
+}
--- a/browser/base/content/test/social/browser_social_activation.js
+++ b/browser/base/content/test/social/browser_social_activation.js
@@ -9,17 +9,17 @@ let tabsToRemove = [];
 function postTestCleanup(callback) {
   Social.provider = null;
   // any tabs opened by the test.
   for (let tab of tabsToRemove)
     gBrowser.removeTab(tab);
   tabsToRemove = [];
   // theses tests use the notification panel but don't bother waiting for it
   // to fully open - the end result is that the panel might stay open
-  SocialUI.notificationPanel.hidePopup();
+  SocialUI.activationPanel.hidePopup();
 
   Services.prefs.clearUserPref("social.whitelist");
 
   // all providers may have had their manifests added.
   for (let manifest of gProviders)
     Services.prefs.clearUserPref("social.manifest." + manifest.origin);
   // all the providers may have been added.
   let numRemoved = 0;
@@ -37,51 +37,51 @@ function postTestCleanup(callback) {
     } catch(ex) {
       // this test didn't add this provider - that's ok.
       cbRemoved();
     }
   }
 }
 
 function addBuiltinManifest(manifest) {
-  Services.prefs.setCharPref("social.manifest." + manifest.origin, JSON.stringify(manifest));
+  setManifestPref("social.manifest."+manifest.origin, manifest);
 }
 
 function addTab(url, callback) {
   let tab = gBrowser.selectedTab = gBrowser.addTab(url, {skipAnimation: true});
   tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
     tab.linkedBrowser.removeEventListener("load", tabLoad, true);
     tabsToRemove.push(tab);
     executeSoon(function() {callback(tab)});
   }, true);
 }
 
-function sendActivationEvent(tab, callback) {
+function sendActivationEvent(tab, callback, nullManifest) {
   // hack Social.lastEventReceived so we don't hit the "too many events" check.
   Social.lastEventReceived = 0;
   let doc = tab.linkedBrowser.contentDocument;
   // if our test has a frame, use it
   if (doc.defaultView.frames[0])
     doc = doc.defaultView.frames[0].document;
-  let button = doc.getElementById("activation");
+  let button = doc.getElementById(nullManifest ? "activation-old" : "activation");
   EventUtils.synthesizeMouseAtCenter(button, {}, doc.defaultView);
   executeSoon(callback);
 }
 
-function activateProvider(domain, callback) {
+function activateProvider(domain, callback, nullManifest) {
   let activationURL = domain+"/browser/browser/base/content/test/social/social_activate.html"
   addTab(activationURL, function(tab) {
-    sendActivationEvent(tab, callback);
+    sendActivationEvent(tab, callback, nullManifest);
   });
 }
 
 function activateIFrameProvider(domain, callback) {
   let activationURL = domain+"/browser/browser/base/content/test/social/social_activate_iframe.html"
   addTab(activationURL, function(tab) {
-    sendActivationEvent(tab, callback);
+    sendActivationEvent(tab, callback, false);
   });
 }
 
 let gTestDomains = ["https://example.com", "https://test1.example.com", "https://test2.example.com"];
 let gProviders = [
   {
     name: "provider 1",
     origin: "https://example.com",
@@ -112,69 +112,90 @@ function test() {
 }
 
 var tests = {
   testActivationWrongOrigin: function(next) {
     // At this stage none of our providers exist, so we expect failure.
     Services.prefs.setBoolPref("social.remote-install.enabled", false);
     activateProvider(gTestDomains[0], function() {
       is(SocialUI.enabled, false, "SocialUI is not enabled");
-      ok(SocialUI.notificationPanel.hidden, "activation panel still hidden");
+      ok(SocialUI.activationPanel.hidden, "activation panel still hidden");
       checkSocialUI();
       Services.prefs.clearUserPref("social.remote-install.enabled");
       next();
     });
   },
 
   testIFrameActivation: function(next) {
     Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
     activateIFrameProvider(gTestDomains[0], function() {
       is(SocialUI.enabled, false, "SocialUI is not enabled");
       ok(!Social.provider, "provider is not installed");
-      ok(SocialUI.notificationPanel.hidden, "activation panel still hidden");
+      ok(SocialUI.activationPanel.hidden, "activation panel still hidden");
       checkSocialUI();
       Services.prefs.clearUserPref("social.whitelist");
       next();
     });
   },
 
   testActivationFirstProvider: function(next) {
     Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
     // first up we add a manifest entry for a single provider.
     activateProvider(gTestDomains[0], function() {
-      ok(!SocialUI.notificationPanel.hidden, "activation panel should be showing");
+      ok(!SocialUI.activationPanel.hidden, "activation panel should be showing");
       is(Social.provider.origin, gTestDomains[0], "new provider is active");
       checkSocialUI();
       // hit "undo"
       document.getElementById("social-undoactivation-button").click();
       executeSoon(function() {
         // we deactivated leaving no providers left, so Social is disabled.
         ok(!Social.provider, "should be no provider left after disabling");
         checkSocialUI();
         Services.prefs.clearUserPref("social.whitelist");
         next();
       })
     });
   },
 
+  testActivationBuiltin: function(next) {
+    let prefname = getManifestPrefname(gProviders[0]);
+    setBuiltinManifestPref(prefname, gProviders[0]);
+    is(SocialService.getOriginActivationType(gTestDomains[0]), "builtin", "manifest is builtin");
+    // first up we add a manifest entry for a single provider.
+    activateProvider(gTestDomains[0], function() {
+      ok(!SocialUI.activationPanel.hidden, "activation panel should be showing");
+      is(Social.provider.origin, gTestDomains[0], "new provider is active");
+      checkSocialUI();
+      // hit "undo"
+      document.getElementById("social-undoactivation-button").click();
+      executeSoon(function() {
+        // we deactivated leaving no providers left, so Social is disabled.
+        ok(!Social.provider, "should be no provider left after disabling");
+        checkSocialUI();
+        resetBuiltinManifestPref(prefname);
+        next();
+      })
+    }, true);
+  },
+
   testActivationMultipleProvider: function(next) {
     // The trick with this test is to make sure that Social.providers[1] is
     // the current provider when doing the undo - this makes sure that the
     // Social code doesn't fallback to Social.providers[0], which it will
     // do in some cases (but those cases do not include what this test does)
     // first enable the 2 providers
     Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
     SocialService.addProvider(gProviders[0], function() {
       SocialService.addProvider(gProviders[1], function() {
         Social.provider = Social.providers[1];
         checkSocialUI();
         // activate the last provider.
         addBuiltinManifest(gProviders[2]);
         activateProvider(gTestDomains[2], function() {
-          ok(!SocialUI.notificationPanel.hidden, "activation panel should be showing");
+          ok(!SocialUI.activationPanel.hidden, "activation panel should be showing");
           is(Social.provider.origin, gTestDomains[2], "new provider is active");
           checkSocialUI();
           // hit "undo"
           document.getElementById("social-undoactivation-button").click();
           executeSoon(function() {
             // we deactivated - the first provider should be enabled.
             is(Social.provider.origin, Social.providers[1].origin, "original provider should have been reactivated");
             checkSocialUI();
@@ -190,17 +211,17 @@ var tests = {
     Services.prefs.setCharPref("social.whitelist", gTestDomains.join(","));
     SocialService.addProvider(gProviders[0], function() {
       SocialService.addProvider(gProviders[1], function() {
         Social.provider = Social.providers[1];
         checkSocialUI();
         // activate the last provider.
         addBuiltinManifest(gProviders[2]);
         activateProvider(gTestDomains[2], function() {
-          ok(!SocialUI.notificationPanel.hidden, "activation panel should be showing");
+          ok(!SocialUI.activationPanel.hidden, "activation panel should be showing");
           is(Social.provider.origin, gTestDomains[2], "new provider is active");
           checkSocialUI();
           // A bit contrived, but set a new provider current while the
           // activation ui is up.
           Social.provider = Social.providers[1];
           // hit "undo"
           document.getElementById("social-undoactivation-button").click();
           executeSoon(function() {
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -227,16 +227,51 @@ function setAndUpdateBlocklist(aURL, aCa
   Services.prefs.setCharPref("extensions.blocklist.url", aURL);
   updateBlocklist(aCallback);
 }
 
 function resetBlocklist() {
   Services.prefs.setCharPref("extensions.blocklist.url", _originalTestBlocklistURL);
 }
 
+function setManifestPref(name, manifest) {
+  let string = Cc["@mozilla.org/supports-string;1"].
+               createInstance(Ci.nsISupportsString);
+  string.data = JSON.stringify(manifest);
+  Services.prefs.setComplexValue(name, Ci.nsISupportsString, string);
+}
+
+function getManifestPrefname(aManifest) {
+  // is same as the generated name in SocialServiceInternal.getManifestPrefname
+  let originUri = Services.io.newURI(aManifest.origin, null, null);
+  return "social.manifest." + originUri.hostPort.replace('.','-');
+}
+
+function setBuiltinManifestPref(name, manifest) {
+  // we set this as a default pref, it must not be a user pref
+  manifest.builtin = true;
+  let string = Cc["@mozilla.org/supports-string;1"].
+               createInstance(Ci.nsISupportsString);
+  string.data = JSON.stringify(manifest);
+  Services.prefs.getDefaultBranch(null).setComplexValue(name, Ci.nsISupportsString, string);
+  // verify this is set on the default branch
+  let stored = Services.prefs.getComplexValue(name, Ci.nsISupportsString).data;
+  is(stored, string.data, "manifest '"+name+"' stored in default prefs");
+  // don't dirty our manifest, we'll need it without this flag later
+  delete manifest.builtin;
+  // verify we DO NOT have a user-level pref
+  ok(!Services.prefs.prefHasUserValue(name), "manifest '"+name+"' is not in user-prefs");
+}
+
+function resetBuiltinManifestPref(name) {
+  Services.prefs.getDefaultBranch(null).deleteBranch(name);
+  is(Services.prefs.getDefaultBranch(null).getPrefType(name),
+     Services.prefs.PREF_INVALID, "default manifest removed");
+}
+
 function addWindowListener(aURL, aCallback) {
   Services.wm.addListener({
     onOpenWindow: function(aXULWindow) {
       info("window opened, waiting for focus");
       Services.wm.removeListener(this);
 
       var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIDOMWindow);
--- a/browser/base/content/test/social/social_activate.html
+++ b/browser/base/content/test/social/social_activate.html
@@ -23,17 +23,23 @@ var data = {
   "version": "1.0"
 }
 
 function activate(node) {
   node.setAttribute("data-service", JSON.stringify(data));
   var event = new CustomEvent("ActivateSocialFeature");
   node.dispatchEvent(event);
 }
+
+function oldActivate(node) {
+  var event = new CustomEvent("ActivateSocialFeature");
+  document.dispatchEvent(event);
+}
 </script>
 <body>
 
 nothing to see here
 
+<button id="activation-old" onclick="oldActivate(this)">Activate The Demo Provider</button>
 <button id="activation" onclick="activate(this)">Activate The Demo Provider</button>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/test_bug839103.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Document for Bug 839103</title>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+</body>
+</html>
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -30,30 +30,28 @@ browser.jar:
         content/browser/abouthome/history.png         (content/abouthome/history.png)
         content/browser/abouthome/apps.png            (content/abouthome/apps.png)
         content/browser/abouthome/addons.png          (content/abouthome/addons.png)
         content/browser/abouthome/sync.png            (content/abouthome/sync.png)
         content/browser/abouthome/settings.png        (content/abouthome/settings.png)
         content/browser/abouthome/restore.png         (content/abouthome/restore.png)
         content/browser/abouthome/restore-large.png   (content/abouthome/restore-large.png)
         content/browser/abouthome/mozilla.png         (content/abouthome/mozilla.png)
-#ifdef XP_MACOSX
         content/browser/abouthome/snippet1@2x.png      (content/abouthome/snippet1@2x.png)
         content/browser/abouthome/snippet2@2x.png      (content/abouthome/snippet2@2x.png)
         content/browser/abouthome/downloads@2x.png     (content/abouthome/downloads@2x.png)
         content/browser/abouthome/bookmarks@2x.png     (content/abouthome/bookmarks@2x.png)
         content/browser/abouthome/history@2x.png       (content/abouthome/history@2x.png)
         content/browser/abouthome/apps@2x.png          (content/abouthome/apps@2x.png)
         content/browser/abouthome/addons@2x.png        (content/abouthome/addons@2x.png)
         content/browser/abouthome/sync@2x.png          (content/abouthome/sync@2x.png)
         content/browser/abouthome/settings@2x.png      (content/abouthome/settings@2x.png)
         content/browser/abouthome/restore@2x.png       (content/abouthome/restore@2x.png)
         content/browser/abouthome/restore-large@2x.png (content/abouthome/restore-large@2x.png)
         content/browser/abouthome/mozilla@2x.png       (content/abouthome/mozilla@2x.png)
-#endif
 #ifdef MOZ_SERVICES_HEALTHREPORT
         content/browser/abouthealthreport/abouthealth.xhtml   (content/abouthealthreport/abouthealth.xhtml)
         content/browser/abouthealthreport/abouthealth.js      (content/abouthealthreport/abouthealth.js)
         content/browser/abouthealthreport/abouthealth.css     (content/abouthealthreport/abouthealth.css)
 #endif
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
         content/browser/aboutSocialError.xhtml        (content/aboutSocialError.xhtml)
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -12,19 +12,17 @@
 namespace mozilla {
 namespace browser {
 
 NS_IMPL_ISUPPORTS1(AboutRedirector, nsIAboutModule)
 
 struct RedirEntry {
   const char* id;
   const char* url;
-  uint32_t flags;  // See nsIAboutModule.  The URI_SAFE_FOR_UNTRUSTED_CONTENT
-                   // flag does double duty here -- if it's not set, we don't
-                   // drop chrome privileges.
+  uint32_t flags;
 };
 
 /*
   Entries which do not have URI_SAFE_FOR_UNTRUSTED_CONTENT will run with chrome
   privileges. This is potentially dangerous. Please use
   URI_SAFE_FOR_UNTRUSTED_CONTENT in the third argument to each map item below
   unless your about: page really needs chrome privileges. Security review is
   required before adding new map entries without
@@ -123,38 +121,16 @@ AboutRedirector::NewChannel(nsIURI *aURI
     if (!strcmp(path.get(), kRedirMap[i].id)) {
       nsCOMPtr<nsIChannel> tempChannel;
       rv = ioService->NewChannel(nsDependentCString(kRedirMap[i].url),
                                  nullptr, nullptr, getter_AddRefs(tempChannel));
       NS_ENSURE_SUCCESS(rv, rv);
 
       tempChannel->SetOriginalURI(aURI);
 
-      // Keep the page from getting unnecessary privileges unless it needs them
-      if (kRedirMap[i].flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) {
-        if (path.EqualsLiteral("feeds")) {
-          nsCOMPtr<nsIScriptSecurityManager> securityManager =
-            do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
-          NS_ENSURE_SUCCESS(rv, rv);
-  
-          nsCOMPtr<nsIPrincipal> principal;
-          rv = securityManager->GetNoAppCodebasePrincipal(aURI, getter_AddRefs(principal));
-          NS_ENSURE_SUCCESS(rv, rv);
-  
-          rv = tempChannel->SetOwner(principal);
-        }
-        else {
-          // Setting the owner to null means that we'll go through the normal
-          // path in GetChannelPrincipal and create a codebase principal based
-          // on the channel's originalURI
-          rv = tempChannel->SetOwner(nullptr);
-          NS_ENSURE_SUCCESS(rv, rv);
-        }
-      }
-
       NS_ADDREF(*result = tempChannel);
       return rv;
     }
   }
 
   return NS_ERROR_ILLEGAL_VALUE;
 }
 
--- a/browser/components/feeds/src/FeedConverter.js
+++ b/browser/components/feeds/src/FeedConverter.js
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
 /* 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/. */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/debug.js");
+Components.utils.import("resource://gre/modules/Services.jsm");
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
 function LOG(str) {
   dump("*** " + str + "\n");
 }
@@ -18,18 +19,16 @@ const FS_CONTRACTID = "@mozilla.org/brow
 const FPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=feed";
 const PCPH_CONTRACTID = "@mozilla.org/network/protocol;1?name=pcast";
 
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
 const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
 const TYPE_ANY = "*/*";
 
-const FEEDHANDLER_URI = "about:feeds";
-
 const PREF_SELECTED_APP = "browser.feeds.handlers.application";
 const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
 const PREF_SELECTED_ACTION = "browser.feeds.handler";
 const PREF_SELECTED_READER = "browser.feeds.handler.default";
 
 const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
 const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
 const PREF_VIDEO_SELECTED_ACTION = "browser.videoFeeds.handler";
@@ -241,22 +240,24 @@ FeedConverter.prototype = {
       // if the parser returned a document.
       if (result.doc) {
 
         // Store the result in the result service so that the display
         // page can access it.
         feedService.addFeedResult(result);
 
         // Now load the actual XUL document.
-        var chromeURI = ios.newURI(FEEDHANDLER_URI, null, null);
-        chromeChannel = ios.newChannelFromURI(chromeURI, null);
+        var aboutFeedsURI = ios.newURI("about:feeds", null, null);
+        chromeChannel = ios.newChannelFromURI(aboutFeedsURI, null);
         chromeChannel.originalURI = result.uri;
+        chromeChannel.owner =
+          Services.scriptSecurityManager.getNoAppCodebasePrincipal(aboutFeedsURI);
+      } else {
+        chromeChannel = ios.newChannelFromURI(result.uri, null);
       }
-      else
-        chromeChannel = ios.newChannelFromURI(result.uri, null);
 
       chromeChannel.loadGroup = this._request.loadGroup;
       chromeChannel.asyncOpen(this._listener, null);
     }
     finally {
       this._releaseHandles();
     }
   },
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -46,17 +46,16 @@ function makeURI(aURLSpec, aCharset) {
 
 const XML_NS = "http://www.w3.org/XML/1998/namespace"
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
 const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
 const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
 const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
-const FEEDHANDLER_URI = "about:feeds";
 
 const PREF_SELECTED_APP = "browser.feeds.handlers.application";
 const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
 const PREF_SELECTED_ACTION = "browser.feeds.handler";
 const PREF_SELECTED_READER = "browser.feeds.handler.default";
 
 const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
 const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
@@ -1097,17 +1096,17 @@ FeedWriter.prototype = {
    */
   _getOriginalURI: function FW__getOriginalURI(aWindow) {
     var chan = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).
                getInterface(Ci.nsIWebNavigation).
                QueryInterface(Ci.nsIDocShell).currentDocumentChannel;
 
     var resolvedURI = Cc["@mozilla.org/network/io-service;1"].
                       getService(Ci.nsIIOService).
-                      newChannel(FEEDHANDLER_URI, null, null).URI;
+                      newChannel("about:feeds", null, null).URI;
 
     if (resolvedURI.equals(chan.URI))
       return chan.originalURI;
 
     return null;
   },
 
   _window: null,
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -361,18 +361,18 @@ BrowserGlue.prototype = {
     os.removeObserver(this, "browser:purge-session-history");
     os.removeObserver(this, "quit-application-requested");
     os.removeObserver(this, "quit-application-granted");
 #ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
     os.removeObserver(this, "browser-lastwindow-close-requested");
     os.removeObserver(this, "browser-lastwindow-close-granted");
 #endif
 #ifdef MOZ_SERVICES_SYNC
-    os.removeObserver(this, "weave:service:ready", false);
-    os.removeObserver(this, "weave:engine:clients:display-uri", false);
+    os.removeObserver(this, "weave:service:ready");
+    os.removeObserver(this, "weave:engine:clients:display-uri");
 #endif
     os.removeObserver(this, "session-save");
     if (this._isIdleObserver)
       this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
     if (this._isPlacesInitObserver)
       os.removeObserver(this, "places-init-complete");
     if (this._isPlacesLockedObserver)
       os.removeObserver(this, "places-database-locked");
@@ -726,17 +726,17 @@ BrowserGlue.prototype = {
                 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
                 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2 +
                 promptService.BUTTON_POS_0_DEFAULT;
 
     var neverAsk = {value:false};
     var button0Title = quitBundle.GetStringFromName("saveTitle");
     var button1Title = quitBundle.GetStringFromName("cancelTitle");
     var button2Title = quitBundle.GetStringFromName("quitTitle");
-    var neverAskText = quitBundle.GetStringFromName("neverAsk");
+    var neverAskText = quitBundle.GetStringFromName("neverAsk2");
 
     // This wouldn't have been set above since we shouldn't be here for
     // aQuitType == "lastwindow"
     mostRecentBrowserWindow = Services.wm.getMostRecentWindow("navigator:browser");
 
     var buttonChoice =
       promptService.confirmEx(mostRecentBrowserWindow, quitDialogTitle, message,
                               flags, button0Title, button1Title, button2Title,
@@ -1812,25 +1812,25 @@ ContentPermissionPrompt.prototype = {
 
   _promptPointerLock: function CPP_promtPointerLock(aRequest, autoAllow) {
 
     let browserBundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
     let requestingURI = aRequest.principal.URI;
 
     let originString = requestingURI.schemeIs("file") ? requestingURI.path : requestingURI.host;
     let message = browserBundle.formatStringFromName(autoAllow ?
-                                  "pointerLock.autoLock.title" : "pointerLock.title",
+                                  "pointerLock.autoLock.title2" : "pointerLock.title2",
                                   [originString], 1);
     // If this is an autoAllow info prompt, offer no actions.
     // _showPrompt() will allow the request when it's dismissed.
     let actions = [];
     if (!autoAllow) {
       actions = [
         {
-          stringId: "pointerLock.allow",
+          stringId: "pointerLock.allow2",
           action: null,
           expireType: null,
           callback: function() {},
         },
         {
           stringId: "pointerLock.alwaysAllow",
           action: Ci.nsIPermissionManager.ALLOW_ACTION,
           expireType: null,
--- a/browser/components/preferences/aboutPermissions.js
+++ b/browser/components/preferences/aboutPermissions.js
@@ -432,20 +432,20 @@ let AboutPermissions = {
       Services.prefs.removeObserver("signon.rememberSignons", this, false);
       Services.prefs.removeObserver("network.cookie.", this, false);
       Services.prefs.removeObserver("geo.enabled", this, false);
       Services.prefs.removeObserver("dom.indexedDB.enabled", this, false);
       Services.prefs.removeObserver("dom.disable_open_during_load", this, false);
       Services.prefs.removeObserver("plugins.click_to_play", this, false);
       Services.prefs.removeObserver("full-screen-api.enabled", this, false);
 
-      Services.obs.removeObserver(this, "perm-changed", false);
-      Services.obs.removeObserver(this, "passwordmgr-storage-changed", false);
-      Services.obs.removeObserver(this, "cookie-changed", false);
-      Services.obs.removeObserver(this, "browser:purge-domain-data", false);
+      Services.obs.removeObserver(this, "perm-changed");
+      Services.obs.removeObserver(this, "passwordmgr-storage-changed");
+      Services.obs.removeObserver(this, "cookie-changed");
+      Services.obs.removeObserver(this, "browser:purge-domain-data");
     }
 
     gSitesStmt.finalize();
     gVisitStmt.finalize();
     gPlacesDatabase.asyncClose(null);
   },
 
   observe: function (aSubject, aTopic, aData) {
--- a/browser/components/preferences/in-content/tabs.js
+++ b/browser/components/preferences/in-content/tabs.js
@@ -7,19 +7,16 @@ var gTabsPane = {
   /*
    * Preferences:
    *
    * browser.link.open_newwindow
    * - determines where pages which would open in a new window are opened:
    *     1 opens such links in the most recent window or tab,
    *     2 opens such links in a new window,
    *     3 opens such links in a new tab
-   * browser.tabs.autoHide
-   * - true if the tab bar is hidden when only one tab is open, false to always
-   *   show it
    * browser.tabs.loadInBackground
    * - true if display should switch to a new tab which has been opened from a
    *   link, false if display shouldn't switch
    * browser.tabs.warnOnClose
    * - true if when closing a window with multiple tabs the user is warned and
    *   allowed to cancel the action, false to just close the window
    * browser.tabs.warnOnOpen
    * - true if the user should be warned if he attempts to open a lot of tabs at
--- a/browser/components/preferences/in-content/tabs.xul
+++ b/browser/components/preferences/in-content/tabs.xul
@@ -4,20 +4,16 @@
 
 <script type="application/javascript"
         src="chrome://browser/content/preferences/in-content/tabs.js"/>
 
 <preferences id="tabsPreferences">
   <preference id="browser.link.open_newwindow"
               name="browser.link.open_newwindow"
               type="int"/>
-  <preference id="browser.tabs.autoHide"
-              name="browser.tabs.autoHide"
-              type="bool"
-              inverted="true"/>
   <preference id="browser.tabs.loadInBackground"
               name="browser.tabs.loadInBackground"
               type="bool"
               inverted="true"/>
   <preference id="browser.tabs.warnOnClose"
               name="browser.tabs.warnOnClose"
               type="bool"/>
   <preference id="browser.tabs.warnOnOpen"
@@ -53,21 +49,16 @@
           class="indent"/>
 
 <checkbox id="warnOpenMany" label="&warnOpenManyTabs.label;"
           data-category="paneTabs" hidden="true"
           accesskey="&warnOpenManyTabs.accesskey;"
           preference="browser.tabs.warnOnOpen"
           class="indent"/>
 
-<checkbox id="showTabBar" label="&showTabBar.label;"
-          data-category="paneTabs" hidden="true"
-          accesskey="&showTabBar.accesskey;"
-          preference="browser.tabs.autoHide"
-          class="indent"/>
 
 <checkbox id="restoreOnDemand" label="&restoreTabsOnDemand.label;"
           data-category="paneTabs" hidden="true"
           accesskey="&restoreTabsOnDemand.accesskey;"
           preference="browser.sessionstore.restore_on_demand"
           class="indent"/>
 
 <checkbox id="switchToNewTabs" label="&switchToNewTabs.label;"
--- a/browser/components/preferences/tabs.js
+++ b/browser/components/preferences/tabs.js
@@ -8,19 +8,16 @@ var gTabsPane = {
   /*
    * Preferences:
    *
    * browser.link.open_newwindow
    * - determines where pages which would open in a new window are opened:
    *     1 opens such links in the most recent window or tab,
    *     2 opens such links in a new window,
    *     3 opens such links in a new tab
-   * browser.tabs.autoHide
-   * - true if the tab bar is hidden when only one tab is open, false to always
-   *   show it
    * browser.tabs.loadInBackground
    * - true if display should switch to a new tab which has been opened from a
    *   link, false if display shouldn't switch
    * browser.tabs.warnOnClose
    * - true if when closing a window with multiple tabs the user is warned and
    *   allowed to cancel the action, false to just close the window
    * browser.tabs.warnOnOpen
    * - true if the user should be warned if he attempts to open a lot of tabs at
--- a/browser/components/preferences/tabs.xul
+++ b/browser/components/preferences/tabs.xul
@@ -18,17 +18,16 @@
   <prefpane id="paneTabs"
 #ifdef XP_WIN
             onpaneload="gTabsPane.init();"
 #endif
             helpTopic="prefs-tabs">
 
     <preferences id="tabsPreferences">
       <preference id="browser.link.open_newwindow"     name="browser.link.open_newwindow"     type="int"/>
-      <preference id="browser.tabs.autoHide"           name="browser.tabs.autoHide"           type="bool" inverted="true"/>
       <preference id="browser.tabs.loadInBackground"   name="browser.tabs.loadInBackground"   type="bool" inverted="true"/>
       <preference id="browser.tabs.warnOnClose"        name="browser.tabs.warnOnClose"        type="bool"/>
       <preference id="browser.tabs.warnOnOpen"         name="browser.tabs.warnOnOpen"         type="bool"/>
       <preference id="browser.sessionstore.restore_on_demand" name="browser.sessionstore.restore_on_demand" type="bool"/>
 #ifdef XP_WIN
       <preference id="browser.taskbar.previews.enable" name="browser.taskbar.previews.enable" type="bool"/>
 #endif
     </preferences>
@@ -44,19 +43,16 @@
                 onsyncfrompreference="return gTabsPane.readLinkTarget();"
                 onsynctopreference="return gTabsPane.writeLinkTarget();"/>
       <checkbox id="warnCloseMultiple" label="&warnCloseMultipleTabs.label;"
                 accesskey="&warnCloseMultipleTabs.accesskey;"
                 preference="browser.tabs.warnOnClose"/>
       <checkbox id="warnOpenMany" label="&warnOpenManyTabs.label;"
                 accesskey="&warnOpenManyTabs.accesskey;"
                 preference="browser.tabs.warnOnOpen"/>
-      <checkbox id="showTabBar" label="&showTabBar.label;"
-                accesskey="&showTabBar.accesskey;"
-                preference="browser.tabs.autoHide"/>
       <checkbox id="restoreOnDemand" label="&restoreTabsOnDemand.label;"
                 accesskey="&restoreTabsOnDemand.accesskey;"
                 preference="browser.sessionstore.restore_on_demand"/>
       <checkbox id="switchToNewTabs" label="&switchToNewTabs.label;"
                 accesskey="&switchToNewTabs.accesskey;"
                 preference="browser.tabs.loadInBackground"/>
 #ifdef XP_WIN
       <checkbox id="showTabsInTaskbar" label="&showTabsInTaskbar.label;"
--- a/browser/components/preferences/tests/browser_chunk_permissions.js
+++ b/browser/components/preferences/tests/browser_chunk_permissions.js
@@ -67,23 +67,23 @@ function runNextTest() {
     waitForClearHistory(finish);
     return;
   }
 
   let nextTest = tests[gTestIndex++];
   info(nextTest.desc);
 
   function preinit_observer() {
-    Services.obs.removeObserver(preinit_observer, "browser-permissions-preinit", false);
+    Services.obs.removeObserver(preinit_observer, "browser-permissions-preinit");
     nextTest.preInit();
   }
   Services.obs.addObserver(preinit_observer, "browser-permissions-preinit", false);
 
   function init_observer() {
-    Services.obs.removeObserver(init_observer, "browser-permissions-initialized", false);
+    Services.obs.removeObserver(init_observer, "browser-permissions-initialized");
     nextTest.run();
   }
   Services.obs.addObserver(init_observer, "browser-permissions-initialized", false);
 
   // open about:permissions
   let tab = gBrowser.selectedTab = gBrowser.addTab("about:permissions");
   registerCleanupFunction(function() {
     gBrowser.removeTab(tab);
--- a/browser/components/preferences/tests/browser_permissions.js
+++ b/browser/components/preferences/tests/browser_permissions.js
@@ -56,17 +56,17 @@ function test() {
       }
     }
 
     // open about:permissions
     gBrowser.selectedTab = gBrowser.addTab("about:permissions");
   });
 
   function observer() {
-    Services.obs.removeObserver(observer, "browser-permissions-initialized", false);
+    Services.obs.removeObserver(observer, "browser-permissions-initialized");
     runNextTest();
   }
   Services.obs.addObserver(observer, "browser-permissions-initialized", false);
 }
 
 function cleanUp() {
   for (let type in TEST_PERMS) {
     if (type != "password") {
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_DownloadLastDirWithCPS.js
@@ -3,27 +3,61 @@
  * 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/. */
 
 let gTests;
 function test() {
   waitForExplicitFinish();
   requestLongerTimeout(2);
   gTests = runTest();
-  moveAlong();
+  gTests.next();
 }
 
-function moveAlong() {
+/*
+ * ================
+ * Helper functions
+ * ================
+ */
+
+function moveAlong(aResult) {
   try {
-    gTests.next();
+    gTests.send(aResult);
   } catch (x if x instanceof StopIteration) {
     finish();
   }
 }
 
+function createWindow(aOptions) {
+  whenNewWindowLoaded(aOptions, function(win) {
+    moveAlong(win);
+  });
+}
+
+function getFile(downloadLastDir, aURI) {
+  downloadLastDir.getFileAsync(aURI, function(result) {
+    moveAlong(result);
+  });
+}
+
+function setFile(downloadLastDir, aURI, aValue) {
+  downloadLastDir.setFile(aURI, aValue);
+  executeSoon(moveAlong);
+}
+
+function clearHistoryAndWait() {
+  clearHistory();
+  executeSoon(function() executeSoon(moveAlong));
+}
+
+/*
+ * ===================
+ * Function with tests
+ * ===================
+ */
+
 function runTest() {
   let FileUtils =
     Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
   let DownloadLastDir =
     Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}).DownloadLastDir;
 
   let tmpDir = FileUtils.getDir("TmpD", [], true);
   let dir1 = newDirectory();
@@ -35,219 +69,211 @@ function runTest() {
   let uri3 = Services.io.newURI("http://test3.com/", null, null);
   let uri4 = Services.io.newURI("http://test4.com/", null, null);
 
   // cleanup functions registration
   registerCleanupFunction(function () {
     Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
     Services.prefs.clearUserPref("browser.download.lastDir");
     [dir1, dir2, dir3].forEach(function(dir) dir.remove(true));
+    win.close();
+    pbWin.close();
   });
 
-  function testOnWindow(aPrivate, aCallback) {
-    whenNewWindowLoaded({private: aPrivate}, function(win) {
-      let gDownloadLastDir = new DownloadLastDir(win);
-      aCallback(win, gDownloadLastDir);
-      gDownloadLastDir.cleanupPrivateFile();
-      win.close();
-      executeSoon(moveAlong);
-    });
+  function checkDownloadLastDir(gDownloadLastDir, aLastDir) {
+    is(gDownloadLastDir.file.path, aLastDir.path,
+       "gDownloadLastDir should point to the expected last directory");
+    getFile(gDownloadLastDir, uri1);
   }
 
-  function checkInit(aWin, gDownloadLastDir) {
-    is(typeof gDownloadLastDir, "object",
-       "gDownloadLastDir should be a valid object");
-    is(gDownloadLastDir.file, null,
-       "LastDir pref should be null to start with");
-
-    // set up last dir
-    gDownloadLastDir.setFile(null, tmpDir);
-    is(gDownloadLastDir.file.path, tmpDir.path,
-       "LastDir should point to the tmpDir");
-    isnot(gDownloadLastDir.file, tmpDir,
-          "gDownloadLastDir.file should not be pointing to tmpDir");
-
-    // set uri1 to dir1, all should now return dir1
-    // also check that a new object is returned
-    gDownloadLastDir.setFile(uri1, dir1);
-    is(gDownloadLastDir.file.path, dir1.path,
-       "gDownloadLastDir should return dir1");
-    isnot(gDownloadLastDir.file, dir1,
-          "gDownloadLastDir.file should not return dir1");
-    is(gDownloadLastDir.getFile(uri1).path, dir1.path,
-       "uri1 should return dir1"); // set in CPS
-    isnot(gDownloadLastDir.getFile(uri1), dir1,
-          "getFile on uri1 should not return dir1");
-    is(gDownloadLastDir.getFile(uri2).path, dir1.path,
-       "uri2 should return dir1"); // fallback
-    isnot(gDownloadLastDir.getFile(uri2), dir1,
-          "getFile on uri2 should not return dir1");
-    is(gDownloadLastDir.getFile(uri3).path, dir1.path,
-       "uri3 should return dir1"); // fallback
-    isnot(gDownloadLastDir.getFile(uri3), dir1,
-          "getFile on uri3 should not return dir1");
-    is(gDownloadLastDir.getFile(uri4).path, dir1.path,
-       "uri4 should return dir1"); // fallback
-    isnot(gDownloadLastDir.getFile(uri4), dir1,
-          "getFile on uri4 should not return dir1");
-
-    // set uri2 to dir2, all except uri1 should now return dir2
-    gDownloadLastDir.setFile(uri2, dir2);
-    is(gDownloadLastDir.file.path, dir2.path,
-       "gDownloadLastDir should point to dir2");
-    is(gDownloadLastDir.getFile(uri1).path, dir1.path,
-       "uri1 should return dir1"); // set in CPS
-    is(gDownloadLastDir.getFile(uri2).path, dir2.path,
-       "uri2 should return dir2"); // set in CPS
-    is(gDownloadLastDir.getFile(uri3).path, dir2.path,
-       "uri3 should return dir2"); // fallback
-    is(gDownloadLastDir.getFile(uri4).path, dir2.path,
-       "uri4 should return dir2"); // fallback
-
-    // set uri3 to dir3, all except uri1 and uri2 should now return dir3
-    gDownloadLastDir.setFile(uri3, dir3);
-    is(gDownloadLastDir.file.path, dir3.path,
-       "gDownloadLastDir should point to dir3");
-    is(gDownloadLastDir.getFile(uri1).path, dir1.path,
-       "uri1 should return dir1"); // set in CPS
-    is(gDownloadLastDir.getFile(uri2).path, dir2.path,
-       "uri2 should return dir2"); // set in CPS
-    is(gDownloadLastDir.getFile(uri3).path, dir3.path,
-       "uri3 should return dir3"); // set in CPS
-    is(gDownloadLastDir.getFile(uri4).path, dir3.path,
-       "uri4 should return dir4"); // fallback
-
-    // set uri1 to dir2, all except uri3 should now return dir2
-    gDownloadLastDir.setFile(uri1, dir2);
-    is(gDownloadLastDir.file.path, dir2.path,
-       "gDownloadLastDir should point to dir2");
-    is(gDownloadLastDir.getFile(uri1).path, dir2.path,
-       "uri1 should return dir2"); // set in CPS
-    is(gDownloadLastDir.getFile(uri2).path, dir2.path,
-       "uri2 should return dir2"); // set in CPS
-    is(gDownloadLastDir.getFile(uri3).path, dir3.path,
-       "uri3 should return dir3"); // set in CPS
-    is(gDownloadLastDir.getFile(uri4).path, dir2.path,
-       "uri4 should return dir2"); // fallback
-
-    // check clearHistory removes all data
-    clearHistory();
-    is(gDownloadLastDir.file, null, "clearHistory removes all data");
-    is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir", null),
-       false, "LastDir preference should be absent");
-    is(gDownloadLastDir.getFile(uri1), null, "uri1 should point to null");
-    is(gDownloadLastDir.getFile(uri2), null, "uri2 should point to null");
-    is(gDownloadLastDir.getFile(uri3), null, "uri3 should point to null");
-    is(gDownloadLastDir.getFile(uri4), null, "uri4 should point to null");
-  }
-
-  function checkDownloadLastDir(aWin, gDownloadLastDir, aLastDir) {
-    is(gDownloadLastDir.file.path, aLastDir.path,
-       "gDownloadLastDir should point to the expected last directory");
-    is(gDownloadLastDir.getFile(uri1).path, aLastDir.path,
-       "uri1 should return the expected last directory");
+  function checkDownloadLastDirNull(gDownloadLastDir) {
+    is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
+    getFile(gDownloadLastDir, uri1);
   }
 
-  function checkDownloadLastDirNull(aWin, gDownloadLastDir) {
-    is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
-    is(gDownloadLastDir.getFile(uri1), null, "uri1 should return null");
-  }
+  /*
+   * ================================
+   * Create a regular and a PB window
+   * ================================
+   */
+
+  let win = yield createWindow({private: false});
+  let pbWin = yield createWindow({private: true});
+
+  let downloadLastDir = new DownloadLastDir(win);
+  let pbDownloadLastDir = new DownloadLastDir(pbWin);
 
-  function checkSetFile(gDownloadLastDir, aDir1, aDir2, aDir3) {
-    // check that disabling CPS works
-    Services.prefs.setBoolPref("browser.download.lastDir.savePerSite", false);
+  /*
+   * ==================
+   * Beginning of tests
+   * ==================
+   */
 
-    gDownloadLastDir.setFile(uri1, aDir1);
-    is(gDownloadLastDir.file.path, aDir1.path, "LastDir should be set to dir1");
-    is(gDownloadLastDir.getFile(uri1).path, aDir1.path, "uri1 should return dir1");
-    is(gDownloadLastDir.getFile(uri2).path, aDir1.path, "uri2 should return dir1");
-    is(gDownloadLastDir.getFile(uri3).path, aDir1.path, "uri3 should return dir1");
-    is(gDownloadLastDir.getFile(uri4).path, aDir1.path, "uri4 should return dir1");
+  is(typeof downloadLastDir, "object",
+     "downloadLastDir should be a valid object");
+  is(downloadLastDir.file, null,
+     "LastDir pref should be null to start with");
+
+  // set up last dir
+  yield setFile(downloadLastDir, null, tmpDir);
+  is(downloadLastDir.file.path, tmpDir.path,
+     "LastDir should point to the tmpDir");
+  isnot(downloadLastDir.file, tmpDir,
+        "downloadLastDir.file should not be pointing to tmpDir");
 
-    gDownloadLastDir.setFile(uri2, aDir2);
-    is(gDownloadLastDir.file.path, aDir2.path, "LastDir should be set to dir2");
-    is(gDownloadLastDir.getFile(uri1).path, aDir2.path, "uri1 should return dir2");
-    is(gDownloadLastDir.getFile(uri2).path, aDir2.path, "uri2 should return dir2");
-    is(gDownloadLastDir.getFile(uri3).path, aDir2.path, "uri3 should return dir2");
-    is(gDownloadLastDir.getFile(uri4).path, aDir2.path, "uri4 should return dir2");
+  // set uri1 to dir1, all should now return dir1
+  // also check that a new object is returned
+  yield setFile(downloadLastDir, uri1, dir1);
+  is(downloadLastDir.file.path, dir1.path,
+     "downloadLastDir should return dir1");
+  isnot(downloadLastDir.file, dir1,
+        "downloadLastDir.file should not return dir1");
+  is((yield getFile(downloadLastDir, uri1)).path, dir1.path,
+     "uri1 should return dir1"); // set in CPS
+  isnot((yield getFile(downloadLastDir, uri1)), dir1,
+        "getFile on uri1 should not return dir1");
+  is((yield getFile(downloadLastDir, uri2)).path, dir1.path,
+     "uri2 should return dir1"); // fallback
+  isnot((yield getFile(downloadLastDir, uri2)), dir1,
+        "getFile on uri2 should not return dir1");
+  is((yield getFile(downloadLastDir, uri3)).path, dir1.path,
+     "uri3 should return dir1"); // fallback
+  isnot((yield getFile(downloadLastDir, uri3)), dir1,
+        "getFile on uri3 should not return dir1");
+  is((yield getFile(downloadLastDir, uri4)).path, dir1.path,
+     "uri4 should return dir1"); // fallback
+  isnot((yield getFile(downloadLastDir, uri4)), dir1,
+        "getFile on uri4 should not return dir1");
 
-    Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
+  // set uri2 to dir2, all except uri1 should now return dir2
+  yield setFile(downloadLastDir, uri2, dir2);
+  is(downloadLastDir.file.path, dir2.path,
+     "downloadLastDir should point to dir2");
+  is((yield getFile(downloadLastDir, uri1)).path, dir1.path,
+     "uri1 should return dir1"); // set in CPS
+  is((yield getFile(downloadLastDir, uri2)).path, dir2.path,
+     "uri2 should return dir2"); // set in CPS
+  is((yield getFile(downloadLastDir, uri3)).path, dir2.path,
+     "uri3 should return dir2"); // fallback
+  is((yield getFile(downloadLastDir, uri4)).path, dir2.path,
+     "uri4 should return dir2"); // fallback
 
-    // check that passing null to setFile clears the stored value
-    gDownloadLastDir.setFile(uri3, aDir3);
-    is(gDownloadLastDir.getFile(uri3).path, aDir3.path, "LastDir should be set to dir3");
-    gDownloadLastDir.setFile(uri3, null);
-    is(gDownloadLastDir.getFile(uri3), null, "uri3 should return null");
-  }
+  // set uri3 to dir3, all except uri1 and uri2 should now return dir3
+  yield setFile(downloadLastDir, uri3, dir3);
+  is(downloadLastDir.file.path, dir3.path,
+     "downloadLastDir should point to dir3");
+  is((yield getFile(downloadLastDir, uri1)).path, dir1.path,
+     "uri1 should return dir1"); // set in CPS
+  is((yield getFile(downloadLastDir, uri2)).path, dir2.path,
+     "uri2 should return dir2"); // set in CPS
+  is((yield getFile(downloadLastDir, uri3)).path, dir3.path,
+     "uri3 should return dir3"); // set in CPS
+  is((yield getFile(downloadLastDir, uri4)).path, dir3.path,
+     "uri4 should return dir4"); // fallback
 
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkInit(win, downloadDir);
-    downloadDir.setFile(null, tmpDir);
-  });
+  // set uri1 to dir2, all except uri3 should now return dir2
+  yield setFile(downloadLastDir, uri1, dir2);
+  is(downloadLastDir.file.path, dir2.path,
+     "downloadLastDir should point to dir2");
+  is((yield getFile(downloadLastDir, uri1)).path, dir2.path,
+     "uri1 should return dir2"); // set in CPS
+  is((yield getFile(downloadLastDir, uri2)).path, dir2.path,
+     "uri2 should return dir2"); // set in CPS
+  is((yield getFile(downloadLastDir, uri3)).path, dir3.path,
+     "uri3 should return dir3"); // set in CPS
+  is((yield getFile(downloadLastDir, uri4)).path, dir2.path,
+     "uri4 should return dir2"); // fallback
+
+  yield clearHistoryAndWait();
+
+  // check clearHistory removes all data
+  is(downloadLastDir.file, null, "clearHistory removes all data");
+  //is(Services.contentPrefs.hasPref(uri1, "browser.download.lastDir", null),
+  //   false, "LastDir preference should be absent");
+  is((yield getFile(downloadLastDir, uri1)), null, "uri1 should point to null");
+  is((yield getFile(downloadLastDir, uri2)), null, "uri2 should point to null");
+  is((yield getFile(downloadLastDir, uri3)), null, "uri3 should point to null");
+  is((yield getFile(downloadLastDir, uri4)), null, "uri4 should point to null");
+
+  yield setFile(downloadLastDir, null, tmpDir);
 
   // check data set outside PB mode is remembered
-  yield testOnWindow(true, function(win, downloadDir) {
-    checkDownloadLastDir(win, downloadDir, tmpDir);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkDownloadLastDir(win, downloadDir, tmpDir);
-    clearHistory();
-    downloadDir.setFile(uri1, dir1);
-  });
+  is((yield checkDownloadLastDir(pbDownloadLastDir, tmpDir)).path, tmpDir.path, "uri1 should return the expected last directory");
+  is((yield checkDownloadLastDir(downloadLastDir, tmpDir)).path, tmpDir.path, "uri1 should return the expected last directory");
+  yield clearHistoryAndWait();
+
+  yield setFile(downloadLastDir, uri1, dir1);
 
   // check data set using CPS outside PB mode is remembered
-  yield testOnWindow(true, function(win, downloadDir) {
-    checkDownloadLastDir(win, downloadDir, dir1);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkDownloadLastDir(win, downloadDir, dir1);
-    clearHistory();
-  });
+  is((yield checkDownloadLastDir(pbDownloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+  is((yield checkDownloadLastDir(downloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+  yield clearHistoryAndWait();
 
   // check data set inside PB mode is forgotten
-  yield testOnWindow(true, function(win, downloadDir) {
-    downloadDir.setFile(null, tmpDir);
-    checkDownloadLastDir(win, downloadDir, tmpDir);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkDownloadLastDirNull(win, downloadDir);
-    clearHistory();
-  });
+  yield setFile(pbDownloadLastDir, null, tmpDir);
+
+  is((yield checkDownloadLastDir(pbDownloadLastDir, tmpDir)).path, tmpDir.path, "uri1 should return the expected last directory");
+  is((yield checkDownloadLastDirNull(downloadLastDir)), null, "uri1 should return the expected last directory");
+
+  yield clearHistoryAndWait();
 
   // check data set using CPS inside PB mode is forgotten
-  yield testOnWindow(true, function(win, downloadDir) {
-    downloadDir.setFile(uri1, dir1);
-    checkDownloadLastDir(win, downloadDir, dir1);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkDownloadLastDirNull(win, downloadDir);
-    clearHistory();
-    downloadDir.setFile(uri1, dir1);
-  });
+  yield setFile(pbDownloadLastDir, uri1, dir1);
+
+  is((yield checkDownloadLastDir(pbDownloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+  is((yield checkDownloadLastDirNull(downloadLastDir)), null, "uri1 should return the expected last directory");
 
   // check data set outside PB mode but changed inside is remembered correctly
-  yield testOnWindow(true, function(win, downloadDir) {
-    downloadDir.setFile(uri1, dir2);
-    checkDownloadLastDir(win, downloadDir, dir2);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkDownloadLastDir(win, downloadDir, dir1);
-  });
+  yield setFile(downloadLastDir, uri1, dir1);
+  yield setFile(pbDownloadLastDir, uri1, dir2);
+  is((yield checkDownloadLastDir(pbDownloadLastDir, dir2)).path, dir2.path, "uri1 should return the expected last directory");
+  is((yield checkDownloadLastDir(downloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
 
-  // check that the last dir store got cleared
-  yield testOnWindow(true, function(win, downloadDir) {
-    checkDownloadLastDir(win, downloadDir, dir1);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    clearHistory();
-  });
+  /*
+   * ====================
+   * Create new PB window
+   * ====================
+   */
+
+  // check that the last dir store got cleared in a new PB window
+  pbWin.close();
+  let pbWin = yield createWindow({private: true});
+  let pbDownloadLastDir = new DownloadLastDir(pbWin);
+
+  is((yield checkDownloadLastDir(pbDownloadLastDir, dir1)).path, dir1.path, "uri1 should return the expected last directory");
+
+  yield clearHistoryAndWait();
 
   // check clearHistory inside PB mode clears data outside PB mode
-  yield testOnWindow(true, function(win, downloadDir) {
-    downloadDir.setFile(uri1, dir2);
-    clearHistory();
-    checkDownloadLastDirNull(win, downloadDir);
-  });
-  yield testOnWindow(false, function(win, downloadDir) {
-    checkDownloadLastDirNull(win, downloadDir);
-    checkSetFile(downloadDir, dir1, dir2, dir3);
-  });
+  yield setFile(pbDownloadLastDir, uri1, dir2);
+
+  yield clearHistoryAndWait();
+
+  is((yield checkDownloadLastDirNull(downloadLastDir)), null, "uri1 should return the expected last directory");
+  is((yield checkDownloadLastDirNull(pbDownloadLastDir)), null, "uri1 should return the expected last directory");
+
+  // check that disabling CPS works
+  Services.prefs.setBoolPref("browser.download.lastDir.savePerSite", false);
+
+  yield setFile(downloadLastDir, uri1, dir1);
+  is(downloadLastDir.file.path, dir1.path, "LastDir should be set to dir1");
+  is((yield getFile(downloadLastDir, uri1)).path, dir1.path, "uri1 should return dir1");
+  is((yield getFile(downloadLastDir, uri2)).path, dir1.path, "uri2 should return dir1");
+  is((yield getFile(downloadLastDir, uri3)).path, dir1.path, "uri3 should return dir1");
+  is((yield getFile(downloadLastDir, uri4)).path, dir1.path, "uri4 should return dir1");
+
+  downloadLastDir.setFile(uri2, dir2);
+  is(downloadLastDir.file.path, dir2.path, "LastDir should be set to dir2");
+  is((yield getFile(downloadLastDir, uri1)).path, dir2.path, "uri1 should return dir2");
+  is((yield getFile(downloadLastDir, uri2)).path, dir2.path, "uri2 should return dir2");
+  is((yield getFile(downloadLastDir, uri3)).path, dir2.path, "uri3 should return dir2");
+  is((yield getFile(downloadLastDir, uri4)).path, dir2.path, "uri4 should return dir2");
+
+  Services.prefs.clearUserPref("browser.download.lastDir.savePerSite");
+
+  // check that passing null to setFile clears the stored value
+  yield setFile(downloadLastDir, uri3, dir3);
+  is((yield getFile(downloadLastDir, uri3)).path, dir3.path, "LastDir should be set to dir3");
+  yield setFile(downloadLastDir, uri3, null);
+  is((yield getFile(downloadLastDir, uri3)), null, "uri3 should return null");
+
+  yield clearHistoryAndWait();
 }
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_certexceptionsui.js
@@ -23,18 +23,18 @@ function test() {
   function doTest() {
     let params = {
       exceptionAdded : false,
       location: INVALID_CERT_LOCATION,
       prefetchCert: true,
     };
     function testCheckbox() {
       win.removeEventListener("load", testCheckbox, false);
-      Services.obs.addObserver(function (aSubject, aTopic, aData) {
-        Services.obs.removeObserver(arguments.callee, "cert-exception-ui-ready", false);
+      Services.obs.addObserver(function onCertUI(aSubject, aTopic, aData) {
+        Services.obs.removeObserver(onCertUI, "cert-exception-ui-ready");
         ok(win.gCert, "The certificate information should be available now");
 
         let checkbox = win.document.getElementById("permanent");
         ok(checkbox.hasAttribute("disabled"),
           "the permanent checkbox should be disabled when handling the private browsing mode");
         ok(!checkbox.hasAttribute("checked"),
           "the permanent checkbox should not be checked when handling the private browsing mode");
         win.close();
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir.js
@@ -38,48 +38,52 @@ function test() {
   });
   prefs.setComplexValue("lastDir", Ci.nsIFile, tmpDir);
 
   function testOnWindow(aPrivate, aCallback) {
     whenNewWindowLoaded({private: aPrivate}, function(win) {
       let gDownloadLastDir = new DownloadLastDir(win);
       aCallback(win, gDownloadLastDir);
       gDownloadLastDir.cleanupPrivateFile();
-      win.close();
     });
   }
 
   function testDownloadDir(aWin, gDownloadLastDir, aFile, aDisplayDir, aLastDir,
                            aGlobalLastDir, aCallback) {
     let context = aWin.gBrowser.selectedBrowser.contentWindow;
 
     // Check lastDir preference.
     is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
        "LastDir should be the expected display dir");
     // Check gDownloadLastDir value.
     is(gDownloadLastDir.file.path, aDisplayDir.path,
        "gDownloadLastDir should be the expected display dir");
 
     MockFilePicker.returnFiles = [aFile];
     MockFilePicker.displayDirectory = null;
-    let file =
-      launcherDialog.promptForSaveToFile(launcher, context, null, null, null);
-    ok(!!file, "promptForSaveToFile correctly returned a file");
+
+    launcher.saveDestinationAvailable = function (file) {
+      ok(!!file, "promptForSaveToFile correctly returned a file");
 
-    // File picker should start with expected display dir.
-    is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
-      "File picker should start with browser.download.lastDir");
-    // browser.download.lastDir should be modified on not private windows
-    is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
-       "LastDir should be the expected last dir");
-    // gDownloadLastDir should be usable outside of private windows
-    is(gDownloadLastDir.file.path, aGlobalLastDir.path,
-       "gDownloadLastDir should be the expected global last dir");
+      // File picker should start with expected display dir.
+      is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
+        "File picker should start with browser.download.lastDir");
+      // browser.download.lastDir should be modified on not private windows
+      is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
+         "LastDir should be the expected last dir");
+      // gDownloadLastDir should be usable outside of private windows
+      is(gDownloadLastDir.file.path, aGlobalLastDir.path,
+         "gDownloadLastDir should be the expected global last dir");
 
-    aCallback();
+      launcher.saveDestinationAvailable = null;
+      aWin.close();
+      aCallback();
+    };
+
+    launcherDialog.promptForSaveToFileAsync(launcher, context, null, null, null);
   }
 
   testOnWindow(false, function(win, downloadDir) {
     testDownloadDir(win, downloadDir, file1, tmpDir, dir1, dir1, function() {
       testOnWindow(true, function(win, downloadDir) {
         testDownloadDir(win, downloadDir, file2, dir1, dir1, dir2, function() {
           testOnWindow(false, function(win, downloadDir) {
             testDownloadDir(win, downloadDir, file3, dir1, dir3, dir3, finish);
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
@@ -61,30 +61,29 @@ function test() {
     is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
        "LastDir should be the expected display dir");
     // Check gDownloadLastDir value.
     is(gDownloadLastDir.file.path, aDisplayDir.path,
        "gDownloadLastDir should be the expected display dir");
 
     MockFilePicker.returnFiles = [aFile];
     MockFilePicker.displayDirectory = null;
-    ok(aWin.getTargetFile(params),
-       "Show the file picker dialog with given params");
+    aWin.getTargetFile(params, function() {
+      // File picker should start with expected display dir.
+      is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
+         "File picker should start with browser.download.lastDir");
+      // browser.download.lastDir should be modified on not private windows
+      is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
+         "LastDir should be the expected last dir");
+      // gDownloadLastDir should be usable outside of private windows
+      is(gDownloadLastDir.file.path, aGlobalLastDir.path,
+         "gDownloadLastDir should be the expected global last dir");
 
-    // File picker should start with expected display dir.
-    is(MockFilePicker.displayDirectory.path, aDisplayDir.path,
-       "File picker should start with browser.download.lastDir");
-    // browser.download.lastDir should be modified on not private windows
-    is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aLastDir.path,
-       "LastDir should be the expected last dir");
-    // gDownloadLastDir should be usable outside of private windows
-    is(gDownloadLastDir.file.path, aGlobalLastDir.path,
-       "gDownloadLastDir should be the expected global last dir");
-
-    aCallback();
+      aCallback();
+    });
   }
 
   testOnWindow(false, function(win, downloadDir) {
     testDownloadDir(win, downloadDir, file1, tmpDir, dir1, dir1, function() {
       testOnWindow(true, function(win, downloadDir) {
         testDownloadDir(win, downloadDir, file2, dir1, dir1, dir2, function() {
           testOnWindow(false, function(win, downloadDir) {
             testDownloadDir(win, downloadDir, file3, dir1, dir3, dir3, finish);
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
@@ -10,24 +10,24 @@ function test() {
     SimpleTest.waitForFocus(function() {
       let expectedExiting = true;
       let expectedExited = false;
       let observerExiting = {
         observe: function(aSubject, aTopic, aData) {
           is(aTopic, "last-pb-context-exiting", "Correct topic should be dispatched (exiting)");
           is(expectedExiting, true, "notification not expected yet (exiting)");
           expectedExited = true;
-          Services.obs.removeObserver(observerExiting, "last-pb-context-exiting", false);
+          Services.obs.removeObserver(observerExiting, "last-pb-context-exiting");
         }
       };
       let observerExited = {
         observe: function(aSubject, aTopic, aData) {
           is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched (exited)");
           is(expectedExited, true, "notification not expected yet (exited)");
-          Services.obs.removeObserver(observerExited, "last-pb-context-exited", false);
+          Services.obs.removeObserver(observerExited, "last-pb-context-exited");
           aCallback();
         }
       };
       Services.obs.addObserver(observerExiting, "last-pb-context-exiting", false);
       Services.obs.addObserver(observerExited, "last-pb-context-exited", false);
       expectedExiting = true;
       aCloseWindow(newWin);
       newWin = null;
--- a/browser/components/sessionstore/test/browser_354894_perwindowpb.js
+++ b/browser/components/sessionstore/test/browser_354894_perwindowpb.js
@@ -162,17 +162,17 @@ function test() {
   }
 
   /**
    * Helper: Cleans up behind the testsuite
    */
   function cleanupTestsuite(callback) {
     // Finally remove observers again
     for (let o in observing)
-      Services.obs.removeObserver(observer, o, false);
+      Services.obs.removeObserver(observer, o);
 
     // Reset the prefs we touched
     [
       "browser.startup.page",
       "browser.privatebrowsing.keep_current_session"
     ].forEach(function (pref) {
       if (gPrefService.prefHasUserValue(pref))
         gPrefService.clearUserPref(pref);
--- a/browser/components/sessionstore/test/browser_448741.js
+++ b/browser/components/sessionstore/test/browser_448741.js
@@ -31,28 +31,28 @@ function test() {
           delete tabData.extData[uniqueName];
           valueWasCleaned = true;
         }
       });
     });
 
     ok(valueWasCleaned, "found and removed the specific tab value");
     aSubject.data = JSON.stringify(state);
-    Services.obs.removeObserver(cleaningObserver, aTopic, false);
+    Services.obs.removeObserver(cleaningObserver, aTopic);
   }
 
   // make sure that all later observers don't see that value any longer
   function checkingObserver(aSubject, aTopic, aData) {
     ok(valueWasCleaned && aSubject instanceof Ci.nsISupportsString,
        "ready to check the cleaned state?");
     ok(aSubject.data.indexOf(uniqueValue) == -1, "data no longer contains our value?");
 
     // clean up
     gBrowser.removeTab(tab);
-    Services.obs.removeObserver(checkingObserver, aTopic, false);
+    Services.obs.removeObserver(checkingObserver, aTopic);
     if (gPrefService.prefHasUserValue("browser.sessionstore.interval"))
       gPrefService.clearUserPref("browser.sessionstore.interval");
     finish();
   }
 
   // last added observers are invoked first
   Services.obs.addObserver(checkingObserver, "sessionstore-state-write", false);
   Services.obs.addObserver(cleaningObserver, "sessionstore-state-write", false);
--- a/browser/components/sessionstore/test/browser_586147.js
+++ b/browser/components/sessionstore/test/browser_586147.js
@@ -1,16 +1,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/. */
 
 function observeOneRestore(callback) {
   let topic = "sessionstore-browser-state-restored";