Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Mon, 08 Apr 2013 10:55:12 -0700
changeset 128787 861f3c6327a4705c7d4d6d3353ac2ce40b171ea5
parent 128786 225be6d5e41b408dbd44d769d38dac09492b350a (current diff)
parent 127941 b0d84238095938e638497cd1b02bc7005f1abdfb (diff)
child 128788 f536d418c3d2f245553251746931fdd0cb3b6f38
push id1521
push userttaubert@mozilla.com
push dateTue, 16 Apr 2013 17:51:27 +0000
treeherderfx-team@5542cdcb4a9d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone23.0a1
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";
-  Services.obs.addObserver(function() {
-    Services.obs.removeObserver(arguments.callee, topic, false);
+  Services.obs.addObserver(function onRestore() {
+    Services.obs.removeObserver(onRestore, topic);
     callback();
   }, topic, false);
 };
 
 function test() {
   waitForExplicitFinish();
   ignoreAllUncaughtExceptions();
 
--- a/browser/components/sessionstore/test/browser_589246.js
+++ b/browser/components/sessionstore/test/browser_589246.js
@@ -148,17 +148,17 @@ function setupForTest(aConditions) {
 
   // Set the state
   Services.obs.addObserver(onStateRestored, "sessionstore-browser-state-restored", false);
   ss.setBrowserState(JSON.stringify(testState));
 }
 
 function onStateRestored(aSubject, aTopic, aData) {
   info("test #" + testNum + ": onStateRestored");
-  Services.obs.removeObserver(onStateRestored, "sessionstore-browser-state-restored", false);
+  Services.obs.removeObserver(onStateRestored, "sessionstore-browser-state-restored");
 
   // change this window's windowtype so that closing a new window will trigger
   // browser-lastwindow-close-granted.
   document.documentElement.setAttribute("windowtype", "navigator:testrunner");
 
   let newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "http://example.com");
   newWin.addEventListener("load", function(aEvent) {
     newWin.removeEventListener("load", arguments.callee, false);
@@ -199,17 +199,17 @@ function onStateRestored(aSubject, aTopi
       }
     }, true);
   }, false);
 }
 
 // This will be called before the window is actually closed
 function onLastWindowClosed(aSubject, aTopic, aData) {
   info("test #" + testNum + ": onLastWindowClosed");
-  Services.obs.removeObserver(onLastWindowClosed, "browser-lastwindow-close-granted", false);
+  Services.obs.removeObserver(onLastWindowClosed, "browser-lastwindow-close-granted");
   gotLastWindowClosedTopic = true;
 }
 
 // This is the unload event listener on the new window (from onStateRestored).
 // Unload is fired after the window is closed, so sessionstore has already
 // updated _closedWindo