Merge mozilla-central to jsdbg2.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 18 Jul 2011 10:58:56 -0500
changeset 75216 8a24918fd43848874391baa68f7245e52de03128
parent 75215 69611b724e6813a372d1b71aaafe5b45d65c62c6 (current diff)
parent 72946 819a2ffc4f0e022d1660e8804f41a74c6548e04b (diff)
child 75217 3d1006081f64240d8688dd7782f112fb3659496f
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone8.0a1
Merge mozilla-central to jsdbg2.
browser/base/content/browser.js
browser/base/content/test/tabview/browser_tabview_bug625666.js
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/interfaces/base/nsIDOMWindowInternal.idl
dom/interfaces/storage/nsIDOMStorageWindow.idl
dom/interfaces/threads/Makefile.in
dom/interfaces/threads/nsIDOMWorkers.idl
dom/src/threads/Makefile.in
dom/src/threads/nsDOMThreadService.cpp
dom/src/threads/nsDOMThreadService.h
dom/src/threads/nsDOMWorker.cpp
dom/src/threads/nsDOMWorker.h
dom/src/threads/nsDOMWorkerEvents.cpp
dom/src/threads/nsDOMWorkerEvents.h
dom/src/threads/nsDOMWorkerLocation.cpp
dom/src/threads/nsDOMWorkerLocation.h
dom/src/threads/nsDOMWorkerMacros.h
dom/src/threads/nsDOMWorkerMessageHandler.cpp
dom/src/threads/nsDOMWorkerMessageHandler.h
dom/src/threads/nsDOMWorkerNavigator.cpp
dom/src/threads/nsDOMWorkerNavigator.h
dom/src/threads/nsDOMWorkerPool.cpp
dom/src/threads/nsDOMWorkerPool.h
dom/src/threads/nsDOMWorkerScriptLoader.cpp
dom/src/threads/nsDOMWorkerScriptLoader.h
dom/src/threads/nsDOMWorkerSecurityManager.cpp
dom/src/threads/nsDOMWorkerSecurityManager.h
dom/src/threads/nsDOMWorkerTimeout.cpp
dom/src/threads/nsDOMWorkerTimeout.h
dom/src/threads/nsDOMWorkerXHR.cpp
dom/src/threads/nsDOMWorkerXHR.h
dom/src/threads/nsDOMWorkerXHRProxiedFunctions.h
dom/src/threads/nsDOMWorkerXHRProxy.cpp
dom/src/threads/nsDOMWorkerXHRProxy.h
dom/src/threads/test/Makefile.in
dom/src/threads/test/WorkerTest.jsm
dom/src/threads/test/WorkerTest_badworker.js
dom/src/threads/test/WorkerTest_subworker.js
dom/src/threads/test/WorkerTest_worker.js
dom/src/threads/test/atob_worker.js
dom/src/threads/test/chromeWorker_subworker.js
dom/src/threads/test/chromeWorker_worker.js
dom/src/threads/test/closeOnGC_server.sjs
dom/src/threads/test/closeOnGC_worker.js
dom/src/threads/test/close_worker.js
dom/src/threads/test/errorPropagation_worker1.js
dom/src/threads/test/errorPropagation_worker2.js
dom/src/threads/test/fibonacci_worker.js
dom/src/threads/test/functionHandlers_worker.js
dom/src/threads/test/importScripts_worker.js
dom/src/threads/test/importScripts_worker_imported1.js
dom/src/threads/test/importScripts_worker_imported2.js
dom/src/threads/test/importScripts_worker_imported3.js
dom/src/threads/test/importScripts_worker_imported4.js
dom/src/threads/test/json_worker.js
dom/src/threads/test/location_worker.js
dom/src/threads/test/longThread_worker.js
dom/src/threads/test/navigator_worker.js
dom/src/threads/test/newError_worker.js
dom/src/threads/test/recursion_worker.js
dom/src/threads/test/regExpStatics_worker.js
dom/src/threads/test/relativeLoad_import.js
dom/src/threads/test/relativeLoad_sub_import.js
dom/src/threads/test/relativeLoad_sub_worker.js
dom/src/threads/test/relativeLoad_sub_worker2.js
dom/src/threads/test/relativeLoad_worker.js
dom/src/threads/test/relativeLoad_worker2.js
dom/src/threads/test/scopeOnerror_worker.js
dom/src/threads/test/simpleThread_worker.js
dom/src/threads/test/suspend_iframe.html
dom/src/threads/test/suspend_worker.js
dom/src/threads/test/terminate_worker.js
dom/src/threads/test/testXHR.txt
dom/src/threads/test/test_404.html
dom/src/threads/test/test_atob.html
dom/src/threads/test/test_chromeWorker.html
dom/src/threads/test/test_chromeWorker.xul
dom/src/threads/test/test_chromeWorkerComponent.xul
dom/src/threads/test/test_chromeWorkerJSM.xul
dom/src/threads/test/test_close.html
dom/src/threads/test/test_closeOnGC.html
dom/src/threads/test/test_errorPropagation.html
dom/src/threads/test/test_fibonacci.html
dom/src/threads/test/test_functionHandlers.html
dom/src/threads/test/test_importScripts.html
dom/src/threads/test/test_json.html
dom/src/threads/test/test_location.html
dom/src/threads/test/test_longThread.html
dom/src/threads/test/test_navigator.html
dom/src/threads/test/test_newError.html
dom/src/threads/test/test_recursion.html
dom/src/threads/test/test_regExpStatics.html
dom/src/threads/test/test_relativeLoad.html
dom/src/threads/test/test_scopeOnerror.html
dom/src/threads/test/test_simpleThread.html
dom/src/threads/test/test_suspend.html
dom/src/threads/test/test_terminate.html
dom/src/threads/test/test_threadErrors.html
dom/src/threads/test/test_threadTimeouts.html
dom/src/threads/test/test_throwingOnerror.html
dom/src/threads/test/test_xhr.html
dom/src/threads/test/test_xhrAbort.html
dom/src/threads/test/test_xpcom.html
dom/src/threads/test/threadErrors_worker1.js
dom/src/threads/test/threadErrors_worker2.js
dom/src/threads/test/threadErrors_worker3.js
dom/src/threads/test/threadErrors_worker4.js
dom/src/threads/test/threadTimeouts_worker.js
dom/src/threads/test/throwingOnerror_worker.js
dom/src/threads/test/xhrAbort_worker.js
dom/src/threads/test/xhr_worker.js
dom/src/threads/test/xpcom_worker.js
js/src/Makefile.in
js/src/config/autoconf.mk.in
js/src/configure.in
js/src/jsapi-tests/Makefile.in
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsbuiltins.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdate.cpp
js/src/jsemit.cpp
js/src/jsemit.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsinterp.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsopcode.cpp
js/src/jsopcode.tbl
js/src/jsparse.cpp
js/src/jsprobes.cpp
js/src/jsproxy.cpp
js/src/jsprvtd.h
js/src/jsregexp.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jstracer.cpp
js/src/jstracer.h
js/src/jstypedarray.cpp
js/src/jsvector.h
js/src/jswrapper.h
js/src/jsxdrapi.h
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/FastArithmetic.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
js/src/tests/js1_8_5/extensions/jstests.list
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
mobile/app/macbuild/Contents/CVS/Entries
mobile/app/macbuild/Contents/CVS/Repository
mobile/app/macbuild/Contents/CVS/Root
mobile/app/macbuild/Contents/Resources/CVS/Entries
mobile/app/macbuild/Contents/Resources/CVS/Repository
mobile/app/macbuild/Contents/Resources/CVS/Root
mobile/app/macbuild/Contents/Resources/English.lproj/CVS/Entries
mobile/app/macbuild/Contents/Resources/English.lproj/CVS/Repository
mobile/app/macbuild/Contents/Resources/English.lproj/CVS/Root
mobile/app/macbuild/background.png
mobile/app/macbuild/disk.icns
mobile/app/macbuild/document.icns
mobile/app/macbuild/dsstore
mobile/app/macbuild/fennec.icns
mobile/app/macbuild/license.r
modules/libpref/src/init/all.js
netwerk/cookie/test/unit_ipc/head_ipc_setup.js
netwerk/test/unit_ipc/head_ipc_setup.js
services/sync/tests/unit/head_appinfo.js.in
tools/performance/startup/analyze-timeline-log.pl
tools/performance/startup/measure-simple.pl
tools/performance/startup/printlog.pl
xpcom/ds/nsITimelineService.idl
xpcom/ds/nsTimelineService.cpp
xpcom/ds/nsTimelineService.h
--- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp
+++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp
@@ -50,17 +50,17 @@
 #include "nsAccessibilityService.h"
 #include "AtkSocketAccessible.h"
 
 #include <gtk/gtk.h>
 #include <atk/atk.h>
 
 typedef GType (* AtkGetTypeType) (void);
 GType g_atk_hyperlink_impl_type = G_TYPE_INVALID;
-static PRBool sATKChecked = PR_FALSE;
+static bool sATKChecked = false;
 static PRLibrary *sATKLib = nsnull;
 static const char sATKLibName[] = "libatk-1.0.so.0";
 static const char sATKHyperlinkImplGetTypeSymbol[] =
     "atk_hyperlink_impl_get_type";
 static const char sAccEnv [] = "GNOME_ACCESSIBILITY";
 static const char sSysPrefService [] =
     "@mozilla.org/system-preference-service;1";
 static const char sAccessibilityKey [] =
@@ -95,33 +95,37 @@ static guint add_listener (GSignalEmissi
                            const gchar *hook_data,
                            guint gail_listenerid = 0);
 static AtkKeyEventStruct *atk_key_event_from_gdk_event_key(GdkEventKey *key);
 static gboolean notify_hf(gpointer key, gpointer value, gpointer data);
 static void insert_hf(gpointer key, gpointer value, gpointer data);
 static gint mai_key_snooper(GtkWidget *the_widget, GdkEventKey *event,
                             gpointer func_data);
 
-static GHashTable *listener_list = NULL;
-static gint listener_idx = 1;
+static GHashTable* sListener_list = NULL;
+static gint sListener_idx = 1;
 
 #define MAI_TYPE_UTIL              (mai_util_get_type ())
 #define MAI_UTIL(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
                                     MAI_TYPE_UTIL, MaiUtil))
 #define MAI_UTIL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), \
                                     MAI_TYPE_UTIL, MaiUtilClass))
 #define MAI_IS_UTIL(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
                                     MAI_TYPE_UTIL))
 #define MAI_IS_UTIL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), \
                                     MAI_TYPE_UTIL))
 #define MAI_UTIL_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), \
                                     MAI_TYPE_UTIL, MaiUtilClass))
 
-static GHashTable *key_listener_list = NULL;
-static guint key_snooper_id = 0;
+static GHashTable* sKey_listener_list = NULL;
+static guint sKey_snooper_id = 0;
+static GQuark sQuark_gecko_acc_obj = g_quark_from_static_string("GeckoAccObj");
+static bool sToplevel_event_hook_added = false;
+static gulong sToplevel_show_hook = 0;
+static gulong sToplevel_hide_hook = 0;
 
 G_BEGIN_DECLS
 typedef void (*GnomeAccessibilityInit) (void);
 typedef void (*GnomeAccessibilityShutdown) (void);
 G_END_DECLS
 
 struct MaiUtil
 {
@@ -218,26 +222,32 @@ mai_util_get_type(void)
     return type;
 }
 
 static void
 window_added (AtkObject *atk_obj,
               guint     index,
               AtkObject *child)
 {
-  guint id =  g_signal_lookup ("create", MAI_TYPE_ATK_OBJECT);
+  if (!IS_MAI_OBJECT(child))
+      return;
+
+  static guint id =  g_signal_lookup ("create", MAI_TYPE_ATK_OBJECT);
   g_signal_emit (child, id, 0);
 }
 
 static void
 window_removed (AtkObject *atk_obj,
                 guint     index,
                 AtkObject *child)
 {
-  guint id =  g_signal_lookup ("destroy", MAI_TYPE_ATK_OBJECT);
+  if (!IS_MAI_OBJECT(child))
+      return;
+
+  static guint id =  g_signal_lookup ("destroy", MAI_TYPE_ATK_OBJECT);
   g_signal_emit (child, id, 0);
 }
 
 /* intialize the the atk interface (function pointers) with MAI implementation.
  * When atk bridge get loaded, these interface can be used.
  */
 static void
 mai_util_class_init(MaiUtilClass *klass)
@@ -259,18 +269,18 @@ mai_util_class_init(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;
 
-    listener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
-                                          _listener_info_destroy);
+    sListener_list = g_hash_table_new_full(g_int_hash, g_int_equal, NULL,
+                                           _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);
 }
 
 static guint
 mai_util_add_global_event_listener(GSignalEmissionHook listener,
@@ -284,17 +294,17 @@ mai_util_add_global_event_listener(GSign
     if (split_string) {
         if (!strcmp ("window", split_string[0])) {
             guint gail_listenerid = 0;
             if (gail_add_global_event_listener) {
                 // call gail's function to track gtk native window events
                 gail_listenerid =
                     gail_add_global_event_listener(listener, event_type);
             }
-            
+
             rc = add_listener (listener, "MaiAtkObject", split_string[1],
                                event_type, gail_listenerid);
         }
         else {
             rc = add_listener (listener, split_string[1], split_string[2],
                                event_type);
         }
         g_strfreev(split_string);
@@ -305,32 +315,32 @@ mai_util_add_global_event_listener(GSign
 static void
 mai_util_remove_global_event_listener(guint remove_listener)
 {
     if (remove_listener > 0) {
         MaiUtilListenerInfo *listener_info;
         gint tmp_idx = remove_listener;
 
         listener_info = (MaiUtilListenerInfo *)
-            g_hash_table_lookup(listener_list, &tmp_idx);
+            g_hash_table_lookup(sListener_list, &tmp_idx);
 
         if (listener_info != NULL) {
             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 */
                 g_signal_remove_emission_hook(listener_info->signal_id,
                                               listener_info->hook_id);
 
                 /* Remove the element from the hash */
-                g_hash_table_remove(listener_list, &tmp_idx);
+                g_hash_table_remove(sListener_list, &tmp_idx);
             }
             else {
                 g_warning("Invalid listener hook_id %ld or signal_id %d\n",
                           listener_info->hook_id, listener_info->signal_id);
             }
         }
         else {
             // atk-bridge is initialized with gail (e.g. yelp)
@@ -361,24 +371,24 @@ atk_key_event_from_gdk_event_key (GdkEve
         break;
     default:
         g_assert_not_reached ();
         return NULL;
     }
     event->state = key->state;
     event->keyval = key->keyval;
     event->length = key->length;
-    if (key->string && key->string [0] && 
+    if (key->string && key->string [0] &&
         (key->state & GDK_CONTROL_MASK ||
          g_unichar_isgraph (g_utf8_get_char (key->string)))) {
         event->string = key->string;
     }
     else if (key->type == GDK_KEY_PRESS ||
              key->type == GDK_KEY_RELEASE) {
-        event->string = gdk_keyval_name (key->keyval);	    
+        event->string = gdk_keyval_name (key->keyval);
     }
     event->keycode = key->hardware_keycode;
     event->timestamp = key->time;
 
     MAI_LOG_DEBUG(("MaiKey:\tsym %u\n\tmods %x\n\tcode %u\n\ttime %lx\n",
                    (unsigned int) event->keyval,
                    (unsigned int) event->state,
                    (unsigned int) event->keycode,
@@ -404,19 +414,19 @@ insert_hf(gpointer key, gpointer value, 
 
 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 (key_listener_list) {
+    if (sKey_listener_list) {
         GHashTable *new_hash = g_hash_table_new(NULL, NULL);
-        g_hash_table_foreach (key_listener_list, insert_hf, new_hash);
+        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);
     return (consumed ? 1 : 0);
@@ -425,39 +435,39 @@ mai_key_snooper(GtkWidget *the_widget, G
 static guint
 mai_util_add_key_event_listener (AtkKeySnoopFunc listener,
                                  gpointer data)
 {
     NS_ENSURE_TRUE(listener, 0);
 
     static guint key=0;
 
-    if (!key_listener_list) {
-        key_listener_list = g_hash_table_new(NULL, NULL);
-        key_snooper_id = gtk_key_snooper_install(mai_key_snooper, data);
+    if (!sKey_listener_list) {
+        sKey_listener_list = g_hash_table_new(NULL, NULL);
+        sKey_snooper_id = gtk_key_snooper_install(mai_key_snooper, data);
     }
     AtkKeySnoopFuncPointer atkKeySnoop;
     atkKeySnoop.func_ptr = listener;
-    g_hash_table_insert(key_listener_list, GUINT_TO_POINTER (key++),
+    g_hash_table_insert(sKey_listener_list, GUINT_TO_POINTER (key++),
                         atkKeySnoop.data);
     return key;
 }
 
 static void
 mai_util_remove_key_event_listener (guint remove_listener)
 {
-    if (!key_listener_list) {
+    if (!sKey_listener_list) {
         // atk-bridge is initialized with gail (e.g. yelp)
         // try gail_remove_key_event_listener
         return gail_remove_key_event_listener(remove_listener);
     }
 
-    g_hash_table_remove(key_listener_list, GUINT_TO_POINTER (remove_listener));
-    if (g_hash_table_size(key_listener_list) == 0) {
-        gtk_key_snooper_remove(key_snooper_id);
+    g_hash_table_remove(sKey_listener_list, GUINT_TO_POINTER (remove_listener));
+    if (g_hash_table_size(sKey_listener_list) == 0) {
+        gtk_key_snooper_remove(sKey_snooper_id);
     }
 }
 
 AtkObject *
 mai_util_get_root(void)
 {
     if (nsAccessibilityService::IsShutdown()) {
         // We've shutdown, try to use gail instead
@@ -507,31 +517,31 @@ add_listener (GSignalEmissionHook listen
     gint rc = 0;
 
     type = g_type_from_name(object_type);
     if (type) {
         signal_id = g_signal_lookup(signal, type);
         if (signal_id > 0) {
             MaiUtilListenerInfo *listener_info;
 
-            rc = listener_idx;
+            rc = sListener_idx;
 
             listener_info =  (MaiUtilListenerInfo *)
                 g_malloc(sizeof(MaiUtilListenerInfo));
-            listener_info->key = listener_idx;
+            listener_info->key = sListener_idx;
             listener_info->hook_id =
                 g_signal_add_emission_hook(signal_id, 0, listener,
                                            g_strdup(hook_data),
                                            (GDestroyNotify)g_free);
             listener_info->signal_id = signal_id;
             listener_info->gail_listenerid = gail_listenerid;
 
-            g_hash_table_insert(listener_list, &(listener_info->key),
+            g_hash_table_insert(sListener_list, &(listener_info->key),
                                 listener_info);
-            listener_idx++;
+            sListener_idx++;
         }
         else {
             g_warning("Invalid signal type %s\n", signal);
         }
     }
     else {
         g_warning("Invalid object type %s\n", object_type);
     }
@@ -549,16 +559,59 @@ nsApplicationAccessibleWrap::nsApplicati
 }
 
 nsApplicationAccessibleWrap::~nsApplicationAccessibleWrap()
 {
     MAI_LOG_DEBUG(("======Destory AppRootAcc=%p\n", (void*)this));
     nsAccessibleWrap::ShutdownAtkObject();
 }
 
+static gboolean
+toplevel_event_watcher(GSignalInvocationHint* ihint,
+                       guint                  n_param_values,
+                       const GValue*          param_values,
+                       gpointer               data)
+{
+  if (nsAccessibilityService::IsShutdown())
+    return TRUE;
+
+  GObject* object = reinterpret_cast<GObject*>(g_value_get_object(param_values));
+  if (!GTK_IS_WINDOW(object))
+    return TRUE;
+
+  AtkObject* child = gtk_widget_get_accessible(GTK_WIDGET(object));
+
+  // GTK native dialog
+  if (!IS_MAI_OBJECT(child) &&
+      (atk_object_get_role(child) == ATK_ROLE_DIALOG)) {
+
+    if (data == reinterpret_cast<gpointer>(nsIAccessibleEvent::EVENT_SHOW)) {
+
+      // Attach the dialog accessible to app accessible tree
+      nsAccessible* windowAcc = GetAccService()->AddNativeRootAccessible(child);
+      g_object_set_qdata(G_OBJECT(child), sQuark_gecko_acc_obj,
+                         reinterpret_cast<gpointer>(windowAcc));
+
+    } else {
+
+      // Deattach the dialog accessible
+      nsAccessible* windowAcc =
+        reinterpret_cast<nsAccessible*>
+                        (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);
+      }
+
+    }
+  }
+
+  return TRUE;
+}
+
 PRBool
 nsApplicationAccessibleWrap::Init()
 {
     // XXX following code is copied from widget/src/gtk2/nsWindow.cpp
     // we should put it to somewhere that can be used from both modules
     // see bug 390761
 
     // check if accessibility enabled/disabled by environment variable
@@ -597,24 +650,44 @@ nsApplicationAccessibleWrap::Init()
         // load and initialize atk-bridge library
         rv = LoadGtkModule(sAtkBridge);
         if (NS_SUCCEEDED(rv)) {
             // init atk-bridge
             (*sAtkBridge.init)();
         }
         else
             MAI_LOG_DEBUG(("Fail to load lib: %s\n", sAtkBridge.libName));
+
+        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);
+          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);
+        }
     }
 
     return nsApplicationAccessible::Init();
 }
 
 void
 nsApplicationAccessibleWrap::Unload()
 {
+    if (sToplevel_event_hook_added) {
+      sToplevel_event_hook_added = false;
+      g_signal_remove_emission_hook(g_signal_lookup("show", GTK_TYPE_WINDOW),
+                                    sToplevel_show_hook);
+      g_signal_remove_emission_hook(g_signal_lookup("hide", GTK_TYPE_WINDOW),
+                                    sToplevel_hide_hook);
+    }
+
     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;
@@ -666,17 +739,17 @@ struct AtkRootAccessibleAddedEvent {
 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);
     g_object_unref(eventData->app_accessible);
     g_object_unref(eventData->root_accessible);
     free(data);
-    
+
     return FALSE;
 }
 
 PRBool
 nsApplicationAccessibleWrap::AppendChild(nsAccessible *aChild)
 {
     if (!nsApplicationAccessible::AppendChild(aChild))
       return PR_FALSE;
@@ -736,17 +809,17 @@ nsApplicationAccessibleWrap::PreCreate()
                   PR_FindFunctionSymbol(sATKLib,
                                         AtkSocketAccessible
                                           ::sATKSocketEmbedSymbol);
             AtkSocketAccessible::gCanEmbed =
               AtkSocketAccessible::g_atk_socket_type != G_TYPE_INVALID &&
               AtkSocketAccessible::g_atk_socket_embed;
             }
         }
-        sATKChecked = PR_TRUE;
+        sATKChecked = true;
     }
 }
 
 static nsresult
 LoadGtkModule(GnomeAccessibilityModule& aModule)
 {
     NS_ENSURE_ARG(aModule.libName);
 
--- a/accessible/src/atk/nsMaiInterfaceComponent.cpp
+++ b/accessible/src/atk/nsMaiInterfaceComponent.cpp
@@ -38,21 +38,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsMaiInterfaceComponent.h"
 
 #include "nsAccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 
-#include "nsIDOMDocument.h"
-#include "nsIDOMWindowInternal.h"
-#include "nsIDocShellTreeItem.h"
-#include "nsIInterfaceRequestorUtils.h"
-
 void
 componentInterfaceInitCB(AtkComponentIface *aIface)
 {
     NS_ASSERTION(aIface, "Invalid Interface");
     if(!aIface)
         return;
 
     /*
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -41,19 +41,18 @@
 #include "nsIAccessibleTypes.h"
 
 #include "nsAccessNode.h"
 
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
-#include "nsIDOMNodeList.h"
 #include "nsIDOMRange.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsEventStateManager.h"
@@ -422,22 +421,21 @@ nsCoreUtils::GetScreenCoordsForWindow(ns
   nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
   nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(rootTreeItem);
   if (!domDoc)
     return coords;
 
   nsCOMPtr<nsIDOMWindow> window;
   domDoc->GetDefaultView(getter_AddRefs(window));
-  nsCOMPtr<nsIDOMWindowInternal> windowInter(do_QueryInterface(window));
-  if (!windowInter)
+  if (!window)
     return coords;
 
-  windowInter->GetScreenX(&coords.x);
-  windowInter->GetScreenY(&coords.y);
+  window->GetScreenX(&coords.x);
+  window->GetScreenY(&coords.y);
   return coords;
 }
 
 already_AddRefed<nsIDocShellTreeItem>
 nsCoreUtils::GetDocShellTreeItemFor(nsINode *aNode)
 {
   if (!aNode)
     return nsnull;
--- a/accessible/src/html/nsHTMLImageAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageAccessible.cpp
@@ -174,17 +174,17 @@ nsHTMLImageAccessible::DoAction(PRUint8 
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
 
     nsAutoString longDesc;
     nsresult rv = element->GetLongDesc(longDesc);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsIDocument* document = mContent->GetOwnerDoc();
     nsCOMPtr<nsPIDOMWindow> piWindow = document->GetWindow();
-    nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(piWindow));
+    nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(piWindow);
     NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
     nsCOMPtr<nsIDOMWindow> tmp;
     return win->Open(longDesc, EmptyString(), EmptyString(),
                      getter_AddRefs(tmp));
   }
   return nsLinkableAccessible::DoAction(aIndex);
 }
 
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -506,17 +506,17 @@ nsHTMLTableAccessible::GetAttributesInte
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetRelationByType(PRUint32 aRelationType,
                                          nsIAccessibleRelation **aRelation)
 {
   nsresult rv = nsAccessibleWrap::GetRelationByType(aRelationType,
                                                     aRelation);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_DESCRIBED_BY)
+  if (aRelationType == nsIAccessibleRelation::RELATION_LABELLED_BY)
     return nsRelUtils::AddTarget(aRelationType, aRelation, Caption());
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsIAccessibleTable implementation
 
@@ -1523,21 +1523,18 @@ nsHTMLTableAccessible::IsProbablyForLayo
 NS_IMETHODIMP
 nsHTMLCaptionAccessible::GetRelationByType(PRUint32 aRelationType,
                                            nsIAccessibleRelation **aRelation)
 {
   nsresult rv = nsHyperTextAccessible::GetRelationByType(aRelationType,
                                                          aRelation);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (aRelationType == nsIAccessibleRelation::RELATION_DESCRIPTION_FOR) {
-    nsCOMPtr<nsIAccessible> accParent;
-    GetParent(getter_AddRefs(accParent));
-    return nsRelUtils::AddTarget(aRelationType, aRelation, accParent);
-  }
+  if (aRelationType == nsIAccessibleRelation::RELATION_LABEL_FOR)
+    return nsRelUtils::AddTarget(aRelationType, aRelation, GetParent());
 
   return NS_OK;
 }
 
 PRUint32
 nsHTMLCaptionAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_CAPTION;
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -44,20 +44,18 @@
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsTextAttrs.h"
 
 #include "nsIClipboard.h"
 #include "nsContentCID.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
-#include "nsPIDOMWindow.h"        
 #include "nsIDOMRange.h"
 #include "nsIDOMNSRange.h"
-#include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsFrameSelection.h"
 #include "nsILineIterator.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPlaintextEditor.h"
--- a/accessible/tests/mochitest/relations/test_general.html
+++ b/accessible/tests/mochitest/relations/test_general.html
@@ -97,18 +97,18 @@
       // output 'for' relations
       testRelation("output", RELATION_CONTROLLED_BY, ["input", "input2"]);
       testRelation("output2", RELATION_CONTROLLED_BY, ["input", "input2"]);
       testRelation("input", RELATION_CONTROLLER_FOR, ["output", "output2"]);
       testRelation("input2", RELATION_CONTROLLER_FOR, ["output", "output2"]);
 
       // 'described by'/'description for' relation for html:table and
       // html:caption
-      testRelation("caption", RELATION_DESCRIPTION_FOR, "table");
-      testRelation("table", RELATION_DESCRIBED_BY, "caption");
+      testRelation("caption", RELATION_LABEL_FOR, "table");
+      testRelation("table", RELATION_LABELLED_BY, "caption");
 
       // 'labelled by'/'label for' relation for html:fieldset and
       // html:legend
       testRelation("legend", RELATION_LABEL_FOR, "fieldset");
       testRelation("fieldset", RELATION_LABELLED_BY, "legend");
 
       // 'embeds' relation for root accessible
       var docAcc = null;
old mode 100755
new mode 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -562,17 +562,17 @@ pref("accessibility.typeaheadfind.flashB
 // plugin finder service url
 pref("pfs.datasource.url", "https://pfs.mozilla.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%&appID=%APP_ID%&appVersion=%APP_VERSION%&clientOS=%CLIENT_OS%&chromeLocale=%CHROME_LOCALE%&appRelease=%APP_RELEASE%");
 
 // by default we show an infobar message when pages require plugins the user has not installed, or are outdated
 pref("plugins.hide_infobar_for_missing_plugin", false);
 pref("plugins.hide_infobar_for_outdated_plugin", false);
 
 #ifdef XP_MACOSX
-pref("plugins.use_layers", false);
+pref("plugins.use_layers", true);
 pref("plugins.hide_infobar_for_carbon_failure_plugin", false);
 #endif
 
 pref("plugins.update.url", "https://www.mozilla.com/%LOCALE%/plugincheck/");
 pref("plugins.update.notifyUser", false);
 
 #ifdef XP_WIN
 pref("browser.preferences.instantApply", false);
--- a/browser/base/content/browser-tabview.js
+++ b/browser/base/content/browser-tabview.js
@@ -430,12 +430,17 @@ let TabView = {
       return;
 
     // do nothing if we already enabled session restore once
     if (this.sessionRestoreEnabledOnce)
       return;
 
     this.sessionRestoreEnabledOnce = true;
 
-    // enable session restore
-    Services.prefs.setIntPref(this.PREF_STARTUP_PAGE, 3);
+    // enable session restore if necessary
+    if (Services.prefs.getIntPref(this.PREF_STARTUP_PAGE) != 3) {
+      Services.prefs.setIntPref(this.PREF_STARTUP_PAGE, 3);
+
+      // show banner
+      this._window.UI.notifySessionRestoreEnabled();
+    }
   }
 };
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1410,16 +1410,18 @@ function prepareForStartup() {
     if (!webNavigation)
       throw "no XBL binding for browser";
   } catch (e) {
     alert("Error launching browser window:" + e);
     window.close(); // Give up.
     return;
   }
 
+  messageManager.loadFrameScript("chrome://browser/content/content.js", true);
+
   // initialize observers and listeners
   // and give C++ access to gBrowser
   gBrowser.init();
   XULBrowserWindow.init();
   window.QueryInterface(Ci.nsIInterfaceRequestor)
         .getInterface(nsIWebNavigation)
         .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
         .QueryInterface(Ci.nsIInterfaceRequestor)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/content.js
@@ -0,0 +1,53 @@
+# -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is multi-process front-end code.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Felipe Gomes <felipc@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+// Bug 671101 - directly using webNavigation in this context
+// causes docshells to leak
+__defineGetter__("webNavigation", function() {
+  return docShell.QueryInterface(Ci.nsIWebNavigation);
+});
+
+addMessageListener("WebNavigation:LoadURI", function(message) {
+  let flags = message.json.flags || webNavigation.LOAD_FLAGS_NONE;
+
+  webNavigation.loadURI(message.json.uri, flags, null, null, null);
+});
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -40,16 +40,17 @@
 #   Michael Ventnor <ventnors_dogs234@yahoo.com.au>
 #   Simon Bünzli <zeniko@gmail.com>
 #   Gijs Kruitbosch <gijskruitbosch@gmail.com>
 #   Ehsan Akhgari <ehsan.akhgari@gmail.com>
 #   Dan Mosedale <dmose@mozilla.org>
 #   Justin Dolske <dolske@mozilla.com>
 #   Kathleen Brade <brade@pearlcrescent.com>
 #   Mark Smith <mcs@pearlcrescent.com>
+#   Kailas Patil <patilkr24@gmail.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either the GNU General Public License Version 2 or later (the "GPL"), or
 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 # in which case the provisions of the GPL or the LGPL are applicable instead
 # of those above. If you wish to allow use of your version of this file only
 # under the terms of either the GPL or the LGPL, and not to allow others to
 # use your version of this file under the terms of the MPL, indicate your
@@ -874,27 +875,22 @@ nsContextMenu.prototype = {
 #endif
   },
 
   // Save URL of clicked-on frame.
   saveFrame: function () {
     saveDocument(this.target.ownerDocument);
   },
 
-  // Save URL of clicked-on link.
-  saveLink: function() {
+  // Helper function to wait for appropriate MIME-type headers and
+  // then prompt the user with a file picker
+  saveHelper: function(linkURL, linkText, dialogTitle, bypassCache, doc) {
     // canonical def in nsURILoader.h
     const NS_ERROR_SAVE_LINK_AS_TIMEOUT = 0x805d0020;
 
-    var doc =  this.target.ownerDocument;
-    urlSecurityCheck(this.linkURL, doc.nodePrincipal);
-    var linkText = this.linkText();
-    var linkURL = this.linkURL;
-
-
     // an object to proxy the data through to
     // nsIExternalHelperAppService.doContent, which will wait for the
     // appropriate MIME-type headers and then prompt the user with a
     // file picker
     function saveAsListener() {}
     saveAsListener.prototype = {
       extListener: null, 
 
@@ -936,17 +932,17 @@ nsContextMenu.prototype = {
         this.extListener.onStartRequest(aRequest, aContext);
       }, 
 
       onStopRequest: function saveLinkAs_onStopRequest(aRequest, aContext, 
                                                        aStatusCode) {
         if (aStatusCode == NS_ERROR_SAVE_LINK_AS_TIMEOUT) {
           // do it the old fashioned way, which will pick the best filename
           // it can without waiting.
-          saveURL(linkURL, linkText, null, true, false, doc.documentURIObject);
+          saveURL(linkURL, linkText, dialogTitle, bypassCache, false, doc.documentURIObject);
         }
         if (this.extListener)
           this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
       },
 
       onDataAvailable: function saveLinkAs_onDataAvailable(aRequest, aContext,
                                                            aInputStream,
                                                            aOffset, aCount) {
@@ -980,20 +976,29 @@ nsContextMenu.prototype = {
         channel.cancel(NS_ERROR_SAVE_LINK_AS_TIMEOUT);
         return;
       }
     }
 
     // set up a channel to do the saving
     var ioService = Cc["@mozilla.org/network/io-service;1"].
                     getService(Ci.nsIIOService);
-    var channel = ioService.newChannelFromURI(this.getLinkURI());
+    var channel = ioService.newChannelFromURI(makeURI(linkURL));
     channel.notificationCallbacks = new callbacks();
-    channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE |
-                         Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
+
+    let flags = Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
+
+    if (bypassCache)
+      flags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
+
+    if (channel instanceof Ci.nsICachingChannel)
+      flags |= Ci.nsICachingChannel.LOAD_BYPASS_LOCAL_CACHE_IF_BUSY;
+
+    channel.loadFlags |= flags;
+
     if (channel instanceof Ci.nsIHttpChannel) {
       channel.referrer = doc.documentURIObject;
       if (channel instanceof Ci.nsIHttpChannelInternal)
         channel.forceAllowThirdPartyCookie = true;
     }
 
     // fallback to the old way if we don't see the headers quickly 
     var timeToWait = 
@@ -1001,16 +1006,24 @@ nsContextMenu.prototype = {
     var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
     timer.initWithCallback(new timerCallback(), timeToWait,
                            timer.TYPE_ONE_SHOT);
 
     // kick off the channel with our proxy object as the listener
     channel.asyncOpen(new saveAsListener(), null);
   },
 
+  // Save URL of clicked-on link.
+  saveLink: function() {
+    var doc =  this.target.ownerDocument;
+    urlSecurityCheck(this.linkURL, doc.nodePrincipal);
+
+    this.saveHelper(this.linkURL, this.linkText(), null, true, doc);
+  },
+
   sendLink: function() {
     // we don't know the title of the link so pass in an empty string
     MailIntegration.sendMessage( this.linkURL, "" );
   },
 
   // Backwards-compatability wrapper
   saveImage : function() {
     if (this.onCanvas || this.onImage)
@@ -1028,18 +1041,17 @@ nsContextMenu.prototype = {
     else if (this.onImage) {
       urlSecurityCheck(this.mediaURL, doc.nodePrincipal);
       saveImageURL(this.mediaURL, null, "SaveImageTitle", false,
                    false, doc.documentURIObject);
     }
     else if (this.onVideo || this.onAudio) {
       urlSecurityCheck(this.mediaURL, doc.nodePrincipal);
       var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
-      saveURL(this.mediaURL, null, dialogTitle, false,
-              false, doc.documentURIObject);
+      this.saveHelper(this.mediaURL, null, dialogTitle, false, doc);
     }
   },
 
   // Backwards-compatability wrapper
   sendImage : function() {
     if (this.onCanvas || this.onImage)
         this.sendMedia();
   },
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -81,16 +81,18 @@ function GroupItem(listOfEls, options) {
   this.expanded = null;
   this.hidden = false;
   this.fadeAwayUndoButtonDelay = 15000;
   this.fadeAwayUndoButtonDuration = 300;
 
   this.keepProportional = false;
   this._frozenItemSizeData = {};
 
+  this._onChildClose = this._onChildClose.bind(this);
+
   // Variable: _activeTab
   // The <TabItem> for the groupItem's active tab.
   this._activeTab = null;
 
   if (Utils.isPoint(options.userSize))
     this.userSize = new Point(options.userSize);
 
   var self = this;
@@ -186,16 +188,17 @@ function GroupItem(listOfEls, options) {
   };
 
   this.$title
     .blur(function() {
       self._titleFocused = false;
       self.$titleShield.show();
       if (self.getTitle())
         gTabView.firstUseExperienced = true;
+      self.save();
     })
     .focus(function() {
       self._unfreezeItemSize();
       if (!self._titleFocused) {
         (self.$title)[0].select();
         self._titleFocused = true;
       }
     })
@@ -812,27 +815,25 @@ GroupItem.prototype = Utils.extend(new I
     // when "TabClose" event is fired, the browser tab is about to close and our 
     // item "close" event is fired.  And then, the browser tab gets closed. 
     // In other words, the group "close" event is fired before all browser
     // tabs in the group are closed.  The below code would fire the group "close"
     // event only after all browser tabs in that group are closed.
     let shouldRemoveTabItems = [];
     let toClose = this._children.concat();
     toClose.forEach(function(child) {
-      child.removeSubscriber(self, "close");
+      child.removeSubscriber("close", self._onChildClose);
 
       let removed = child.close(true);
       if (removed) {
         shouldRemoveTabItems.push(child);
       } else {
         // child.removeSubscriber() must be called before child.close(), 
         // therefore we call child.addSubscriber() if the tab is not removed.
-        child.addSubscriber(self, "close", function() {
-          self.remove(child);
-        });
+        child.addSubscriber("close", self._onChildClose);
       }
     });
 
     if (shouldRemoveTabItems.length != toClose.length) {
       // remove children without the assiciated tab and show the group item
       shouldRemoveTabItems.forEach(function(child) {
         self.remove(child, { dontArrange: true });
       });
@@ -1005,29 +1006,17 @@ GroupItem.prototype = Utils.extend(new I
       this._children.splice(index, 0, item);
 
       item.setZ(this.getZ() + 1);
 
       if (!wasAlreadyInThisGroupItem) {
         item.droppable(false);
         item.groupItemData = {};
 
-        item.addSubscriber(this, "close", function() {
-          let count = self._children.length;
-          let dontArrange = self.expanded || !self.shouldStack(count);
-          let dontClose = !item.closedManually && gBrowser._numPinnedTabs > 0;
-          self.remove(item, {dontArrange: dontArrange, dontClose: dontClose});
-
-          if (dontArrange)
-            self._freezeItemSize(count);
-
-          if (self._children.length > 0 && self._activeTab)
-            UI.setActive(self);
-        });
-
+        item.addSubscriber("close", this._onChildClose);
         item.setParent(this);
 
         if (typeof item.setResizable == 'function')
           item.setResizable(false, options.immediately);
 
         if (item == UI.getActiveTab() || !this._activeTab)
           this.setActiveTab(item);
 
@@ -1046,16 +1035,35 @@ GroupItem.prototype = Utils.extend(new I
 
       UI.setReorderTabsOnHide(this);
     } catch(e) {
       Utils.log('GroupItem.add error', e);
     }
   },
 
   // ----------
+  // Function: _onChildClose
+  // Handles "close" events from the group's children.
+  //
+  // Parameters:
+  //   tabItem - The tabItem that is closed.
+  _onChildClose: function GroupItem__onChildClose(tabItem) {
+    let count = this._children.length;
+    let dontArrange = this.expanded || !this.shouldStack(count);
+    let dontClose = !tabItem.closedManually && gBrowser._numPinnedTabs > 0;
+    this.remove(tabItem, {dontArrange: dontArrange, dontClose: dontClose});
+
+    if (dontArrange)
+      this._freezeItemSize(count);
+
+    if (this._children.length > 0 && this._activeTab)
+      UI.setActive(this);
+  },
+
+  // ----------
   // Function: remove
   // Removes an item from the groupItem.
   // Parameters:
   //
   //   a - The item to remove. Can be an <Item>, a DOM element or an iQ object.
   //       The latter two must refer to the container of an <Item>.
   //   options - An optional object with settings for this call. See below.
   //
@@ -1099,17 +1107,17 @@ GroupItem.prototype = Utils.extend(new I
 
       // Force tabItem resize if it's dragged out of a stacked groupItem.
       // The tabItems's title will be visible and that's why we need to
       // recalculate its height.
       if (item.isDragging && this.isStacked())
         item.setBounds(item.getBounds(), true, {force: true});
 
       item.droppable(true);
-      item.removeSubscriber(this, "close");
+      item.removeSubscriber("close", this._onChildClose);
 
       if (typeof item.setResizable == 'function')
         item.setResizable(true, options.immediately);
 
       // if a blank tab is selected while restoring a tab the blank tab gets
       // removed. we need to keep the group alive for the restored tab.
       if (item.isRemovedAfterRestore)
         options.dontClose = true;
--- a/browser/base/content/tabview/modules/utils.jsm
+++ b/browser/base/content/tabview/modules/utils.jsm
@@ -400,69 +400,58 @@ Range.prototype = {
 function Subscribable() {
   this.subscribers = null;
 };
 
 Subscribable.prototype = {
   // ----------
   // Function: addSubscriber
   // The given callback will be called when the Subscribable fires the given event.
-  // The refObject is used to facilitate removal if necessary.
-  addSubscriber: function Subscribable_addSubscriber(refObject, eventName, callback) {
+  addSubscriber: function Subscribable_addSubscriber(eventName, callback) {
     try {
-      Utils.assertThrow(refObject, "refObject");
       Utils.assertThrow(typeof callback == "function", "callback must be a function");
       Utils.assertThrow(eventName && typeof eventName == "string",
           "eventName must be a non-empty string");
     } catch(e) {
       Utils.log(e);
       return;
     }
 
     if (!this.subscribers)
       this.subscribers = {};
 
     if (!this.subscribers[eventName])
       this.subscribers[eventName] = [];
 
-    var subs = this.subscribers[eventName];
-    var existing = subs.filter(function(element) {
-      return element.refObject == refObject;
-    });
-
-    if (existing.length) {
-      Utils.assert(existing.length == 1, 'should only ever be one');
-      existing[0].callback = callback;
-    } else {
-      subs.push({
-        refObject: refObject,
-        callback: callback
-      });
-    }
+    let subscribers = this.subscribers[eventName];
+    if (subscribers.indexOf(callback) == -1)
+      subscribers.push(callback);
   },
 
   // ----------
   // Function: removeSubscriber
-  // Removes the callback associated with refObject for the given event.
-  removeSubscriber: function Subscribable_removeSubscriber(refObject, eventName) {
+  // Removes the subscriber associated with the event for the given callback.
+  removeSubscriber: function Subscribable_removeSubscriber(eventName, callback) {
     try {
-      Utils.assertThrow(refObject, "refObject");
+      Utils.assertThrow(typeof callback == "function", "callback must be a function");
       Utils.assertThrow(eventName && typeof eventName == "string",
           "eventName must be a non-empty string");
     } catch(e) {
       Utils.log(e);
       return;
     }
 
     if (!this.subscribers || !this.subscribers[eventName])
       return;
 
-    this.subscribers[eventName] = this.subscribers[eventName].filter(function(element) {
-      return element.refObject != refObject;
-    });
+    let subscribers = this.subscribers[eventName];
+    let index = subscribers.indexOf(callback);
+
+    if (index > -1)
+      subscribers.splice(index, 1);
   },
 
   // ----------
   // Function: _sendToSubscribers
   // Internal routine. Used by the Subscribable to fire events.
   _sendToSubscribers: function Subscribable__sendToSubscribers(eventName, eventInfo) {
     try {
       Utils.assertThrow(eventName && typeof eventName == "string",
@@ -470,20 +459,20 @@ Subscribable.prototype = {
     } catch(e) {
       Utils.log(e);
       return;
     }
 
     if (!this.subscribers || !this.subscribers[eventName])
       return;
 
-    var subsCopy = this.subscribers[eventName].concat();
-    subsCopy.forEach(function(object) {
+    let subsCopy = this.subscribers[eventName].concat();
+    subsCopy.forEach(function (callback) {
       try {
-        object.callback(this, eventInfo);
+        callback(this, eventInfo);
       } catch(e) {
         Utils.log(e);
       }
     }, this);
   }
 };
 
 // ##########
--- a/browser/base/content/tabview/tabview.css
+++ b/browser/base/content/tabview/tabview.css
@@ -173,16 +173,30 @@ body {
 .shield {
   left: 0;
   top: 0;
   width: 100%;
   height: 100%;
   position: absolute;
 }
 
+.banner {
+  left: 0;
+  bottom: 0;
+  right: 0;
+  padding: 10px 0;
+  position: absolute;
+  z-index: 1000060;
+  background: #000;
+  color: #fff;
+  opacity: 0;
+  text-align: center;
+  font-weight: 700;
+}
+
 /* Resizable
 ----------------------------------*/
 .resizer {
   position: absolute;
 }
 
 .iq-resizable-handle {
   position: absolute;
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -130,16 +130,20 @@ let UI = {
   // Variable: isDOMWindowClosing
   // Tells wether the parent window is about to close
   isDOMWindowClosing: false,
 
   // Variable: _browserKeys
   // Used to keep track of allowed browser keys.
   _browserKeys: null,
 
+  // Variable: _browserKeysWithShift
+  // Used to keep track of allowed browser keys with Shift key combination.
+  _browserKeysWithShift: null,
+
   // Variable: ignoreKeypressForSearch
   // Used to prevent keypress being handled after quitting search mode.
   ignoreKeypressForSearch: false,
 
   // Variable: _lastOpenedTab
   // Used to keep track of the last opened tab.
   _lastOpenedTab: null,
 
@@ -391,32 +395,39 @@ let UI = {
   // Parameters:
   //  - Takes a <TabItem>
   _setActiveTab: function UI__setActiveTab(tabItem) {
     if (tabItem == this._activeTab)
       return;
 
     if (this._activeTab) {
       this._activeTab.makeDeactive();
-      this._activeTab.removeSubscriber(this, "close");
+      this._activeTab.removeSubscriber("close", this._onActiveTabClosed);
     }
+
     this._activeTab = tabItem;
 
     if (this._activeTab) {
-      let self = this;
-      this._activeTab.addSubscriber(this, "close", function(closedTabItem) {
-        if (self._activeTab == closedTabItem)
-          self._setActiveTab(null);
-      });
-
+      this._activeTab.addSubscriber("close", this._onActiveTabClosed);
       this._activeTab.makeActive();
     }
   },
 
   // ----------
+  // Function: _onActiveTabClosed
+  // Handles when the currently active tab gets closed.
+  //
+  // Parameters:
+  //  - the <TabItem> that is closed
+  _onActiveTabClosed: function UI__onActiveTabClosed(tabItem){
+    if (UI._activeTab == tabItem)
+      UI._setActiveTab(null);
+  },
+
+  // ----------
   // Function: setActive
   // Sets the active tab item or group item
   // Parameters:
   //
   // options
   //  dontSetActiveTabInGroup bool for not setting active tab in group
   setActive: function UI_setActive(item, options) {
     Utils.assert(item, "item must be given");
@@ -430,16 +441,23 @@ let UI = {
         let activeTab = item.getActiveTab()
         if (activeTab)
           this._setActiveTab(activeTab);
       }
     }
   },
 
   // ----------
+  // Function: clearActiveTab
+  // Sets the active tab to 'null'.
+  clearActiveTab: function UI_clearActiveTab() {
+    this._setActiveTab(null);
+  },
+
+  // ----------
   // Function: isTabViewVisible
   // Returns true if the TabView UI is currently shown.
   isTabViewVisible: function UI_isTabViewVisible() {
     return gTabViewDeck.selectedPanel == gTabViewFrame;
   },
 
   // ---------
   // Function: _initPageDirection
@@ -461,17 +479,16 @@ let UI = {
     if (this.isTabViewVisible())
       return;
 
     // initialize the direction of the page
     this._initPageDirection();
 
     var self = this;
     var currentTab = this._currentTab;
-    var item = null;
 
     this._reorderTabItemsOnShow.forEach(function(groupItem) {
       groupItem.reorderTabItemsBasedOnTabOrder();
     });
     this._reorderTabItemsOnShow = [];
 
 #ifdef XP_WIN
     // Restore the full height when showing TabView
@@ -486,17 +503,17 @@ let UI = {
     this.setTitlebarColors(true);
 #endif
     let event = document.createEvent("Events");
     event.initEvent("tabviewshown", true, false);
 
     Storage.saveVisibilityData(gWindow, "true");
 
     if (zoomOut && currentTab && currentTab._tabViewTabItem) {
-      item = currentTab._tabViewTabItem;
+      let item = currentTab._tabViewTabItem;
       // If there was a previous currentTab we want to animate
       // its thumbnail (canvas) for the zoom out.
       // Note that we start the animation on the chrome thread.
 
       // Zoom out!
       item.zoomOut(function() {
         if (!currentTab._tabViewTabItem) // if the tab's been destroyed
           item = null;
@@ -507,16 +524,17 @@ let UI = {
         dispatchEvent(event);
 
         // Flush pending updates
         GroupItems.flushAppTabUpdates();
 
         TabItems.resumePainting();
       });
     } else {
+      self.clearActiveTab();
       dispatchEvent(event);
 
       // Flush pending updates
       GroupItems.flushAppTabUpdates();
 
       TabItems.resumePainting();
     }
 
@@ -968,34 +986,37 @@ let UI = {
 #endif
 #ifdef XP_MACOSX
       "preferencesCmdMac", "minimizeWindow", "hideThisAppCmdMac",
 #endif
       "newNavigator", "newNavigatorTab", "undo", "cut", "copy", "paste", 
       "selectAll", "find"
     ].forEach(function(key) {
       let element = gWindow.document.getElementById("key_" + key);
-      keys[key] = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0);
+      let code = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0);
+      keys[code] = key;
     });
+    this._browserKeys = keys;
 
-    // for key combinations with shift key, the charCode of upper case letters 
-    // are different to the lower case ones so need to handle them differently.
+    keys = {};
+    // The lower case letters are passed to processBrowserKeys() even with shift 
+    // key when stimulating a key press using EventUtils.synthesizeKey() so need 
+    // to handle both upper and lower cases here.
     [
 #ifdef XP_UNIX
       "redo",
 #endif
       "closeWindow", "tabview", "undoCloseTab", "undoCloseWindow",
       "privatebrowsing"
     ].forEach(function(key) {
       let element = gWindow.document.getElementById("key_" + key);
-      keys[key] = element.getAttribute("key").toLocaleUpperCase().charCodeAt(0);
+      let code = element.getAttribute("key").toLocaleLowerCase().charCodeAt(0);
+      keys[code] = key;
     });
-
-    delete this._browserKeys;
-    this._browserKeys = keys;
+    this._browserKeysWithShift = keys;
   },
 
   // ----------
   // Function: _setTabViewFrameKeyHandlers
   // Sets up the key handlers for navigating between tabs within the TabView UI.
   _setTabViewFrameKeyHandlers: function UI__setTabViewFrameKeyHandlers() {
     let self = this;
 
@@ -1017,54 +1038,35 @@ let UI = {
 
 #ifdef XP_MACOSX
         if (evt.metaKey) {
 #else
         if (evt.ctrlKey) {
 #endif
           let preventDefault = true;
           if (evt.shiftKey) {
-            switch (evt.charCode) {
-              case self._browserKeys.tabview:
+            // when a user presses ctrl+shift+key, upper case letter charCode 
+            // is passed to processBrowserKeys() so converting back to lower 
+            // case charCode before doing the check
+            let lowercaseCharCode =
+              String.fromCharCode(evt.charCode).toLocaleLowerCase().charCodeAt(0);
+            if (lowercaseCharCode in self._browserKeysWithShift) {
+              let key = self._browserKeysWithShift[lowercaseCharCode];
+              if (key == "tabview")
                 self.exit();
-                break;
-#ifdef XP_UNIX
-              case self._browserKeys.redo:
-#endif
-              case self._browserKeys.closeWindow:
-              case self._browserKeys.undoCloseTab:
-              case self._browserKeys.undoCloseWindow:
-              case self._browserKeys.privatebrowsing:
+              else
                 preventDefault = false;
-                break;
             }
           } else {
-            switch (evt.charCode) {
-              case self._browserKeys.find:
+            if (evt.charCode in self._browserKeys) {
+              let key = self._browserKeys[evt.charCode];
+              if (key == "find")
                 self.enableSearch();
-                break;
-#ifdef XP_UNIX
-              case self._browserKeys.quitApplication:
-#else
-              case self._browserKeys.redo:
-#endif
-#ifdef XP_MACOSX
-              case self._browserKeys.preferencesCmdMac:
-              case self._browserKeys.minimizeWindow:
-              case self._browserKeys.hideThisAppCmdMac:
-#endif
-              case self._browserKeys.newNavigator:
-              case self._browserKeys.newNavigatorTab:
-              case self._browserKeys.undo:
-              case self._browserKeys.cut:
-              case self._browserKeys.copy:
-              case self._browserKeys.paste:
-              case self._browserKeys.selectAll:
+              else
                 preventDefault = false;
-                break;
             }
           }
           if (preventDefault) {
             evt.stopPropagation();
             evt.preventDefault();
           }
         }
       }
@@ -1563,13 +1565,42 @@ let UI = {
 
     // use the tab image if it doesn't start with http e.g. data:image/png, chrome://
     if (tab.image && !(/^https?:/.test(tab.image)))
       url = tab.image;
     else
       url = gFavIconService.getFaviconImageForPage(tab.linkedBrowser.currentURI).spec;
 
     return url;
+  },
+
+  // ----------
+  // Function: notifySessionRestoreEnabled
+  // Notify the user that session restore has been automatically enabled
+  // by showing a banner that expects no user interaction. It fades out after
+  // some seconds.
+  notifySessionRestoreEnabled: function UI_notifySessionRestoreEnabled() {
+    let brandBundle = gWindow.document.getElementById("bundle_brand");
+    let brandShortName = brandBundle.getString("brandShortName");
+    let notificationText = tabviewBundle.formatStringFromName(
+      "tabview.notification.sessionStore", [brandShortName], 1);
+
+    let banner = iQ("<div>")
+      .text(notificationText)
+      .addClass("banner")
+      .appendTo("body");
+
+    let onFadeOut = function () {
+      banner.remove();
+    };
+
+    let onFadeIn = function () {
+      setTimeout(function () {
+        banner.animate({opacity: 0}, {duration: 1500, complete: onFadeOut});
+      }, 5000);
+    };
+
+    banner.animate({opacity: 0.7}, {duration: 1500, complete: onFadeIn});
   }
 };
 
 // ----------
 UI.init();
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -207,16 +207,20 @@ endif
                  browser_sanitize-passwordDisabledHosts.js \
                  browser_sanitize-sitepermissions.js \
                  browser_sanitize-timespans.js \
                  browser_clearplugindata.js \
                  browser_clearplugindata.html \
                  browser_clearplugindata_noage.html \
                  browser_popupUI.js \
                  browser_sanitizeDialog.js \
+                 browser_save_video.js \
+                 bug564387.html \
+                 bug564387_video1.ogv \
+                 bug564387_video1.ogv^headers^ \
                  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_bug519216.js
+++ b/browser/base/content/test/browser_bug519216.js
@@ -36,13 +36,15 @@ var progressListener3 = {
   }
 };
 
 var expectListener4 = false;
 var progressListener4 = {
   onLocationChange: function onLocationChange() {
     ok(expectListener4, "didn't call progressListener4 for the first location change");
     gBrowser.removeProgressListener(this);
-    gBrowser.addTab();
-    gBrowser.removeCurrentTab();
-    finish();
+    executeSoon(function () {
+      gBrowser.addTab();
+      gBrowser.removeCurrentTab();
+      finish();
+    });
   }
 };
--- a/browser/base/content/test/browser_bug553455.js
+++ b/browser/base/content/test/browser_bug553455.js
@@ -45,17 +45,17 @@ function wait_for_notification_close(aCa
 function wait_for_install_dialog(aCallback) {
   info("Waiting for install dialog");
   Services.wm.addListener({
     onOpenWindow: function(aXULWindow) {
       info("Install dialog opened, waiting for focus");
       Services.wm.removeListener(this);
 
       var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                                .getInterface(Ci.nsIDOMWindowInternal);
+                                .getInterface(Ci.nsIDOMWindow);
       waitForFocus(function() {
         info("Saw install dialog");
         is(domwindow.document.location.href, XPINSTALL_URL, "Should have seen the right window open");
 
         // Override the countdown timer on the accept button
         var button = domwindow.document.documentElement.getButton("accept");
         button.disabled = false;
 
--- a/browser/base/content/test/browser_popupNotification.js
+++ b/browser/base/content/test/browser_popupNotification.js
@@ -105,19 +105,21 @@ function runNextTest() {
     doOnPopupEvent("popuphidden", function () {
       if (!gShownState[gTestIndex]) {
         // This is expected to happen for test 9, so let's not treat it as a failure.
         info("Popup from test " + gTestIndex + " was hidden before its popupshown fired");
       }
 
       let onHidden = onHiddenArray.shift();
       info("[Test #" + gTestIndex + "] popup hidden (" + onHiddenArray.length + " hides remaining)");
-      onHidden.call(nextTest, this);
-      if (!onHiddenArray.length)
-        goNext();
+      executeSoon(function () {
+        onHidden.call(nextTest, this);
+        if (!onHiddenArray.length)
+          goNext();
+      });
     }, onHiddenArray.length);
     info("[Test #" + gTestIndex + "] added listeners; panel state: " + PopupNotifications.isPanelOpen);
   }
 
   info("[Test #" + gTestIndex + "] running test");
   nextTest.run();
 }
 
@@ -734,9 +736,9 @@ function loadURI(uri, callback) {
   gBrowser.loadURI(uri);
 }
 
 function dismissNotification(popup) {
   info("[Test #" + gTestIndex + "] dismissing notification");
   executeSoon(function () {
     EventUtils.synthesizeKey("VK_ESCAPE", {});
   });
-}
\ No newline at end of file
+}
--- a/browser/base/content/test/browser_sanitize-download-history.js
+++ b/browser/base/content/test/browser_sanitize-download-history.js
@@ -136,30 +136,30 @@ function test()
            getService(Ci.nsIDownloadManager);
   let db = dm.DBConnection;
 
   // Empty any old downloads
   db.executeSimpleSQL("DELETE FROM moz_downloads");
 
   // Close the UI if necessary
   let win = Services.ww.getWindowByName("Sanatize", null);
-  if (win && (win instanceof Ci.nsIDOMWindowInternal))
+  if (win && (win instanceof Ci.nsIDOMWindow))
     win.close();
 
   // Start the test when the sanitize window loads
   Services.ww.registerNotification(function (aSubject, aTopic, aData) {
     Services.ww.unregisterNotification(arguments.callee);
     aSubject.QueryInterface(Ci.nsIDOMEventTarget)
             .addEventListener("DOMContentLoaded", doTest, false);
   });
 
   // Let the methods that run onload finish before we test
   let doTest = function() setTimeout(function() {
     let win = Services.ww.getWindowByName("Sanitize", null)
-                .QueryInterface(Ci.nsIDOMWindowInternal);
+                .QueryInterface(Ci.nsIDOMWindow);
 
     for (let i = 0; i < tests.length; i++)
       tests[i](win);
 
     win.close();
     finish();
   }, 0);
  
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_save_video.js
@@ -0,0 +1,110 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * TestCase for bug 564387
+ * <https://bugzilla.mozilla.org/show_bug.cgi?id=564387>
+ */
+function test() {
+
+  // --- Testing support library ---
+
+  // Import the toolkit test support library in the scope of the current test.
+  // This operation also defines the common constants Cc, Ci, Cu, Cr and Cm.
+  Components.classes["@mozilla.org/moz/jssubscript-loader;1"].
+   getService(Components.interfaces.mozIJSSubScriptLoader).loadSubScript(
+   "chrome://mochitests/content/browser/toolkit/content/tests/browser/common/_loadAll.js",
+   this);
+
+  // --- Test implementation ---
+
+  const kBaseUrl =
+        "http://mochi.test:8888/browser/browser/base/content/test/";
+
+  function pageShown(event) {
+    if (event.target.location != "about:blank")
+      testRunner.continueTest();
+  }
+
+  function saveVideoAs_TestGenerator() {
+    // Load Test page
+    gBrowser.addEventListener("pageshow", pageShown, false);
+    gBrowser.loadURI(kBaseUrl + "bug564387.html");
+    yield;
+    gBrowser.removeEventListener("pageshow", pageShown, false);
+
+    // Ensure that the window is focused.
+    SimpleTest.waitForFocus(testRunner.continueTest);
+    yield;
+
+    try {
+      // get the video element
+      var video1 = gBrowser.contentDocument.getElementById("video1");
+
+      // Synthesize the right click on the context menu, and
+      // wait for it to be shown
+      document.addEventListener("popupshown", testRunner.continueTest, false);
+      EventUtils.synthesizeMouseAtCenter(video1,
+                                         { type: "contextmenu", button: 2 },
+                                         gBrowser.contentWindow);
+      yield;
+
+      // Create the folder the video will be saved into.
+      var destDir = createTemporarySaveDirectory();
+      try {
+        // Call the appropriate save function defined in contentAreaUtils.js.
+        mockFilePickerSettings.destDir = destDir;
+        mockFilePickerSettings.filterIndex = 1; // kSaveAsType_URL
+
+        // register mock file picker object
+        mockFilePickerRegisterer.register();
+        try {
+          // register mock download progress listener
+          mockTransferForContinuingRegisterer.register();
+          try {
+            // Select "Save Video As" option from context menu
+            var saveVideoCommand = document.getElementById("context-savevideo");
+            saveVideoCommand.doCommand();
+
+            // Unregister the popupshown listener
+            document.removeEventListener("popupshown",
+                                         testRunner.continueTest, false);
+            // Close the context menu
+            document.getElementById("placesContext").hidePopup();
+
+            // Wait for the download to finish, and exit if it wasn't successful.
+            var downloadSuccess = yield;
+            if (!downloadSuccess)
+              throw "Unexpected failure in downloading Video file!";
+          }
+          finally {
+            // unregister download progress listener
+            mockTransferForContinuingRegisterer.unregister();
+          }
+        }
+        finally {
+          // unregister mock file picker object
+          mockFilePickerRegisterer.unregister();
+        }
+
+        // Read the name of the saved file.
+        var fileName = mockFilePickerResults.selectedFile.leafName;
+
+        is(fileName, "Bug564387-expectedName.ogv",
+                     "Video File Name is correctly retrieved from Content-Disposition http header");
+      }
+      finally {
+        // Clean up the saved file.
+        destDir.remove(true);
+      }
+    }
+    finally {
+      // Replace the current tab with a clean one.
+      gBrowser.addTab().linkedBrowser.stop();
+      gBrowser.removeCurrentTab();
+    }
+  }
+
+  // --- Run the test ---
+  testRunner.runTest(saveVideoAs_TestGenerator);
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/bug564387.html
@@ -0,0 +1,11 @@
+<html>
+  <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=564387 -->
+  <head>
+    <title> Bug 564387 test</title>
+  </head>
+  <body>
+    Testing for Mozilla Bug: 564387
+    <br>
+    <video src="bug564387_video1.ogv" id="video1"> </video> 
+  </body>
+</html>
copy from embedding/test/320x240.ogv
copy to browser/base/content/test/bug564387_video1.ogv
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/bug564387_video1.ogv^headers^
@@ -0,0 +1,3 @@
+Content-Disposition: filename="Bug564387-expectedName.ogv" 
+Content-Type: video/ogg
+
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -105,17 +105,16 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug624692.js \
                  browser_tabview_bug624727.js \
                  browser_tabview_bug624847.js \
                  browser_tabview_bug624931.js \
                  browser_tabview_bug624953.js \
                  browser_tabview_bug625195.js \
                  browser_tabview_bug625269.js \
                  browser_tabview_bug625424.js \
-                 browser_tabview_bug625666.js \
                  browser_tabview_bug626368.js \
                  browser_tabview_bug626525.js \
                  browser_tabview_bug626791.js \
                  browser_tabview_bug627239.js \
                  browser_tabview_bug627288.js \
                  browser_tabview_bug627736.js \
                  browser_tabview_bug628061.js \
                  browser_tabview_bug628165.js \
@@ -145,16 +144,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug654721.js \
                  browser_tabview_bug654941.js \
                  browser_tabview_bug655269.js \
                  browser_tabview_bug656778.js \
                  browser_tabview_bug656913.js \
                  browser_tabview_bug662266.js \
                  browser_tabview_bug663421.js \
                  browser_tabview_bug665502.js \
+                 browser_tabview_bug669694.js \
                  browser_tabview_dragdrop.js \
                  browser_tabview_exit_button.js \
                  browser_tabview_expander.js \
                  browser_tabview_firstrun_pref.js \
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_multiwindow_search.js \
                  browser_tabview_privatebrowsing.js \
--- a/browser/base/content/test/tabview/browser_tabview_bug580412.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug580412.js
@@ -1,126 +1,80 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
-
-  window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
-  if (TabView.isVisible())
-    onTabViewWindowLoaded();
-  else
-    TabView.show();
+  showTabView(onTabViewShown);
 }
 
-function onTabViewWindowLoaded() {
-  window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
-
-  let contentWindow = document.getElementById("tab-view").contentWindow;
+function onTabViewShown() {
+  let contentWindow = TabView.getContentWindow();
   let [originalTab] = gBrowser.visibleTabs;
 
   ok(TabView.isVisible(), "Tab View is visible");
   is(contentWindow.GroupItems.groupItems.length, 1, "There is only one group");
   let currentActiveGroup = contentWindow.GroupItems.getActiveGroupItem();
 
-  // set double click interval to negative so quick drag and drop doesn't 
-  // trigger the double click code.
-  let origDBlClickInterval = contentWindow.UI.DBLCLICK_INTERVAL;
-  contentWindow.UI.DBLCLICK_INTERVAL = -1;
-
   let endGame = function() {
-    contentWindow.UI.reset();
-    contentWindow.UI.DBLCLICK_INTERVAL = origDBlClickInterval;
-
-    let onTabViewHidden = function() {
-      window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-      ok(!TabView.isVisible(), "TabView is shown");
-      finish();
-    };
-    window.addEventListener("tabviewhidden", onTabViewHidden, false);
-
     ok(TabView.isVisible(), "TabView is shown");
-
     gBrowser.selectedTab = originalTab;
-    TabView.hide();
-  }
 
-  let part1 = function() {
-    // move down 20 so we're far enough away from the top.
-    checkSnap(currentActiveGroup, 0, 20, contentWindow, function(snapped){
-      ok(!snapped,"Move away from the edge");
-
-      // Just pick it up and drop it.
-      checkSnap(currentActiveGroup, 0, 0, contentWindow, function(snapped){
-        ok(!snapped,"Just pick it up and drop it");
-
-        checkSnap(currentActiveGroup, 0, 1, contentWindow, function(snapped){
-          ok(snapped,"Drag one pixel: should snap");
-
-          checkSnap(currentActiveGroup, 0, 5, contentWindow, function(snapped){
-            ok(!snapped,"Moving five pixels: shouldn't snap");
-            endGame();
-          });
-        });
-      });
+    hideTabView(function () {
+      ok(!TabView.isVisible(), "TabView is hidden");
+      finish();
     });
   }
 
+  // we need to stop the setBounds() css animation or else the test will
+  // fail in single-mode because the group is newly created "ontabshown".
+  let $container = contentWindow.iQ(currentActiveGroup.container);
+  $container.css("-moz-transition-property", "none");
+
   currentActiveGroup.setPosition(40, 40, true);
   currentActiveGroup.arrange({animate: false});
-  part1();
+
+  // move down 20 so we're far enough away from the top.
+  checkSnap(currentActiveGroup, 0, 20, contentWindow, function(snapped){
+    is(currentActiveGroup.getBounds().top, 60, "group.top is 60px");
+    ok(!snapped,"Move away from the edge");
+
+    // Just pick it up and drop it.
+    checkSnap(currentActiveGroup, 0, 0, contentWindow, function(snapped){
+      is(currentActiveGroup.getBounds().top, 60, "group.top is 60px");
+      ok(!snapped,"Just pick it up and drop it");
+
+      checkSnap(currentActiveGroup, 0, 1, contentWindow, function(snapped){
+        is(currentActiveGroup.getBounds().top, 60, "group.top is 60px");
+        ok(snapped,"Drag one pixel: should snap");
+
+        checkSnap(currentActiveGroup, 0, 5, contentWindow, function(snapped){
+          is(currentActiveGroup.getBounds().top, 65, "group.top is 65px");
+          ok(!snapped,"Moving five pixels: shouldn't snap");
+          endGame();
+        });
+      });
+    });
+  });
 }
 
-function simulateDragDrop(tabItem, offsetX, offsetY, contentWindow) {
-  // enter drag mode
-  let dataTransfer;
-
-  EventUtils.synthesizeMouse(
-    tabItem.container, 1, 1, { type: "mousedown" }, contentWindow);
-  let event = contentWindow.document.createEvent("DragEvents");
-  event.initDragEvent(
-    "dragenter", true, true, contentWindow, 0, 0, 0, 0, 0,
-    false, false, false, false, 1, null, dataTransfer);
-  tabItem.container.dispatchEvent(event);
+function simulateDragDrop(item, offsetX, offsetY, contentWindow) {
+  let target = item.container;
 
-  // drag over
-  if (offsetX || offsetY) {
-    let Ci = Components.interfaces;
-    let utils = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
-                              getInterface(Ci.nsIDOMWindowUtils);
-    let rect = tabItem.getBounds();
-    for (let i = 1; i <= 5; i++) {
-      let left = rect.left + 1 + Math.round(i * offsetX / 5);
-      let top = rect.top + 1 + Math.round(i * offsetY / 5);
-      utils.sendMouseEvent("mousemove", left, top, 0, 1, 0);
-    }
-    event = contentWindow.document.createEvent("DragEvents");
-    event.initDragEvent(
-      "dragover", true, true, contentWindow, 0, 0, 0, 0, 0,
-      false, false, false, false, 0, null, dataTransfer);
-    tabItem.container.dispatchEvent(event);
-  }
-
-  // drop
-  EventUtils.synthesizeMouse(
-    tabItem.container, 0, 0, { type: "mouseup" }, contentWindow);
-  event = contentWindow.document.createEvent("DragEvents");
-  event.initDragEvent(
-    "drop", true, true, contentWindow, 0, 0, 0, 0, 0,
-    false, false, false, false, 0, null, dataTransfer);
-  tabItem.container.dispatchEvent(event);
+  EventUtils.synthesizeMouse(target, 1, 1, {type: "mousedown"}, contentWindow);
+  EventUtils.synthesizeMouse(target, 1 + offsetX, 1 + offsetY, {type: "mousemove"}, contentWindow);
+  EventUtils.synthesizeMouse(target, 1, 1, {type: "mouseup"}, contentWindow);
 }
 
 function checkSnap(item, offsetX, offsetY, contentWindow, callback) {
   let firstTop = item.getBounds().top;
   let firstLeft = item.getBounds().left;
-  let onDrop = function() {
-    let snapped = false;
-    item.container.removeEventListener('drop', onDrop, false);
-    if (item.getBounds().top != firstTop + offsetY)
-      snapped = true;
-    if (item.getBounds().left != firstLeft + offsetX)
-      snapped = true;
-    callback(snapped);
-  };
-  item.container.addEventListener('drop', onDrop, false);
+
   simulateDragDrop(item, offsetX, offsetY, contentWindow);
+
+  let snapped = false;
+  if (item.getBounds().top != firstTop + offsetY)
+    snapped = true;
+  if (item.getBounds().left != firstLeft + offsetX)
+    snapped = true;
+
+  callback(snapped);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug587276.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug587276.js
@@ -12,17 +12,17 @@ function test() {
 function test1() {
   ok(TabView.isVisible(), "Tab View is visible");
 
   contentWindow = document.getElementById("tab-view").contentWindow;
   whenTabViewIsHidden(function() {
     ok(!TabView.isVisible(), "Tab View is not visible");
     showTabView(test2);
   });
-  EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, contentWindow);
+  EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, contentWindow);
 }
 
 function test2() {
   ok(TabView.isVisible(), "Tab View is visible");
 
   whenSearchIsEnabled(function() {
     ok(contentWindow.isSearchEnabled(), "The search is enabled")
 
@@ -53,17 +53,17 @@ function test3() {
 function test4() {
   is(gBrowser.tabs.length, 2, "There are two tabs");
 
   let onTabClose = function() {
     gBrowser.tabContainer.removeEventListener("TabClose", onTabClose, true);
     executeSoon(function() {
       is(gBrowser.tabs.length, 1, "There is one tab after removing one");
 
-      EventUtils.synthesizeKey("T", { accelKey: true, shiftKey: true }, contentWindow);
+      EventUtils.synthesizeKey("t", { accelKey: true, shiftKey: true }, contentWindow);
       is(gBrowser.tabs.length, 2, "There are two tabs after restoring one");
 
       gBrowser.tabs[0].linkedBrowser.loadURI("about:blank");
       gBrowser.selectedTab = gBrowser.tabs[0];
       test8();
     });
   };
   gBrowser.tabContainer.addEventListener("TabClose", onTabClose, true);
@@ -91,15 +91,15 @@ function test9() {
   is(ZoomManager.zoom, zoomLevel, "The zoom level remains unchanged after cmd/ctrl + - is pressed");
 
   test10();
 }
 
 function test10() {
   is(gBrowser.tabs.length, 1, "There is one tab before cmd/ctrl + shift + a is pressed");
   // it would open about:addons on a new tab if it passes through the white list.
-  EventUtils.synthesizeKey("A", { accelKey: true, shiftKey: true }, contentWindow);
+  EventUtils.synthesizeKey("a", { accelKey: true, shiftKey: true }, contentWindow);
 
   executeSoon(function() {
     is(gBrowser.tabs.length, 1, "There is still one tab after cmd/ctrl + shift + a is pressed");
     hideTabView(finish);
   })
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug588265.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug588265.js
@@ -53,36 +53,36 @@ function createNewTabItemInGroupItem(gro
 function testGroups(groupItemOne, groupItemTwo, contentWindow) {
   // check active tab and group
   is(contentWindow.GroupItems.getActiveGroupItem(), groupItemTwo, 
      "The group two is the active group");
   is(contentWindow.UI.getActiveTab(), groupItemTwo.getChild(0), 
      "The first tab item in group two is active");
   
   let tabItem = groupItemOne.getChild(1);
-  tabItem.addSubscriber(tabItem, "tabRemoved", function() {
-    tabItem.removeSubscriber(tabItem, "tabRemoved");
+  tabItem.addSubscriber("tabRemoved", function onTabRemoved() {
+    tabItem.removeSubscriber("tabRemoved", onTabRemoved);
 
     is(groupItemOne.getChildren().length, 1,
       "The num of childen in group one is 1");
 
     // check active group and active tab
     is(contentWindow.GroupItems.getActiveGroupItem(), groupItemOne, 
        "The group one is the active group");
     is(contentWindow.UI.getActiveTab(), groupItemOne.getChild(0), 
        "The first tab item in group one is active");
 
     let onTabViewHidden = function() {
       window.removeEventListener("tabviewhidden", onTabViewHidden, false);
       is(groupItemOne.getChildren().length, 2, 
          "The num of childen in group one is 2");
 
       // clean up and finish
-      groupItemTwo.addSubscriber(groupItemTwo, "close", function() {
-        groupItemTwo.removeSubscriber(groupItemTwo, "close");
+      groupItemTwo.addSubscriber("close", function onClose() {
+        groupItemTwo.removeSubscriber("close", onClose);
 
         gBrowser.removeTab(groupItemOne.getChild(1).tab);
         is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
         is(groupItemOne.getChildren().length, 1, 
            "The num of childen in group one is 1");
         is(gBrowser.tabs.length, 1, "Has only one tab");
 
         finish();
--- a/browser/base/content/test/tabview/browser_tabview_bug591706.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug591706.js
@@ -41,18 +41,18 @@ function onTabViewWindowLoaded() {
   isnot(firstTab.linkedBrowser.contentWindow.location, secondTab.linkedBrowser.contentWindow.location, "The two tabs must have different locations");
 
   // Add the first tab to the group *programmatically*, without specifying a dropPos
   group.add(firstTabItem);
   is(group.getChildren().length, 2, "Two tabs in the group");
   is(group.getChildren()[0].tab.linkedBrowser.contentWindow.location, secondTab.linkedBrowser.contentWindow.location, "The second tab was there first");
   is(group.getChildren()[1].tab.linkedBrowser.contentWindow.location, firstTab.linkedBrowser.contentWindow.location, "The first tab was just added and went to the end of the line");
   
-  group.addSubscriber(group, "close", function() {
-    group.removeSubscriber(group, "close");
+  group.addSubscriber("close", function onClose() {
+    group.removeSubscriber("close", onClose);
 
     ok(group.isEmpty(), "The group is empty again");
 
     is(contentWindow.GroupItems.getActiveGroupItem(), currentGroup, "There is an active group");
     is(gBrowser.tabs.length, 1, "There is only one tab left");
     is(gBrowser.visibleTabs.length, 1, "There is also only one visible tab");
 
     let onTabViewHidden = function() {
--- a/browser/base/content/test/tabview/browser_tabview_bug595020.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595020.js
@@ -6,16 +6,18 @@ let ss = Cc["@mozilla.org/browser/sessio
 let stateStartup = {windows:[
   {tabs:[{entries:[{url:"about:home"}]}], extData:{"tabview-last-session-group-name":"title"}}
 ]};
 
 function test() {
   let assertWindowTitle = function (win, title) {
     let browser = win.gBrowser.tabs[0].linkedBrowser;
     let winTitle = win.gBrowser.getWindowTitleForBrowser(browser);
+
+    info('window title is: "' + winTitle + '"');
     is(winTitle.indexOf(title), 0, "title starts with '" + title + "'");
   };
 
   let testGroupNameChange = function (win) {
     showTabView(function () {
       let cw = win.TabView.getContentWindow();
       let groupItem = cw.GroupItems.groupItems[0];
       groupItem.setTitle("new-title");
--- a/browser/base/content/test/tabview/browser_tabview_bug595191.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595191.js
@@ -52,10 +52,10 @@ function toggleTabViewTest(contentWindow
   let onTabViewHidden = function() {
     contentWindow.removeEventListener("tabviewhidden", onTabViewHidden, false);
 
     ok(!TabView.isVisible(), "Tab View is hidden");
     finish();
   }
   contentWindow.addEventListener("tabviewhidden", onTabViewHidden, false);
   // Use keyboard shortcut to toggle back to browser view
-  EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true });
+  EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug595518.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595518.js
@@ -23,17 +23,17 @@ function onTabViewWindowLoaded() {
     
     // verify that the exit button no longer has focus
     is(contentWindow.iQ("#exit-button:focus").length, 0, 
        "The exit button doesn't have the focus");
 
     // verify that the keyboard combo works (this is the crux of bug 595518)
     // Prepare the key combo
     window.addEventListener("tabviewshown", onTabViewShown, false);
-    EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, contentWindow);
+    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, contentWindow);
   }
   
   let onTabViewShown = function() {
     window.removeEventListener("tabviewshown", onTabViewShown, false);
     
     // test if the key combo worked
     ok(TabView.isVisible(), "Tab View is visible");
 
--- a/browser/base/content/test/tabview/browser_tabview_bug595521.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595521.js
@@ -24,24 +24,24 @@ function testCloseLastGroup() {
   let checkExistence = function() {
     is(contentWindow.GroupItems.groupItems.length, 1, 
        "Still has one group after delay");
 
     EventUtils.sendMouseEvent(
       { type: "click" }, groupItem.$undoContainer[0], contentWindow);
   };
 
-  groupItem.addSubscriber(groupItem, "groupHidden", function() {
-    groupItem.removeSubscriber(groupItem, "groupHidden");
+  groupItem.addSubscriber("groupHidden", function onHidden() {
+    groupItem.removeSubscriber("groupHidden", onHidden);
     // it should still stay after 3 ms.
     setTimeout(checkExistence, 3);
   });
 
-  groupItem.addSubscriber(groupItem, "groupShown", function() {
-    groupItem.removeSubscriber(groupItem, "groupShown");
+  groupItem.addSubscriber("groupShown", function onShown() {
+    groupItem.removeSubscriber("groupShown", onShown);
 
     let endGame = function() {
       window.removeEventListener("tabviewhidden", endGame, false);
       ok(!TabView.isVisible(), "Tab View is hidden");
 
       groupItem.fadeAwayUndoButtonDelay = fadeAwayUndoButtonDelay;
       groupItem.fadeAwayUndoButtonDuration = fadeAwayUndoButtonDuration;
 
--- a/browser/base/content/test/tabview/browser_tabview_bug595930.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595930.js
@@ -21,40 +21,35 @@ function onTabViewWindowLoaded() {
   let group1 = new contentWindow.GroupItem([], { bounds: box1 });
   ok(group1.isEmpty(), "This group is empty");
   contentWindow.UI.setActive(group1);
   let tab1 = gBrowser.loadOneTab("about:blank#1", {inBackground: true});
   let tab1Item = tab1._tabViewTabItem;
   ok(group1.getChildren().some(function(child) child == tab1Item), "The tab was made in our new group");
   is(group1.getChildren().length, 1, "Only one tab in the first group");
 
-  group1.addSubscriber(group1, "close", function() {
-    group1.removeSubscriber(group1, "close");
+  group1.addSubscriber("close", function onClose() {
+    group1.removeSubscriber("close", onClose);
 
     let onTabViewHidden = function() {
       window.removeEventListener("tabviewhidden", onTabViewHidden, false);
       // assert that we're no longer in tab view
       ok(!TabView.isVisible(), "Tab View is hidden");
       finish();
     };
     window.addEventListener("tabviewhidden", onTabViewHidden, false);
 
     // delay to give time for hidden group DOM element to be removed so
     // the appropriate group would get selected when the key
     // combination is pressed
     executeSoon(function() { 
-      EventUtils.synthesizeKey("E", {accelKey : true, shiftKey: true}, contentWindow);
+      EventUtils.synthesizeKey("e", {accelKey : true, shiftKey: true}, contentWindow);
     });
   });
 
-  group1.addSubscriber(group1, "groupHidden", function() {
-    group1.removeSubscriber(group1, "groupHidden");
-
+  hideGroupItem(group1, function () {
     // close undo group
     let closeButton = group1.$undoContainer.find(".close");
     EventUtils.sendMouseEvent(
       { type: "click" }, closeButton[0], contentWindow);
   });
-
-  // Get rid of the group and its children
-  group1.closeAll();
 }
 
--- a/browser/base/content/test/tabview/browser_tabview_bug597248.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug597248.js
@@ -30,18 +30,18 @@ function setupTwo(win) {
   let tabItems = contentWindow.TabItems.getItems();
   is(tabItems.length, 3, "There should be 3 tab items before closing");
 
   let numTabsToSave = tabItems.length;
 
   // force all canvases to update, and hook in imageData save detection
   tabItems.forEach(function(tabItem) {
     contentWindow.TabItems.update(tabItem.tab);
-    tabItem.addSubscriber(tabItem, "savedCachedImageData", function(item) {
-      item.removeSubscriber(item, "savedCachedImageData");
+    tabItem.addSubscriber("savedCachedImageData", function onSaved(item) {
+      item.removeSubscriber("savedCachedImageData", onSaved);
       --numTabsToSave;
     });
   });
 
   // after the window is closed, restore it.
   let xulWindowDestory = function() {
     Services.obs.removeObserver(
        xulWindowDestory, "xul-window-destroyed", false);
@@ -82,18 +82,18 @@ function setupTwo(win) {
             else
               frameInitialized = true;
           }
 
           let tabItems = restoredContentWindow.TabItems.getItems();
           let count = tabItems.length;
 
           tabItems.forEach(function(tabItem) {
-            tabItem.addSubscriber(tabItem, "loadedCachedImageData", function() {
-              tabItem.removeSubscriber(tabItem, "loadedCachedImageData");
+            tabItem.addSubscriber("loadedCachedImageData", function onLoaded() {
+              tabItem.removeSubscriber("loadedCachedImageData", onLoaded);
               ok(tabItem.isShowingCachedData(),
                 "Tab item is showing cached data and is just connected. " +
                 tabItem.tab.linkedBrowser.currentURI.spec);
               if (--count == 0)
                 nextStep();
             });
           });
         }
--- a/browser/base/content/test/tabview/browser_tabview_bug597980.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug597980.js
@@ -73,13 +73,13 @@ function part2(win) {
 
     win.addEventListener("tabviewhidden", function () {
       win.removeEventListener("tabviewhidden", arguments.callee, false);
       is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)");
        win.close();
        finish();
     }, false);
     // show tabview
-    EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, win);
+    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
     // hide tabview
-    EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, win);
+    EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win);
   })
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug599626.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug599626.js
@@ -31,18 +31,18 @@ function onTabViewWindowLoaded() {
 
     testStayOnPage(contentWindow, groupItemOne, groupItemTwo);
   }
   browser.addEventListener("load", onLoad, true);
 }
 
 function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) {
   setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
-    groupItemTwo.addSubscriber(groupItemTwo, "groupShown", function() {
-      groupItemTwo.removeSubscriber(groupItemTwo, "groupShown");
+    groupItemTwo.addSubscriber("groupShown", function onShown() {
+      groupItemTwo.removeSubscriber("groupShown", onShown);
 
       is(gBrowser.tabs.length, 2, 
          "The total number of tab is 2 when staying on the page");
       is(contentWindow.TabItems.getItems().length, 2, 
          "The total number of tab items is 2 when staying on the page");
 
       let onTabViewShown = function() {
         window.removeEventListener("tabviewshown", onTabViewShown, false);
@@ -56,18 +56,18 @@ function testStayOnPage(contentWindow, g
     // stay on page
     doc.documentElement.getButton("cancel").click();
   });
 }
 
 function testLeavePage(contentWindow, groupItemOne, groupItemTwo) {
   setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
     // clean up and finish the test
-    groupItemTwo.addSubscriber(groupItemTwo, "close", function() {
-      groupItemTwo.removeSubscriber(groupItemTwo, "close");
+    groupItemTwo.addSubscriber("close", function onClose() {
+      groupItemTwo.removeSubscriber("close", onClose);
 
       is(gBrowser.tabs.length, 1,
          "The total number of tab is 1 after leaving the page");
       is(contentWindow.TabItems.getItems().length, 1, 
          "The total number of tab items is 1 after leaving the page");
 
       let endGame = function() {
         window.removeEventListener("tabviewhidden", endGame, false);
--- a/browser/base/content/test/tabview/browser_tabview_bug602432.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug602432.js
@@ -21,18 +21,18 @@ function test() {
     let numTabsToUpdate = 10;
     let groupItem = createGroupItemWithBlankTabs(win, 150, 150, 100, numTabsToUpdate, false);
     ok(groupItem.isStacked(), "groupItem is stacked");
 
     let cw = win.TabView.getContentWindow();
     cw.TabItems.pausePainting();
 
     groupItem.getChildren().forEach(function (tabItem) {
-      tabItem.addSubscriber(tabItem, "updated", function () {
-        tabItem.removeSubscriber(tabItem, "updated");
+      tabItem.addSubscriber("updated", function onUpdated() {
+        tabItem.removeSubscriber("updated", onUpdated);
         tabItem._testLastTabUpdateTime = tabItem._lastTabUpdateTime;
 
         if (--numTabsToUpdate)
           return;
 
         checkUpdateTimes(groupItem);
         finish();
       });
--- a/browser/base/content/test/tabview/browser_tabview_bug607108.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug607108.js
@@ -31,22 +31,17 @@ function test() {
     // enter a title for the new group
     EventUtils.synthesizeKey("t", {}, cw);
     EventUtils.synthesizeKey("VK_RETURN", {}, cw);
 
 
     let groupItem = cw.GroupItems.groupItems[1];
     is(groupItem.getTitle(), "t", "new groupItem's title is correct");
 
-    groupItem.addSubscriber(groupItem, "close", function () {
-      groupItem.removeSubscriber(groupItem, "close");
-      executeSoon(callback);
-    });
-
-    groupItem.closeAll();
+    closeGroupItem(groupItem, callback);
   };
 
   let testDragOutOfGroup = function (callback) {
     assertNumberOfGroupItems(1);
 
     let groupItem = cw.GroupItems.groupItems[0];
     dragTabOutOfGroup(groupItem);
     assertNumberOfGroupItems(2);
--- a/browser/base/content/test/tabview/browser_tabview_bug608037.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug608037.js
@@ -23,36 +23,20 @@ function onTabViewWindowLoaded() {
   let groupItems = contentWindow.GroupItems.groupItems;
   is(groupItems.length, 1, "There is only one group");
   is(groupItems[0].getChildren().length, 3, "The group has three tab items");
 
   gBrowser.removeTab(tabTwo);
   ok(TabView.isVisible(), "Tab View is still visible after removing a tab");
   is(groupItems[0].getChildren().length, 2, "The group has two tab items");
 
-  tabTwo = undoCloseTab(0);
-  whenTabIsReconnected(tabTwo, function() {
+  restoreTab(function (tabTwo) {
     ok(TabView.isVisible(), "Tab View is still visible after restoring a tab");
     is(groupItems[0].getChildren().length, 3, "The group still has three tab items");
 
     // clean up and finish
     hideTabView(function () {
       gBrowser.removeTab(tabOne);
       gBrowser.removeTab(tabTwo);
       finish();
     });
   });
 }
-
-// ----------
-function whenTabIsReconnected(tab, callback) {
-  let tabItem = tab._tabViewTabItem;
-
-  if (tabItem._reconnected) {
-    callback();
-    return;
-  }
-
-  tabItem.addSubscriber(tabItem, "reconnected", function () {
-    tabItem.removeSubscriber(tabItem, "reconnected");
-    callback();
-  });
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug608158.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug608158.js
@@ -13,27 +13,24 @@ function onTabViewWindowLoaded() {
 
   let contentWindow = document.getElementById("tab-view").contentWindow;
 
   is(contentWindow.GroupItems.groupItems.length, 1, 
      "There is one group item on startup");
   is(gBrowser.tabs.length, 1, "There is one tab on startup");
   let groupItem = contentWindow.GroupItems.groupItems[0];
 
-  groupItem.addSubscriber(groupItem, "groupHidden", function() {
-    groupItem.removeSubscriber(groupItem, "groupHidden");
-
+  hideGroupItem(groupItem, function () {
     let onTabViewHidden = function() {
       window.removeEventListener("tabviewhidden", onTabViewHidden, false);
       is(contentWindow.GroupItems.groupItems.length, 1, 
          "There is still one group item");
       isnot(groupItem, contentWindow.GroupItems.groupItems[0], 
             "The initial group item is not the same as the final group item");
       is(gBrowser.tabs.length, 1, "There is only one tab");
       ok(!TabView.isVisible(), "Tab View is hidden");
       finish();
     };
     window.addEventListener("tabviewhidden", onTabViewHidden, false);
 
     TabView.hide();
   });
-  groupItem.closeAll();
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug610208.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug610208.js
@@ -155,23 +155,23 @@ function test() {
   // layer
   let testExpandedMode = function () {
     let oldBounds = groupItem.getBounds();
     groupItem.setSize(100, 100, true);
     groupItem.setUserSize();
 
     ok(groupItem.isStacked(), 'testExpandedMode: group is stacked');
 
-    groupItem.addSubscriber(groupItem, 'expanded', function () {
-      groupItem.removeSubscriber(groupItem, 'expanded');
+    groupItem.addSubscriber('expanded', function onGroupExpanded() {
+      groupItem.removeSubscriber('expanded', onGroupExpanded);
       onExpanded();
     });
 
-    groupItem.addSubscriber(groupItem, 'collapsed', function () {
-      groupItem.removeSubscriber(groupItem, 'collapsed');
+    groupItem.addSubscriber('collapsed', function onGroupCollapsed() {
+      groupItem.removeSubscriber('collapsed', onGroupCollapsed);
       onCollapsed();
     });
 
     let onExpanded = function () {
       let originalBounds = groupItem.getChild(0).getBounds();
       let tabItem = groupItem.getChild(1);
       let bounds = tabItem.getBounds();
 
--- a/browser/base/content/test/tabview/browser_tabview_bug610242.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug610242.js
@@ -31,18 +31,18 @@ function onTabViewWindowLoaded(win) {
   let mozilla  = win.gBrowser.loadOneTab("about:mozilla", bg);
   let html     = win.gBrowser.loadOneTab("http://example.com", bg);
   let png      = win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/moz.png", bg);
   let svg      = win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/title_test.svg", bg);
   
   ok(!group.shouldStack(group._children.length), "Group should not stack.");
   
   // PREPARE FINISH:
-  group.addSubscriber(group, "close", function() {
-    group.removeSubscriber(group, "close");
+  group.addSubscriber("close", function onClose() {
+    group.removeSubscriber("close", onClose);
 
     ok(group.isEmpty(), "The group is empty again");
 
     contentWindow.UI.setActive(currentGroup);
     isnot(contentWindow.GroupItems.getActiveGroupItem(), null, "There is an active group");
     is(win.gBrowser.tabs.length, 1, "There is only one tab left");
     is(win.gBrowser.visibleTabs.length, 1, "There is also only one visible tab");
 
@@ -73,16 +73,12 @@ function onTabViewWindowLoaded(win) {
       check(datahtml, "datahtml", false);
       check(mozilla, "about:mozilla", true);
       check(html, "html", true);
       check(png, "png", false);
       check(svg, "svg", true);
   
       // Get rid of the group and its children
       // The group close will trigger a finish().
-      group.addSubscriber(group, "groupHidden", function() {
-        group.removeSubscriber(group, "groupHidden");
-        group.closeHidden();
-      });
-      group.closeAll();
+      closeGroupItem(group);
     }, win);  
   }, win);
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug613541.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug613541.js
@@ -15,33 +15,16 @@ function test() {
     cw.UI.setActive(groupItem);
 
     for (let i=0; i<numTabs || 0; i++)
       gBrowser.loadOneTab('about:blank', {inBackground: true});
 
     return groupItem;
   }
 
-  let hideGroupItem = function (groupItem, callback) {
-    groupItem.addSubscriber(groupItem, 'groupHidden', function () {
-      groupItem.removeSubscriber(groupItem, 'groupHidden');
-      callback();
-    });
-    groupItem.closeAll();
-  }
-
-  let closeGroupItem = function (groupItem, callback) {
-    afterAllTabsLoaded(function () {
-      hideGroupItem(groupItem, function () {
-        groupItem.closeHidden();
-        callback();
-      });
-    });
-  }
-
   let tests = [];
 
   let next = function () {
     let test = tests.shift();
 
     if (test) {
       // check that the previous test left things as expected
       if (currentTest) {
--- a/browser/base/content/test/tabview/browser_tabview_bug624847.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug624847.js
@@ -36,30 +36,16 @@ function test() {
   let createTab = function (url) {
     return gBrowser.loadOneTab(url || 'http://mochi.test:8888/', {inBackground: true});
   }
 
   let createBlankTab = function () {
     return createTab('about:blank');
   }
 
-  let restoreTab = function (callback) {
-    let tab = undoCloseTab(0);
-
-    if (tab._tabViewTabItem._reconnected) {
-      afterAllTabsLoaded(callback);
-      return;
-    }
-
-    tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
-      tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
-      afterAllTabsLoaded(callback);
-    });
-  }
-
   let finishTest = function () {
     prefix = 'finish';
     assertValidPrerequisites();
     finish();
   }
 
   let testUndoCloseWithSelectedBlankTab = function () {
     prefix = 'unpinned';
deleted file mode 100644
--- a/browser/base/content/test/tabview/browser_tabview_bug625666.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function test() {
-  let cw;
-
-  let getTabItemAspect = function (tabItem) {
-    let bounds = cw.iQ('.thumb', tabItem.container).bounds();
-    let padding = cw.TabItems.tabItemPadding;
-    return (bounds.height + padding.y) / (bounds.width + padding.x);
-  }
-
-  let getAspectRange = function () {
-    let aspect = cw.TabItems.tabAspect;
-    let variance = aspect / 100 * 1.5;
-    return new cw.Range(aspect - variance, aspect + variance);
-  }
-
-  waitForExplicitFinish();
-
-  newWindowWithTabView(function (win) {
-    registerCleanupFunction(function () win.close());
-    cw = win.TabView.getContentWindow();
-
-    // prepare orphan tab
-    let tabItem = win.gBrowser.tabs[0]._tabViewTabItem;
-    tabItem.parent.remove(tabItem, {immediately: true});
-    tabItem.setBounds(new cw.Rect(20, 20, 200, 165), true);
-
-    let bounds = tabItem.getBounds();
-
-    // prepare group item
-    let box = new cw.Rect(20, 300, 400, 200);
-    let groupItem = new cw.GroupItem([], {bounds: box, immediately: true});
-
-    groupItem.setBounds(new cw.Rect(20, 100, 400, 200));
-    groupItem.pushAway(true);
-
-    let newBounds = tabItem.getBounds();
-    ok(newBounds.width < bounds.width, "The new width of item is smaller than the old one.");
-    ok(newBounds.height < bounds.height, "The new height of item is smaller than the old one.");
-
-    let aspectRange = getAspectRange();
-    let aspect = getTabItemAspect(tabItem);
-    ok(aspectRange.contains(aspect), "orphaned tabItem's aspect is correct");
-
-    finish();
-  });
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug627239.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug627239.js
@@ -34,40 +34,34 @@ function test1() {
   newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
 
   afterAllTabsLoaded(function() {
     let tabItem = newTab._tabViewTabItem;
 
     ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab), 
        "Should not save the thumbnail for tab");
 
-    tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
-      tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
-      test2();
-    });
+    whenDeniedToCacheImageData(tabItem, test2);
     tabItem.save(true);
     HttpRequestObserver.cacheControlValue = null;
   });
 }
 
 function test2() {
   // page with cache-control: private, should save thumbnail
   HttpRequestObserver.cacheControlValue = "private";
 
   newTab.linkedBrowser.loadURI("http://www.example.com/");
   afterAllTabsLoaded(function() {
     let tabItem = newTab._tabViewTabItem;
 
     ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab), 
        "Should save the thumbnail for tab");
 
-    tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
-      tabItem.removeSubscriber(tabItem, "savedCachedImageData");
-      test3();
-    });
+    whenSavedCachedImageData(tabItem, test3);
     tabItem.save(true);
   });
 }
 
 function test3() {
   // page with cache-control: private with https caching enabled, should save thumbnail
   HttpRequestObserver.cacheControlValue = "private";
 
@@ -77,21 +71,17 @@ function test3() {
 
   newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/dummy_page.html");
   afterAllTabsLoaded(function() {
     let tabItem = newTab._tabViewTabItem;
 
     ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
        "Should save the thumbnail for tab");
 
-    tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
-      tabItem.removeSubscriber(tabItem, "savedCachedImageData");
-
-      test4();
-    });
+    whenSavedCachedImageData(tabItem, test4);
     tabItem.save(true);
   });
 }
 
 function test4() {
   // page with cache-control: public with https caching disabled, should save thumbnail
   HttpRequestObserver.cacheControlValue = "public";
 
@@ -99,39 +89,33 @@ function test4() {
 
   newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/");
   afterAllTabsLoaded(function() {
     let tabItem = newTab._tabViewTabItem;
 
     ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
        "Should save the thumbnail for tab");
 
-    tabItem.addSubscriber(tabItem, "savedCachedImageData", function() {
-      tabItem.removeSubscriber(tabItem, "savedCachedImageData");
-
-      test5();
-    });
+    whenSavedCachedImageData(tabItem, test5);
     tabItem.save(true);
   });
 }
 
 function test5() {
   // page with cache-control: private with https caching disabled, should not save thumbnail
   HttpRequestObserver.cacheControlValue = "private";
  
   newTab.linkedBrowser.loadURI("https://example.com/");
   afterAllTabsLoaded(function() {
     let tabItem = newTab._tabViewTabItem;
 
     ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
        "Should not the thumbnail for tab");
 
-    tabItem.addSubscriber(tabItem, "deniedToCacheImageData", function() {
-      tabItem.removeSubscriber(tabItem, "deniedToCacheImageData");
-
+    whenDeniedToCacheImageData(tabItem, function () {
       hideTabView(function () {
         gBrowser.removeTab(gBrowser.tabs[1]);
         finish();
       });
     });
     tabItem.save(true);
   });
 }
@@ -149,8 +133,22 @@ let HttpRequestObserver = {
   register: function() {
     Services.obs.addObserver(this, "http-on-examine-response", false);
   },
 
   unregister: function() {
     Services.obs.removeObserver(this, "http-on-examine-response");
   }
 };
+
+function whenSavedCachedImageData(tabItem, callback) {
+  tabItem.addSubscriber("savedCachedImageData", function onSaved() {
+    tabItem.removeSubscriber("savedCachedImageData", onSaved);
+    callback();
+  });
+}
+
+function whenDeniedToCacheImageData(tabItem, callback) {
+  tabItem.addSubscriber("deniedToCacheImageData", function onDenied() {
+    tabItem.removeSubscriber("deniedToCacheImageData", onDenied);
+    callback();
+  });
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug627288.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug627288.js
@@ -14,21 +14,21 @@ function test() {
       gBrowser.removeTab(tab);
 
       cw.TabItems.pauseReconnecting();
       tab = gBrowser.loadOneTab('http://mochi.test:8888/', {inBackground: true});
 
       afterAllTabsLoaded(function () {
         tabItem = tab._tabViewTabItem;
 
-        tabItem.addSubscriber(tabItem, "savedCachedImageData", function () {
-          tabItem.removeSubscriber(tabItem, "savedCachedImageData");
+        tabItem.addSubscriber("savedCachedImageData", function onSaved() {
+          tabItem.removeSubscriber("savedCachedImageData", onSaved);
 
-          tabItem.addSubscriber(tabItem, "loadedCachedImageData", function () {
-            tabItem.removeSubscriber(tabItem, "loadedCachedImageData");
+          tabItem.addSubscriber("loadedCachedImageData", function onLoaded() {
+            tabItem.removeSubscriber("loadedCachedImageData", onLoaded);
 
             ok(tabItem.isShowingCachedData(), 'tabItem shows cached data');
             testChangeUrlAfterReconnect();
           });
 
           cw.TabItems.resumeReconnecting();
         });
 
--- a/browser/base/content/test/tabview/browser_tabview_bug627736.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug627736.js
@@ -23,39 +23,39 @@ function onTabViewWindowLoaded(win) {
     contentWindow.UI.setActive(group);
     win.gBrowser.loadOneTab('about:blank', {inBackground: true});
   
     is(group.getChildren().length, 1, "The group has one child now.");
     let tab = group.getChild(0);
   
     function check() {
       if (groupOrTab == 'group') {
-        group.removeSubscriber(group, "groupHidden", check);
+        group.removeSubscriber("groupHidden", check);
         group.closeHidden();
       } else
-        tab.removeSubscriber(tab, "tabRemoved", check);
+        tab.removeSubscriber("tabRemoved", check);
   
       is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
         "The original group is active.");
       is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
         "The original tab is active");
   
       callback();
     }
   
     if (groupOrTab == 'group') {
-      group.addSubscriber(group, "groupHidden", check);
+      group.addSubscriber("groupHidden", check);
       group.closeAll();
     } else {
-      tab.addSubscriber(tab, "tabRemoved", check);
+      tab.addSubscriber("tabRemoved", check);
       tab.close();
     }
   }
 
   // PHASE 1: create a group with a tab and close the group.
   openAndClose("group", function postPhase1() {
     // PHASE 2: create a group with a tab and close the tab.
     openAndClose("tab", function postPhase2() {
       win.close();
       finish();
     });
   });
-}
\ No newline at end of file
+}
--- a/browser/base/content/test/tabview/browser_tabview_bug628270.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug628270.js
@@ -20,30 +20,16 @@ function test() {
         groupItem.close();
     });
   }
 
   let getGroupItem = function (index) {
     return cw.GroupItems.groupItems[index];
   }
 
-  let restoreTab = function (callback) {
-    let tab = undoCloseTab(0);
-
-    if (tab._tabViewTabItem._reconnected) {
-      callback();
-      return;
-    }
-
-    tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
-      tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
-      afterAllTabsLoaded(callback);
-    });
-  }
-
   let activateFirstGroupItem = function () {
     let activeTabItem = getGroupItem(0).getChild(0);
     cw.GroupItems.updateActiveGroupItemAndTabBar(activeTabItem);
   }
 
   let assertTabViewIsHidden = function () {
     ok(!TabView.isVisible(), prefix + ': tabview is hidden');
   }
--- a/browser/base/content/test/tabview/browser_tabview_bug629195.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug629195.js
@@ -14,22 +14,17 @@ function test() {
 
       contentWindow = win.document.getElementById("tab-view").contentWindow;
       is(contentWindow.GroupItems.groupItems.length, 1, "There is one group");
       is(contentWindow.GroupItems.groupItems[0].getChildren().length, 1,
          "The group has only one tab item");
 
       // show the undo close group button
       let group = contentWindow.GroupItems.groupItems[0];
-      group.closeAll();
-
-      group.addSubscriber(group, "groupHidden", function() {
-        group.removeSubscriber(group, "groupHidden");
-        restore(group.id);
-      });
+      hideGroupItem(group, function () restore(group.id));
     },
     function(newWin) {
       win = newWin;
       originalTab = win.gBrowser.visibleTabs[0];
       win.gBrowser.addTab();
       win.gBrowser.pinTab(originalTab);
     }
   );
--- a/browser/base/content/test/tabview/browser_tabview_bug631752.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug631752.js
@@ -38,23 +38,23 @@ function test() {
   let testDragOutOfStackedGroup = function () {
     dragTabItem();
 
     let secondGroup = cw.GroupItems.groupItems[1];
     closeGroupItem(secondGroup, testDragOutOfExpandedStackedGroup);
   }
 
   let testDragOutOfExpandedStackedGroup = function () {
-    groupItem.addSubscriber(groupItem, "expanded", function () {
-      groupItem.removeSubscriber(groupItem, "expanded");
+    groupItem.addSubscriber("expanded", function onExpanded() {
+      groupItem.removeSubscriber("expanded", onExpanded);
       dragTabItem();
     });
 
-    groupItem.addSubscriber(groupItem, "collapsed", function () {
-      groupItem.removeSubscriber(groupItem, "collapsed");
+    groupItem.addSubscriber("collapsed", function onCollapsed() {
+      groupItem.removeSubscriber("collapsed", onCollapsed);
 
       let secondGroup = cw.GroupItems.groupItems[1];
       closeGroupItem(secondGroup, function () hideTabView(finishTest));
     });
 
     groupItem.expand();
   }
 
--- a/browser/base/content/test/tabview/browser_tabview_bug633190.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug633190.js
@@ -66,18 +66,18 @@ function testCreateTabAndThen(callback) 
     // tab._tabViewTabItem exists
     executeSoon(function() {
       let tab = event.target;
       tabItem = tab._tabViewTabItem;
       ok(tabItem, "Tab item is available after tab open");
 
       registerCleanupFunction(function () gBrowser.removeTab(tab))
 
-      tabItem.addSubscriber(tabItem, "zoomedIn", function() {
-        tabItem.removeSubscriber(tabItem, "zoomedIn");
+      tabItem.addSubscriber("zoomedIn", function onZoomedIn() {
+        tabItem.removeSubscriber("zoomedIn", onZoomedIn);
 
         is(gBrowser.selectedTab, tab,
           "The selected tab is the same as the newly opened tab");
         executeSoon(callback);
       });
     });
   }
   gBrowser.tabContainer.addEventListener("TabOpen", onTabOpen, false);
--- a/browser/base/content/test/tabview/browser_tabview_bug648882.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug648882.js
@@ -16,18 +16,18 @@ function test() {
     // function returns false (busy) we expect no tabItem updates to happen.
     let busyCount = 5;
     cw.UI.isIdle = function () {
       return isIdle = (0 > --busyCount);
     };
 
     cw.TabItems.pausePainting();
 
-    tabItem.addSubscriber(tabItem, "updated", function () {
-      tabItem.removeSubscriber(tabItem, "updated");
+    tabItem.addSubscriber("updated", function onUpdated() {
+      tabItem.removeSubscriber("updated", onUpdated);
       ok(isIdle, "tabItem is updated only when UI is idle");
       finish();
     });
 
     cw.TabItems.update(tab);
     cw.TabItems.resumePainting();
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug655269.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug655269.js
@@ -3,18 +3,18 @@
 
 function test() {
   waitForExplicitFinish();
 
   newWindowWithTabView(function (win) {
     let cw = win.TabView.getContentWindow();
     let tabItem = win.gBrowser.tabs[0]._tabViewTabItem;
 
-    tabItem.addSubscriber(tabItem, "savedCachedImageData", function () {
-      tabItem.removeSubscriber(tabItem, "savedCachedImageData");
+    tabItem.addSubscriber("savedCachedImageData", function onSaved() {
+      tabItem.removeSubscriber("savedCachedImageData", onSaved);
 
       ok(cw.UI.isDOMWindowClosing, "dom window is closing");
       waitForFocus(finish);
     });
 
     win.close();
   });
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug656778.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug656778.js
@@ -25,16 +25,26 @@ function test() {
   };
 
   let assertPreferences = function (startupPage, firstRun, enabledOnce) {
     assertIntPref(TabView.PREF_STARTUP_PAGE, startupPage);
     assertBoolPref(TabView.PREF_FIRST_RUN, firstRun);
     assertBoolPref(TabView.PREF_RESTORE_ENABLED_ONCE, enabledOnce);
   };
 
+  let assertNotificationBannerVisible = function (win) {
+    let cw = win.TabView.getContentWindow();
+    is(cw.iQ(".banner").length, 1, "notification banner is visible");
+  };
+
+  let assertNotificationBannerNotVisible = function (win) {
+    let cw = win.TabView.getContentWindow();
+    is(cw.iQ(".banner").length, 0, "notification banner is not visible");
+  };
+
   let next = function () {
     if (tests.length == 0) {
       waitForFocus(finish);
       return;
     }
 
     let test = tests.shift();
     info("running " + test.name + "...");
@@ -47,16 +57,17 @@ function test() {
   //
   // Expected result:
   // When entering Panorma session restore will be enabled and a notification
   // banner is shown.
   let test1 = function test1() {
     setPreferences(1, true, false);
 
     newWindowWithTabView(function (win) {
+      assertNotificationBannerVisible(win);
       assertPreferences(3, true, true);
 
       win.close();
       next();
     });
   };
 
   // State:
@@ -67,20 +78,22 @@ function test() {
   // Expected result:
   // When entering Panorma nothing happens. When we detect that Panorama is
   // really used (firstUseExperienced = true) we notify that session restore
   // is now enabled.
   let test2 = function test2() {
     setPreferences(1, false, false);
 
     newWindowWithTabView(function (win) {
+      assertNotificationBannerNotVisible(win);
       assertPreferences(1, false, false);
 
       win.TabView.firstUseExperienced = true;
 
+      assertNotificationBannerVisible(win);
       assertPreferences(3, true, true);
 
       win.close();
       next();
     });
   };
 
   // State:
@@ -89,16 +102,17 @@ function test() {
   //
   // Expected result:
   // When entering Panorama nothing happens because session store is already
   // enabled so there's no reason to notify.
   let test3 = function test3() {
     setPreferences(3, true, false);
 
     newWindowWithTabView(function (win) {
+      assertNotificationBannerNotVisible(win);
       assertPreferences(3, true, true);
 
       win.close();
       next();
     });
   };
 
   // State:
@@ -106,16 +120,17 @@ function test() {
   // restore has been automatically activated.
   //
   // Expected result:
   // When entering Panorama nothing happens.
   let test4 = function test4() {
     setPreferences(3, true, true);
 
     newWindowWithTabView(function (win) {
+      assertNotificationBannerNotVisible(win);
       assertPreferences(3, true, true);
 
       win.close();
       next();
     });
   };
 
   // State:
@@ -124,16 +139,17 @@ function test() {
   // disabled by the user so we won't touch that again.
   //
   // Expected result:
   // When entering Panorama nothing happens and we didn't enable session restore.
   let test5 = function test5() {
     setPreferences(1, true, true);
 
     newWindowWithTabView(function (win) {
+      assertNotificationBannerNotVisible(win);
       assertPreferences(1, true, true);
 
       win.close();
       next();
     });
   };
 
   let tests = [test1, test2, test3, test4, test5];
--- a/browser/base/content/test/tabview/browser_tabview_bug662266.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug662266.js
@@ -13,18 +13,18 @@ function test() {
     let cw = win.TabView.getContentWindow();
     let groupItem = cw.GroupItems.groupItems[0];
     let children = groupItem.getChildren();
 
     groupItem.setSize(200, 200, true);
     ok(groupItem.isStacked(), "groupItem is now stacked");
     is(win.gBrowser.tabs.length, 5, "we have five tabs");
 
-    groupItem.addSubscriber(groupItem, "expanded", function onExpanded() {
-      groupItem.removeSubscriber(groupItem, "expanded");
+    groupItem.addSubscriber("expanded", function onExpanded() {
+      groupItem.removeSubscriber("expanded", onExpanded);
 
       ok(groupItem.expanded, "groupItem is expanded");
       let bounds = children[1].getBounds();
 
       // remove two tabs and see if the remaining tabs are re-arranged to fill
       // the resulting gaps
       for (let i = 0; i < 2; i++) {
         children[1].close();
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug669694.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  function onLoad(win) {
+    registerCleanupFunction(function () win.close());
+
+    let tab = win.gBrowser.addTab();
+    win.gBrowser.pinTab(tab);
+  }
+
+  function onShow(win) {
+    let tabs = win.gBrowser.tabs;
+
+    // zoom into normal tab
+    zoomIn(tabs[1], function () {
+      is(win.gBrowser.selectedTab, tabs[1], "normal tab is selected");
+
+      // select app tab
+      win.gBrowser.selectedTab = tabs[0];
+
+      toggleTabView(win, function () {
+        is(win.gBrowser.selectedTab, tabs[0], "app tab is selected");
+        finish();
+      });
+    });
+  }
+
+  newWindowWithTabView(onShow, onLoad);
+}
+
+// ----------
+function zoomIn(tab, callback) {
+  whenTabViewIsHidden(function () {
+    executeSoon(callback);
+  }, tab.ownerDocument.defaultView);
+
+  tab._tabViewTabItem.zoomIn();
+}
+
+// ----------
+function toggleTabView(win, callback) {
+  showTabView(function () {
+    hideTabView(callback, win);
+  }, win);
+}
--- a/browser/base/content/test/tabview/browser_tabview_dragdrop.js
+++ b/browser/base/content/test/tabview/browser_tabview_dragdrop.js
@@ -19,18 +19,18 @@ function onTabViewWindowLoaded() {
   // create group one and two
   let boxOne = new contentWindow.Rect(20, 20, 300, 300);
   let groupOne = new contentWindow.GroupItem([], { bounds: boxOne });
   ok(groupOne.isEmpty(), "This group is empty");
 
   let boxTwo = new contentWindow.Rect(20, 400, 300, 300);
   let groupTwo = new contentWindow.GroupItem([], { bounds: boxTwo });
 
-  groupOne.addSubscriber(groupOne, "childAdded", function() {
-    groupOne.removeSubscriber(groupOne, "childAdded");
+  groupOne.addSubscriber("childAdded", function onChildAdded() {
+    groupOne.removeSubscriber("childAdded", onChildAdded);
     groupTwo.newTab();
   });
 
   let count = 0;
   let onTabViewShown = function() {
     if (count == 2) {
       window.removeEventListener("tabviewshown", onTabViewShown, false);
       addTest(contentWindow, groupOne.id, groupTwo.id, originalTab);
@@ -63,39 +63,39 @@ function addTest(contentWindow, groupOne
   let groupTwoRectCenter = groupTwo.getBounds().center();
   let tabItemRectCenter = tabItem.getBounds().center();
   let offsetX =
     Math.round(groupTwoRectCenter.x - tabItemRectCenter.x);
   let offsetY =
     Math.round(groupTwoRectCenter.y - tabItemRectCenter.y);
 
   function endGame() {
-    groupTwo.removeSubscriber(groupTwo, "childAdded");
+    groupTwo.removeSubscriber("childAdded", endGame);
 
     is(groupOne.getChildren().length, --groupOneTabItemCount,
        "The number of children in group one is decreased by 1");
     is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
        "The number of children in group two is increased by 1");
   
     let onTabViewHidden = function() {
       window.removeEventListener("tabviewhidden", onTabViewHidden, false);
       groupTwo.closeAll();
       // close undo group
       let closeButton = groupTwo.$undoContainer.find(".close");
       EventUtils.sendMouseEvent(
         { type: "click" }, closeButton[0], contentWindow);
     };
-    groupTwo.addSubscriber(groupTwo, "close", function() {
-      groupTwo.removeSubscriber(groupTwo, "close");
-      finish();  
+    groupTwo.addSubscriber("close", function onClose() {
+      groupTwo.removeSubscriber("close", onClose);
+      finish(); 
     });
     window.addEventListener("tabviewhidden", onTabViewHidden, false);
     gBrowser.selectedTab = originalTab;
   }
-  groupTwo.addSubscriber(groupTwo, "childAdded", endGame);
+  groupTwo.addSubscriber("childAdded", endGame);
   
   simulateDragDrop(tabItem.container, offsetX, offsetY, contentWindow);
 }
 
 function simulateDragDrop(element, offsetX, offsetY, contentWindow) {
   let rect = element.getBoundingClientRect();
   let startX = (rect.right - rect.left)/2;
   let startY = (rect.bottom - rect.top)/2;
--- a/browser/base/content/test/tabview/browser_tabview_expander.js
+++ b/browser/base/content/test/tabview/browser_tabview_expander.js
@@ -46,50 +46,50 @@ function onTabViewWindowLoaded(win) {
     ok(group.getBounds().contains(expanderBounds), "The expander lies in the group.");
     let stackCenter = children[0].getBounds().center();
     ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack.");
   
     // STAGE 1:
     // Here, we just expand the group, click elsewhere, and make sure
     // it collapsed.
     let stage1expanded = function() {
-      group.removeSubscriber("test stage 1", "expanded", stage1expanded);
+      group.removeSubscriber("expanded", stage1expanded);
     
       ok(group.expanded, "The group is now expanded.");
       is(expander[0].style.display, "none", "The expander is hidden!");
       
       let overlay = contentWindow.document.getElementById("expandedTray");    
       ok(overlay, "The expanded tray exists.");
       let $overlay = contentWindow.iQ(overlay);
       
-      group.addSubscriber("test stage 1", "collapsed", stage1collapsed);
+      group.addSubscriber("collapsed", stage1collapsed);
       // null type means "click", for some reason...
       EventUtils.synthesizeMouse(contentWindow.document.body, 10, $overlay.bounds().bottom + 5,
                                  {type: null}, contentWindow);
     };
     
     let stage1collapsed = function() {
-      group.removeSubscriber("test stage 1", "collapsed", stage1collapsed);
+      group.removeSubscriber("collapsed", stage1collapsed);
       ok(!group.expanded, "The group is no longer expanded.");
       isnot(expander[0].style.display, "none", "The expander is visible!");
       let expanderBounds = expander.bounds();
       ok(group.getBounds().contains(expanderBounds), "The expander still lies in the group.");
       let stackCenter = children[0].getBounds().center();
       ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack.");
   
       // now, try opening it up again.
-      group.addSubscriber("test stage 2", "expanded", stage2expanded);
+      group.addSubscriber("expanded", stage2expanded);
       EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
     };
   
     // STAGE 2:
     // Now make sure every child of the group shows up within this "tray", and
     // click on one of them and make sure we go into the tab and the tray collapses.
     let stage2expanded = function() {
-      group.removeSubscriber("test stage 2", "expanded", stage2expanded);
+      group.removeSubscriber("expanded", stage2expanded);
     
       ok(group.expanded, "The group is now expanded.");
       is(expander[0].style.display, "none", "The expander is hidden!");
       
       let overlay = contentWindow.document.getElementById("expandedTray");    
       ok(overlay, "The expanded tray exists.");
       let $overlay = contentWindow.iQ(overlay);
       let overlayBounds = $overlay.bounds();
@@ -127,37 +127,37 @@ function onTabViewWindowLoaded(win) {
       // only check the first 6 tabs as the stack only contains 6 tab items.
       for (let i = 0; i < 6; i++) {
         if (i != 1)
           ok(children[i].zIndex < topChildzIndex,
             "The child[" + i + "] has smaller zIndex than second child");
       }
 
       // okay, expand this group one last time
-      group.addSubscriber("test stage 3", "expanded", stage3expanded);
+      group.addSubscriber("expanded", stage3expanded);
       EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
     }
 
     // STAGE 3:
     // Ensure that stack still shows the same top item after a expand and a collapse.
     let stage3expanded = function() {
-      group.removeSubscriber("test stage 3", "expanded", stage3expanded);
+      group.removeSubscriber("expanded", stage3expanded);
 
       ok(group.expanded, "The group is now expanded.");
       let overlay = contentWindow.document.getElementById("expandedTray");    
       let $overlay = contentWindow.iQ(overlay);
 
-      group.addSubscriber("test stage 3", "collapsed", stage3collapsed);
+      group.addSubscriber("collapsed", stage3collapsed);
       // null type means "click", for some reason...
       EventUtils.synthesizeMouse(contentWindow.document.body, 10, $overlay.bounds().bottom + 5,
                                  {type: null}, contentWindow);
     };
 
     let stage3collapsed = function() {
-      group.removeSubscriber("test stage 3", "collapsed", stage3collapsed);
+      group.removeSubscriber("collapsed", stage3collapsed);
 
       ok(!group.expanded, "The group is no longer expanded.");
       isnot(expander[0].style.display, "none", "The expander is visible!");
 
       let stackCenter = children[0].getBounds().center();
       ok(stackCenter.y < expanderBounds.center().y, "The expander is below the stack.");
 
       is(group.getTopChild(), children[1], 
@@ -171,26 +171,26 @@ function onTabViewWindowLoaded(win) {
             "The child[" + i + "] has smaller zIndex than second dhild after a collapse.");
       }
 
       // In preparation for Stage 4, find that original tab and make it the active tab.
       let originalTabItem = originalTab._tabViewTabItem;
       contentWindow.UI.setActive(originalTabItem);
 
       // now, try opening it up again.
-      group.addSubscriber("test stage 4", "expanded", stage4expanded);
+      group.addSubscriber("expanded", stage4expanded);
       EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
     };
 
     // STAGE 4:
     // Activate another tab not in this group, expand our stacked group, but then
     // enter Panorama (i.e., zoom into this other group), and make sure we can go to
     // it and that the tray gets collapsed.
     let stage4expanded = function() {
-      group.removeSubscriber("test stage 4", "expanded", stage4expanded);
+      group.removeSubscriber("expanded", stage4expanded);
     
       ok(group.expanded, "The group is now expanded.");
       is(expander[0].style.display, "none", "The expander is hidden!");
       let overlay = contentWindow.document.getElementById("expandedTray");
       ok(overlay, "The expanded tray exists.");
       
       let activeTab = contentWindow.UI.getActiveTab();
       ok(activeTab, "There is an active tab.");
@@ -226,12 +226,12 @@ function onTabViewWindowLoaded(win) {
       ok(!group.expanded, "The group is no longer expanded.");
       isnot(expander[0].style.display, "none", "The expander is visible!");
 
       win.close();
       finish();
     }
   
     // get the ball rolling
-    group.addSubscriber("test stage 1", "expanded", stage1expanded);
+    group.addSubscriber("expanded", stage1expanded);
     EventUtils.sendMouseEvent({ type: "click" }, expander[0], contentWindow);
   }, win);
 }
--- a/browser/base/content/test/tabview/browser_tabview_group.js
+++ b/browser/base/content/test/tabview/browser_tabview_group.js
@@ -32,18 +32,18 @@ function testEmptyGroupItem(contentWindo
   
   // create empty group item
   let emptyGroupItem = createEmptyGroupItem(contentWindow, 300, 300, 100);
   ok(emptyGroupItem.isEmpty(), "This group is empty");
 
   is(contentWindow.GroupItems.groupItems.length, ++groupItemCount,
      "The number of groups is increased by 1");
 
-  emptyGroupItem.addSubscriber(emptyGroupItem, "close", function() {
-    emptyGroupItem.removeSubscriber(emptyGroupItem, "close");
+  emptyGroupItem.addSubscriber("close", function onClose() {
+    emptyGroupItem.removeSubscriber("close", onClose);
 
     // check the number of groups.
     is(contentWindow.GroupItems.groupItems.length, --groupItemCount,
        "The number of groups is decreased by 1");
 
     testGroupItemWithTabItem(contentWindow);
   });
 
@@ -70,22 +70,22 @@ function testGroupItemWithTabItem(conten
   };
   let onTabViewShown = function() {
     window.removeEventListener("tabviewshown", onTabViewShown, false);
 
     let tabItem = groupItem.getChild(groupItem.getChildren().length - 1);
     ok(tabItem, "Tab item exists");
 
     let tabItemClosed = false;
-    tabItem.addSubscriber(tabItem, "close", function() {
-      tabItem.removeSubscriber(tabItem, "close");
+    tabItem.addSubscriber("close", function onClose() {
+      tabItem.removeSubscriber("close", onClose);
       tabItemClosed = true;
     });
-    tabItem.addSubscriber(tabItem, "tabRemoved", function() {
-      tabItem.removeSubscriber(tabItem, "tabRemoved");
+    tabItem.addSubscriber("tabRemoved", function onTabRemoved() {
+      tabItem.removeSubscriber("tabRemoved", onTabRemoved);
 
       ok(tabItemClosed, "The tab item is closed");
       is(groupItem.getChildren().length, --tabItemCount,
         "The number of children in new tab group is decreased by 1");
         
       ok(TabView.isVisible(), "Tab View is still shown");
 
       // Now there should only be one tab left, so we need to hide TabView
--- a/browser/base/content/test/tabview/browser_tabview_launch.js
+++ b/browser/base/content/test/tabview/browser_tabview_launch.js
@@ -23,17 +23,17 @@ function test() {
       deck.removeEventListener("select", onSelect, true);
 
       whenTabViewIsShown(function() {
         executeSoon(function() {
           testMethodToHideAndShowTabView(function() {
             newWin.document.getElementById("menu_tabview").doCommand();
           }, function() {
             testMethodToHideAndShowTabView(function() {
-              EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
+              EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, newWin);
             }, finish);
           });
         });
       }, win);
     };
 
     let deck = win.document.getElementById("tab-view-deck");
     deck.addEventListener("select", onSelect, true);
--- a/browser/base/content/test/tabview/browser_tabview_layout.js
+++ b/browser/base/content/test/tabview/browser_tabview_layout.js
@@ -77,18 +77,18 @@ function testEmptyGroupItem(contentWindo
             "Items do not overlap: "
             +jbounds.left+","+jbounds.top+","+jbounds.width+","+jbounds.height+" ; "
             +ibounds.left+","+ibounds.top+","+ibounds.width+","+ibounds.height);        
         }
       }
     }
 
     // Shut down
-    emptyGroupItem.addSubscriber(emptyGroupItem, "close", function() {
-      emptyGroupItem.removeSubscriber(emptyGroupItem, "close");
+    emptyGroupItem.addSubscriber("close", function onClose() {
+      emptyGroupItem.removeSubscriber("close", onClose);
   
       // check the number of groups.
       is(contentWindow.GroupItems.groupItems.length, --groupItemCount,
          "The number of groups is decreased by 1");
 
       let onTabViewHidden = function() {
         window.removeEventListener("tabviewhidden", onTabViewHidden, false);
         // assert that we're no longer in tab view
--- a/browser/base/content/test/tabview/browser_tabview_undo_group.js
+++ b/browser/base/content/test/tabview/browser_tabview_undo_group.js
@@ -41,36 +41,36 @@ function onTabViewWindowLoaded() {
   // click on the + button
   let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
   ok(newTabButton[0], "New tab button exists");
 
   EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
 }
 
 function testUndoGroup(contentWindow, groupItem) {
-  groupItem.addSubscriber(groupItem, "groupHidden", function() {
-    groupItem.removeSubscriber(groupItem, "groupHidden");
+  groupItem.addSubscriber("groupHidden", function onHidden() {
+    groupItem.removeSubscriber("groupHidden", onHidden);
 
     // check the data of the group
     let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
     ok(theGroupItem, "The group item still exists");
     is(theGroupItem.getChildren().length, 1, 
        "The tab item in the group still exists");
 
     // check the visibility of the group element and undo element
     is(theGroupItem.container.style.display, "none", 
        "The group element is hidden");
     ok(theGroupItem.$undoContainer, "Undo container is avaliable");
 
     EventUtils.sendMouseEvent(
       { type: "click" }, theGroupItem.$undoContainer[0], contentWindow);
   });
 
-  groupItem.addSubscriber(groupItem, "groupShown", function() {
-    groupItem.removeSubscriber(groupItem, "groupShown");
+  groupItem.addSubscriber("groupShown", function onShown() {
+    groupItem.removeSubscriber("groupShown", onShown);
 
     // check the data of the group
     let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
     ok(theGroupItem, "The group item still exists");
     is(theGroupItem.getChildren().length, 1, 
        "The tab item in the group still exists");
 
     // check the visibility of the group element and undo element
@@ -82,18 +82,18 @@ function testUndoGroup(contentWindow, gr
   });
 
   let closeButton = groupItem.container.getElementsByClassName("close");
   ok(closeButton[0], "Group item close button exists");
   EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
 }
 
 function testCloseUndoGroup(contentWindow, groupItem) {
-  groupItem.addSubscriber(groupItem, "groupHidden", function() {
-    groupItem.removeSubscriber(groupItem, "groupHidden");
+  groupItem.addSubscriber("groupHidden", function onHidden() {
+    groupItem.removeSubscriber("groupHidden", onHidden);
 
     // check the data of the group
     let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
     ok(theGroupItem, "The group item still exists");
     is(theGroupItem.getChildren().length, 1, 
        "The tab item in the group still exists");
 
     // check the visibility of the group element and undo element
@@ -102,18 +102,18 @@ function testCloseUndoGroup(contentWindo
     ok(theGroupItem.$undoContainer, "Undo container is avaliable");
 
     // click on close
     let closeButton = theGroupItem.$undoContainer.find(".close");
     EventUtils.sendMouseEvent(
       { type: "click" }, closeButton[0], contentWindow);
   });
 
-  groupItem.addSubscriber(groupItem, "close", function() {
-    groupItem.removeSubscriber(groupItem, "close");
+  groupItem.addSubscriber("close", function onClose() {
+    groupItem.removeSubscriber("close", onClose);
 
     let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id);
     ok(!theGroupItem, "The group item doesn't exists");
 
     let endGame = function() {
       window.removeEventListener("tabviewhidden", endGame, false);
       ok(!TabView.isVisible(), "Tab View is hidden");
       finish();
--- a/browser/base/content/test/tabview/head.js
+++ b/browser/base/content/test/tabview/head.js
@@ -40,25 +40,25 @@ function createGroupItemWithBlankTabs(wi
   let urls = [];
   while(numNewTabs--)
     urls.push("about:blank");
   return createGroupItemWithTabs(win, width, height, padding, urls, animate);
 }
 
 // ----------
 function closeGroupItem(groupItem, callback) {
-  groupItem.addSubscriber(groupItem, "close", function () {
-    groupItem.removeSubscriber(groupItem, "close");
+  groupItem.addSubscriber("close", function onClose() {
+    groupItem.removeSubscriber("close", onClose);
     if ("function" == typeof callback)
       executeSoon(callback);
   });
 
   if (groupItem.getChildren().length) {
-    groupItem.addSubscriber(groupItem, "groupHidden", function () {
-      groupItem.removeSubscriber(groupItem, "groupHidden");
+    groupItem.addSubscriber("groupHidden", function onHide() {
+      groupItem.removeSubscriber("groupHidden", onHide);
       groupItem.closeHidden();
     });
   }
 
   groupItem.closeAll();
 }
 
 // ----------
@@ -78,19 +78,21 @@ function afterAllTabItemsUpdated(callbac
 function newWindowWithTabView(shownCallback, loadCallback, width, height) {
   let winWidth = width || 800;
   let winHeight = height || 800;
   let win = window.openDialog(getBrowserURL(), "_blank",
                               "chrome,all,dialog=no,height=" + winHeight +
                               ",width=" + winWidth);
 
   whenWindowLoaded(win, function () {
-    if (typeof loadCallback == "function")
+    if (loadCallback)
       loadCallback(win);
+  });
 
+  whenDelayedStartupFinished(win, function () {
     showTabView(function () shownCallback(win), win);
   });
 }
 
 // ----------
 function afterAllTabsLoaded(callback, win) {
   const TAB_STATE_NEEDS_RESTORE = 1;
 
@@ -215,62 +217,62 @@ function whenSearchIsEnabled(callback, w
   win = win || window;
 
   let contentWindow = win.TabView.getContentWindow();
   if (contentWindow.isSearchEnabled()) {
     callback();
     return;
   }
 
-  contentWindow.addEventListener("tabviewsearchenabled", function () {
-    contentWindow.removeEventListener("tabviewsearchenabled", arguments.callee, false);
+  contentWindow.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
+    contentWindow.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
     callback();
   }, false);
 }
 
 // ----------
 function whenSearchIsDisabled(callback, win) {
   win = win || window;
 
   let contentWindow = win.TabView.getContentWindow();
   if (!contentWindow.isSearchEnabled()) {
     callback();
     return;
   }
 
-  contentWindow.addEventListener("tabviewsearchdisabled", function () {
-    contentWindow.removeEventListener("tabviewsearchdisabled", arguments.callee, false);
+  contentWindow.addEventListener("tabviewsearchdisabled", function onSearchDisabled() {
+    contentWindow.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false);
     callback();
   }, false);
 }
 
 
 // ----------
 function hideGroupItem(groupItem, callback) {
   if (groupItem.hidden) {
     callback();
     return;
   }
 
-  groupItem.addSubscriber(groupItem, "groupHidden", function () {
-    groupItem.removeSubscriber(groupItem, "groupHidden");
+  groupItem.addSubscriber("groupHidden", function onHide() {
+    groupItem.removeSubscriber("groupHidden", onHide);
     callback();
   });
   groupItem.closeAll();
 }
 
 // ----------
 function unhideGroupItem(groupItem, callback) {
   if (!groupItem.hidden) {
     callback();
     return;
   }
 
-  groupItem.addSubscriber(groupItem, "groupShown", function () {
-    groupItem.removeSubscriber(groupItem, "groupShown");
+  groupItem.addSubscriber("groupShown", function onShown() {
+    groupItem.removeSubscriber("groupShown", onShown);
     callback();
   });
   groupItem._unhide();
 }
 
 // ----------
 function whenWindowLoaded(win, callback) {
   win.addEventListener("load", function onLoad() {
@@ -335,13 +337,13 @@ function restoreTab(callback, index, win
     afterAllTabsLoaded(function () callback(tab), win);
   };
 
   if (tabItem._reconnected) {
     finalize();
     return;
   }
 
-  tab._tabViewTabItem.addSubscriber(tab, "reconnected", function onReconnected() {
-    tab._tabViewTabItem.removeSubscriber(tab, "reconnected");
+  tab._tabViewTabItem.addSubscriber("reconnected", function onReconnected() {
+    tab._tabViewTabItem.removeSubscriber("reconnected", onReconnected);
     finalize();
   });
 }
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -24,16 +24,17 @@ browser.jar:
         content/browser/aboutHome-snippet1.png        (content/aboutHome-snippet1.png)
         content/browser/aboutHome-snippet2.png        (content/aboutHome-snippet2.png)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
 *       content/browser/browser.css                   (content/browser.css)
 *       content/browser/browser.js                    (content/browser.js)
 *       content/browser/browser.xul                   (content/browser.xul)
 *       content/browser/browser-tabPreviews.xml       (content/browser-tabPreviews.xml)
+*       content/browser/content.js                    (content/content.js)
 *       content/browser/fullscreen-video.xhtml        (content/fullscreen-video.xhtml)
 *       content/browser/inspector.html                (content/inspector.html)
 *       content/browser/scratchpad.xul                (content/scratchpad.xul)
 *       content/browser/scratchpad.js                 (content/scratchpad.js)
 *       content/browser/pageinfo/pageInfo.xul         (content/pageinfo/pageInfo.xul)
 *       content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
 *       content/browser/pageinfo/pageInfo.css         (content/pageinfo/pageInfo.css)
 *       content/browser/pageinfo/pageInfo.xml         (content/pageinfo/pageInfo.xml)
--- a/browser/components/migration/src/nsProfileMigrator.cpp
+++ b/browser/components/migration/src/nsProfileMigrator.cpp
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsProfileMigrator.h"
 
 #include "nsIBrowserProfileMigrator.h"
 #include "nsIComponentManager.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsILocalFile.h"
 #include "nsIObserverService.h"
 #include "nsIProperties.h"
 #include "nsIServiceManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsISupportsArray.h"
 #include "nsIToolkitProfile.h"
 #include "nsIToolkitProfileService.h"
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -373,19 +373,21 @@ BrowserGlue.prototype = {
     this._sanitizer.onShutdown();
   },
 
   // Browser startup complete. All initial windows have opened.
   _onBrowserStartup: function BG__onBrowserStartup() {
     // Show about:rights notification, if needed.
     if (this._shouldShowRights()) {
       this._showRightsNotification();
+#ifdef MOZ_TELEMETRY_REPORTING
     } else {
       // Only show telemetry notification when about:rights notification is not shown.
       this._showTelemetryNotification();
+#endif
     }
 
 
     // Show update notification, if needed.
     if (Services.prefs.prefHasUserValue("app.update.postupdate"))
       this._showUpdateNotification();
 
     // Load the "more info" page for a locked places.sqlite
@@ -735,16 +737,17 @@ BrowserGlue.prototype = {
       // be displayed per the idl.
       notifier.showAlertNotification("post-update-notification", title, text,
                                      true, url, clickCallback);
     }
     catch (e) {
     }
   },
 
+#ifdef MOZ_TELEMETRY_REPORTING
   _showTelemetryNotification: function BG__showTelemetryNotification() {
     const PREF_TELEMETRY_PROMPTED = "toolkit.telemetry.prompted";
     const PREF_TELEMETRY_ENABLED  = "toolkit.telemetry.enabled";
     const PREF_TELEMETRY_INFOURL  = "toolkit.telemetry.infoURL";
     const PREF_TELEMETRY_SERVER_OWNER = "toolkit.telemetry.server_owner";
 
     try {
       // If the user hasn't already been prompted, ask if they want to
@@ -800,16 +803,17 @@ BrowserGlue.prototype = {
       notification.parentNode.removeNotification(notification, true);
       // Add a new notification to that tab, with no "Learn more" link
       var notifyBox = browser.getNotificationBox();
       notifyBox.appendNotification(telemetryText, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
     }, false);
     let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
     description.appendChild(link);
   },
+#endif
 
   _showPluginUpdatePage: function BG__showPluginUpdatePage() {
     Services.prefs.setBoolPref(PREF_PLUGINS_NOTIFYUSER, false);
 
     var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].
                     getService(Ci.nsIURLFormatter);
     var updateUrl = formatter.formatURLPref(PREF_PLUGINS_UPDATEURL);
 
--- a/browser/components/places/tests/browser/browser_library_middleclick.js
+++ b/browser/components/places/tests/browser/browser_library_middleclick.js
@@ -79,23 +79,27 @@ var gTabsListener = {
     if (gCurrentTest.URIs.indexOf(spec) != -1 )
       this._loadedURIs.push(spec);
 
     if (this._loadedURIs.length == gCurrentTest.URIs.length) {
       // We have correctly opened all URIs.
 
       // Reset arrays.
       this._loadedURIs.length = 0;
-      // Close all tabs.
-      while (gBrowser.tabs.length > 1)
-        gBrowser.removeCurrentTab();
+
       this._openTabsCount = 0;
 
-      // Test finished.  This will move to the next one.
-      waitForFocus(gCurrentTest.finish, gBrowser.ownerDocument.defaultView);
+      executeSoon(function () {
+        // Close all tabs.
+        while (gBrowser.tabs.length > 1)
+          gBrowser.removeCurrentTab();
+
+        // Test finished.  This will move to the next one.
+        waitForFocus(gCurrentTest.finish, gBrowser.ownerDocument.defaultView);
+      });
     }
   }
 }
 
 //------------------------------------------------------------------------------
 // Open bookmark in a new tab.
 
 gTests.push({
--- a/browser/components/preferences/sync.js
+++ b/browser/components/preferences/sync.js
@@ -109,20 +109,20 @@ let gSyncPane = {
 
   startOver: function (showDialog) {
     if (showDialog) {
       let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
                   Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL + 
                   Services.prompt.BUTTON_POS_1_DEFAULT;
       let buttonChoice =
         Services.prompt.confirmEx(window,
-                                  this._stringBundle.GetStringFromName("stopUsingAccount.title"),
-                                  this._stringBundle.GetStringFromName("differentAccount.label"),
+                                  this._stringBundle.GetStringFromName("syncUnlink.title"),
+                                  this._stringBundle.GetStringFromName("syncUnlink.label"),
                                   flags,
-                                  this._stringBundle.GetStringFromName("differentAccountConfirm.label"),
+                                  this._stringBundle.GetStringFromName("syncUnlinkConfirm.label"),
                                   null, null, null, {});
 
       // If the user selects cancel, just bail
       if (buttonChoice == 1)
         return;
     }
 
     Weave.Service.startOver();
--- a/browser/components/preferences/sync.xul
+++ b/browser/components/preferences/sync.xul
@@ -96,22 +96,22 @@
             <hbox>
               <button type="menu"
                       label="&manageAccount.label;"
                       accesskey="&manageAccount.accesskey;">
                 <menupopup>
                   <menuitem label="&viewQuota.label;"
                             oncommand="gSyncPane.openQuotaDialog();"/>
                   <menuseparator/>
-                  <menuitem label="&changePassword.label;"
+                  <menuitem label="&changePassword2.label;"
                             oncommand="gSyncUtils.changePassword();"/>
                   <menuitem label="&mySyncKey.label;"
                             oncommand="gSyncUtils.resetPassphrase();"/>
                   <menuseparator/>
-                  <menuitem label="&resetSync.label;"
+                  <menuitem label="&resetSync2.label;"
                             oncommand="gSyncPane.resetSync();"/>
                 </menupopup>
               </button>
             </hbox>
 
             <hbox>
               <label id="syncAddDeviceLabel"
                      class="text-link"
@@ -167,17 +167,17 @@
                   <textbox id="syncComputerName"
                            onchange="gSyncUtils.changeName(this)"/>
                 </row>
               </rows>
             </grid>
             <hbox>
               <label class="text-link"
                      onclick="gSyncPane.startOver(true); return false;"
-                     value="&deactivateDevice.label;"/>
+                     value="&unlinkDevice.label;"/>
             </hbox>
           </groupbox>
           <hbox id="tosPP" pack="center">
             <label class="text-link"
                    onclick="event.stopPropagation();gSyncUtils.openToS();"
                    value="&prefs.tosLink.label;"/>
             <label class="text-link"
                    onclick="event.stopPropagation();gSyncUtils.openPrivacyPolicy();"
@@ -192,13 +192,13 @@
                    onclick="gSyncPane.updatePass(); return false;"
                    value="&updatePass.label;"/>
             <label class="text-link"
                    onclick="gSyncPane.resetPass(); return false;"
                    value="&resetPass.label;"/>
           </hbox>
           <label class="text-link"
                  onclick="gSyncPane.startOver(true); return false;"
-                 value="&deactivateDevice.label;"/>
+                 value="&unlinkDevice.label;"/>
         </vbox>
       </deck>
   </prefpane>
 </overlay>
--- a/browser/components/preferences/tests/browser_permissions.js
+++ b/browser/components/preferences/tests/browser_permissions.js
@@ -290,17 +290,17 @@ function getSiteItem(aHost) {
 
 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.nsIDOMWindowInternal);
+                                .getInterface(Ci.nsIDOMWindow);
       waitForFocus(function() {
         is(domwindow.document.location.href, aURL, "should have seen the right window open");
         domwindow.close();
         aCallback();
       }, domwindow);
     },
     onCloseWindow: function(aXULWindow) { },
     onWindowTitleChange: function(aXULWindow, aNewTitle) { }
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -284,16 +284,17 @@ var treeView = {
   getCellText: function(idx, column) { return gTreeData[idx].label; },
   isContainer: function(idx)         { return "open" in gTreeData[idx]; },
   getCellValue: function(idx, column){ return gTreeData[idx].checked; },
   isContainerOpen: function(idx)     { return gTreeData[idx].open; },
   isContainerEmpty: function(idx)    { return false; },
   isSeparator: function(idx)         { return false; },
   isSorted: function()               { return false; },
   isEditable: function(idx, column)  { return false; },
+  canDrop: function(idx, orientation, dt) { return false; },
   getLevel: function(idx)            { return this.isContainer(idx) ? 0 : 1; },
 
   getParentIndex: function(idx) {
     if (!this.isContainer(idx))
       for (var t = idx - 1; t >= 0 ; t--)
         if (this.isContainer(t))
           return t;
     return -1;
--- a/browser/components/sessionstore/nsISessionStartup.idl
+++ b/browser/components/sessionstore/nsISessionStartup.idl
@@ -38,21 +38,21 @@
 #include "nsISupports.idl"
 
 /**
  * nsISessionStore keeps track of the current browsing state - i.e.
  * tab history, cookies, scroll state, form data, POSTDATA and window features
  * - and allows to restore everything into one window.
  */
 
-[scriptable, uuid(e7bb7828-0e32-4995-a848-4aa35df603c7)]
+[scriptable, uuid(170c6857-7f71-46ce-bc9b-185723b1c3a8)]
 interface nsISessionStartup: nsISupports
 {
-  // Get session state as string
-  readonly attribute AString state;
+  // Get session state
+  readonly attribute jsval state;
 
   /**
    * Determine if session should be restored 
    */
   boolean doRestore();
 
   /**
    * What type of session we're restoring.
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -84,17 +84,17 @@ function debug(aMsg) {
 /* :::::::: The Service ::::::::::::::: */
 
 function SessionStartup() {
 }
 
 SessionStartup.prototype = {
 
   // the state to restore at startup
-  _iniString: null,
+  _initialState: null,
   _sessionType: Ci.nsISessionStartup.NO_SESSION,
 
 /* ........ Global Event Handlers .............. */
 
   /**
    * Initialize the component
    */
   init: function sss_init() {
@@ -116,64 +116,63 @@ SessionStartup.prototype = {
     let doResumeSession = prefBranch.getBoolPref("sessionstore.resume_session_once") ||
                           prefBranch.getIntPref("startup.page") == 3;
 
     // only continue if the session file exists
     if (!sessionFile.exists())
       return;
 
     // get string containing session state
-    this._iniString = this._readStateFile(sessionFile);
-    if (!this._iniString)
+    let iniString = this._readStateFile(sessionFile);
+    if (!iniString)
       return;
 
     // parse the session state into a JS object
-    let initialState;
     try {
       // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
-      if (this._iniString.charAt(0) == '(')
-        this._iniString = this._iniString.slice(1, -1);
+      if (iniString.charAt(0) == '(')
+        iniString = iniString.slice(1, -1);
       try {
-        initialState = JSON.parse(this._iniString);
+        this._initialState = JSON.parse(iniString);
       }
       catch (exJSON) {
         var s = new Cu.Sandbox("about:blank");
-        initialState = Cu.evalInSandbox("(" + this._iniString + ")", s);
-        this._iniString = JSON.stringify(initialState);
+        this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
       }
     }
     catch (ex) { debug("The session file is invalid: " + ex); }
 
     let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
     let lastSessionCrashed =
-      initialState && initialState.session && initialState.session.state &&
-      initialState.session.state == STATE_RUNNING_STR;
+      this._initialState && this._initialState.session &&
+      this._initialState.session.state &&
+      this._initialState.session.state == STATE_RUNNING_STR;
 
     // Report shutdown success via telemetry. Shortcoming here are
     // being-killed-by-OS-shutdown-logic, shutdown freezing after
     // session restore was written, etc.
     let Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
     Telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
 
     // set the startup type
     if (lastSessionCrashed && resumeFromCrash)
       this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
     else if (!lastSessionCrashed && doResumeSession)
       this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
-    else if (initialState)
+    else if (this._initialState)
       this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
     else
-      this._iniString = null; // reset the state string
+      this._initialState = null; // reset the state
 
     // wait for the first browser window to open
     // Don't reset the initial window's default args (i.e. the home page(s))
     // if all stored tabs are pinned.
     if (this.doRestore() &&
-        (!initialState.windows ||
-        !initialState.windows.every(function (win)
+        (!this._initialState.windows ||
+        !this._initialState.windows.every(function (win)
            win.tabs.every(function (tab) tab.pinned))))
       Services.obs.addObserver(this, "domwindowopened", true);
 
     Services.obs.addObserver(this, "sessionstore-windows-restored", true);
   },
 
   /**
    * Handle notifications
@@ -199,18 +198,18 @@ SessionStartup.prototype = {
       var self = this;
       window.addEventListener("load", function() {
         self._onWindowOpened(window);
         window.removeEventListener("load", arguments.callee, false);
       }, false);
       break;
     case "sessionstore-windows-restored":
       Services.obs.removeObserver(this, "sessionstore-windows-restored");
-      // free _iniString after nsSessionStore is done with it
-      this._iniString = null;
+      // free _initialState after nsSessionStore is done with it
+      this._initialState = null;
       this._sessionType = Ci.nsISessionStartup.NO_SESSION;
       break;
     }
   },
 
   /**
    * Removes the default arguments from the first browser window
    * (and removes the "domwindowopened" observer afterwards).
@@ -249,17 +248,17 @@ SessionStartup.prototype = {
   },
 
 /* ........ Public API ................*/
 
   /**
    * Get the session state as a string
    */
   get state() {
-    return this._iniString;
+    return this._initialState;
   },
 
   /**
    * Determine whether there is a pending session restore.
    * @returns bool
    */
   doRestore: function sss_doRestore() {
     return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -299,55 +299,53 @@ SessionStoreService.prototype = {
 
     // get file references
     this._sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
     this._sessionFileBackup = this._sessionFile.clone();
     this._sessionFile.append("sessionstore.js");
     this._sessionFileBackup.append("sessionstore.bak");
 
     // get string containing session state
-    var iniString;
     var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
              getService(Ci.nsISessionStartup);
     try {
       if (ss.doRestore() ||
           ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION)
-        iniString = ss.state;
+        this._initialState = ss.state;
     }
     catch(ex) { dump(ex + "\n"); } // no state to restore, which is ok
 
-    if (iniString) {
+    if (this._initialState) {
       try {
         // If we're doing a DEFERRED session, then we want to pull pinned tabs
         // out so they can be restored.
         if (ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
-          let [iniState, remainingState] = this._prepDataForDeferredRestore(iniString);
+          let [iniState, remainingState] = this._prepDataForDeferredRestore(this._initialState);
           // If we have a iniState with windows, that means that we have windows
           // with app tabs to restore.
           if (iniState.windows.length)
             this._initialState = iniState;
+          else
+            this._initialState = null;
           if (remainingState.windows.length)
             this._lastSessionState = remainingState;
         }
         else {
-          // parse the session state into JS objects
-          this._initialState = JSON.parse(iniString);
-
           let lastSessionCrashed =
             this._initialState.session && this._initialState.session.state &&
             this._initialState.session.state == STATE_RUNNING_STR;
           if (lastSessionCrashed) {
             this._recentCrashes = (this._initialState.session &&
                                    this._initialState.session.recentCrashes || 0) + 1;
             
             if (this._needsRestorePage(this._initialState, this._recentCrashes)) {
               // replace the crashed session with a restore-page-only session
               let pageData = {
                 url: "about:sessionrestore",
-                formdata: { "#sessionData": iniString }
+                formdata: { "#sessionData": JSON.stringify(this._initialState) }
               };
               this._initialState = { windows: [{ tabs: [{ entries: [pageData] }] }] };
             }
           }
 
           // Load the session start time from the previous state
           this._sessionStartTime = this._initialState.session &&
                                    this._initialState.session.startTime ||
@@ -806,17 +804,17 @@ SessionStoreService.prototype = {
         if (!this._doResumeSession()) {
 #endif
           // We want to split the window up into pinned tabs and unpinned tabs.
           // Pinned tabs should be restored. If there are any remaining tabs,
           // they should be added back to _closedWindows.
           // We'll cheat a little bit and reuse _prepDataForDeferredRestore
           // even though it wasn't built exactly for this.
           let [appTabsState, normalTabsState] =
-            this._prepDataForDeferredRestore(JSON.stringify({ windows: [closedWindowState] }));
+            this._prepDataForDeferredRestore({ windows: [closedWindowState] });
 
           // These are our pinned tabs, which we should restore
           if (appTabsState.windows.length) {
             newWindowState = appTabsState.windows[0];
             delete newWindowState.__lastSessionWindowID;
           }
 
           // In case there were no unpinned tabs, remove the window from _closedWindows
@@ -2217,18 +2215,24 @@ SessionStoreService.prototype = {
     var jscookies = {};
     var _this = this;
     // MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
     var MAX_EXPIRY = Math.pow(2, 62);
     aWindows.forEach(function(aWindow) {
       if (!aWindow._hosts)
         return;
       for (var [host, isPinned] in Iterator(aWindow._hosts)) {
-        var list = CookieSvc.getCookiesFromHost(host);
-        while (list.hasMoreElements()) {
+        let list;
+        try {
+          list = CookieSvc.getCookiesFromHost(host);
+        }
+        catch (ex) {
+          debug("getCookiesFromHost failed. Host: " + host);
+        }
+        while (list && list.hasMoreElements()) {
           var cookie = list.getNext().QueryInterface(Ci.nsICookie2);
           // aWindow._hosts will only have hosts with the right privacy rules,
           // so there is no need to do anything special with this call to
           // _checkPrivacyLevel.
           if (cookie.isSession && _this._checkPrivacyLevel(cookie.isSecure, isPinned)) {
             // use the cookie's host, path, and name as keys into a hash,
             // to make sure we serialize each cookie only once
             if (!(cookie.host in jscookies &&
@@ -2947,18 +2951,21 @@ SessionStoreService.prototype = {
     if (tabData.userTypedValue) {
       browser.userTypedValue = tabData.userTypedValue;
       if (tabData.userTypedClear) {
         // Make it so that we'll enter restoreDocument on page load. We will
         // fire SSTabRestored from there. We don't have any form data to restore
         // so we can just set the URL to null.
         browser.__SS_restore_data = { url: null };
         browser.__SS_restore_tab = aTab;
+        if (didStartLoad)
+          browser.stop();
         didStartLoad = true;
-        browser.loadURI(tabData.userTypedValue, null, null, true);
+        browser.loadURIWithFlags(tabData.userTypedValue,
+                                 Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP);
       }
     }
 
     // If we didn't start a load, then we won't reset this tab through the usual
     // channel (via the progress listener), so reset the tab ourselves. We will
     // also send SSTabRestored since this tab has technically been restored.
     if (!didStartLoad) {
       this._sendTabRestoredNotification(aTab);
@@ -3780,22 +3787,21 @@ SessionStoreService.prototype = {
    * defaultState will be comprised of windows with only pinned tabs, extracted
    * from state. It will contain the cookies that go along with the history
    * entries in those tabs. It will also contain window position information.
    *
    * defaultState will be restored at startup. state will be placed into
    * this._lastSessionState and will be kept in case the user explicitly wants
    * to restore the previous session (publicly exposed as restoreLastSession).
    *
-   * @param stateString
-   *        The state string, presumably from nsISessionStartup.state
+   * @param state
+   *        The state, presumably from nsISessionStartup.state
    * @returns [defaultState, state]
    */
-  _prepDataForDeferredRestore: function sss__prepDataForDeferredRestore(stateString) {
-    let state = JSON.parse(stateString);
+  _prepDataForDeferredRestore: function sss__prepDataForDeferredRestore(state) {
     let defaultState = { windows: [], selectedWindow: 1 };
 
     state.selectedWindow = state.selectedWindow || 1;
 
     // Look at each window, remove pinned tabs, adjust selectedindex,
     // remove window if necessary.
     for (let wIndex = 0; wIndex < state.windows.length;) {
       let window = state.windows[wIndex];
--- a/browser/components/wintaskbar/test/browser_taskbar_preview.js
+++ b/browser/components/wintaskbar/test/browser_taskbar_preview.js
@@ -124,16 +124,16 @@ function test() {
       thumbnailWidth = thumbnailHeight * ratio;
     else
       thumbnailHeight = thumbnailWidth / ratio;
 
     return getCanvas(thumbnailWidth, thumbnailHeight);
   }
 
   function getCanvas(width, height) {
-    let win = window.QueryInterface(Ci.nsIDOMWindowInternal);
+    let win = window.QueryInterface(Ci.nsIDOMWindow);
     let doc = win.document;
     let canvas = doc.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     canvas.width = width;
     canvas.height = height;
     return canvas;
   }
 }
--- a/browser/fuel/src/fuelApplication.js
+++ b/browser/fuel/src/fuelApplication.js
@@ -217,17 +217,17 @@ BrowserTab.prototype = {
   /*
    * Helper event callback used to redirect events made on the XBL element
    */
   _event : function bt_event(aEvent) {
     if (aEvent.type == "load") {
       if (!(aEvent.originalTarget instanceof Ci.nsIDOMDocument))
         return;
 
-      if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindowInternal &&
+      if (aEvent.originalTarget.defaultView instanceof Ci.nsIDOMWindow &&
           aEvent.originalTarget.defaultView.frameElement)
         return;
     }
     this._events.dispatch(aEvent.type, this);
   },
   /*
    * Helper used to determine the index offset of the browsertab
    */
--- a/browser/fuel/test/browser_Application.js
+++ b/browser/fuel/test/browser_Application.js
@@ -29,17 +29,17 @@ WindowOpenListener.prototype = {
   },
 
   onOpenWindow: function(window) {
     if (this.window)
       return;
 
     this.window = window;
     this.domwindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                           .getInterface(Ci.nsIDOMWindowInternal);
+                           .getInterface(Ci.nsIDOMWindow);
     this.domwindow.addEventListener("load", this, false);
   },
 
   onCloseWindow: function(window) {
     if (this.window != window)
       return;
 
     Services.wm.removeListener(this);
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -106,11 +106,11 @@ offlinepermissionstitle=Offline Data
 
 ####Preferences::Advanced::Network
 #LOCALIZATION NOTE: The next string is for the disk usage of the http cache.
 #   e.g., "Your cache is currently using 200 MB"
 #   %1$S = size
 #   %2$S = unit (MB, KB, etc.)
 actualCacheSize=Your cache is currently using %1$S %2$S of disk space
 
-stopUsingAccount.title=Do you want to stop using this account?
-differentAccount.label=This will reset all of your Sync account information and preferences.
-differentAccountConfirm.label=Reset All Information
+syncUnlink.title=Do you want to unlink your device?
+syncUnlink.label=This device will no longer be associated with your Sync account. All of your personal data, both on this device and in your Sync account, will remain intact.
+syncUnlinkConfirm.label=Unlink
--- a/browser/locales/en-US/chrome/browser/preferences/sync.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/sync.dtd
@@ -8,19 +8,20 @@
 <!-- Login error feedback -->
 <!ENTITY updatePass.label             "Update">
 <!ENTITY resetPass.label              "Reset">
 
 <!-- Manage Account -->
 <!ENTITY manageAccount.label          "Manage Account">
 <!ENTITY manageAccount.accesskey      "A">
 <!ENTITY viewQuota.label              "View Quota">
-<!ENTITY changePassword.label         "Change Password">
+<!ENTITY changePassword2.label         "Change Password…">
 <!ENTITY mySyncKey.label              "My Sync Key">
-<!ENTITY resetSync.label              "Reset Sync">
+<!ENTITY resetSync2.label              "Reset Sync…">
+
 <!ENTITY addDevice.label              "Add a Device">
 
 <!ENTITY syncMy.label               "Sync My">
 <!ENTITY engine.bookmarks.label     "Bookmarks">
 <!ENTITY engine.bookmarks.accesskey "m">
 <!ENTITY engine.tabs.label          "Tabs">
 <!ENTITY engine.tabs.accesskey      "T">
 <!ENTITY engine.history.label       "History">
@@ -28,13 +29,13 @@
 <!ENTITY engine.passwords.label     "Passwords">
 <!ENTITY engine.passwords.accesskey "P">
 <!ENTITY engine.prefs.label         "Preferences">
 <!ENTITY engine.prefs.accesskey     "S">
 
 <!-- Device Settings -->
 <!ENTITY syncComputerName.label       "Computer Name:">
 <!ENTITY syncComputerName.accesskey   "c">
-<!ENTITY deactivateDevice.label       "Deactivate This Device">
+<!ENTITY unlinkDevice.label           "Unlink This Device">
 
 <!-- Footer stuff -->
 <!ENTITY prefs.tosLink.label        "Terms of Service">
 <!ENTITY prefs.ppLink.label         "Privacy Policy">
--- a/browser/locales/en-US/chrome/browser/tabview.properties
+++ b/browser/locales/en-US/chrome/browser/tabview.properties
@@ -1,4 +1,5 @@
 tabview.groupItem.newTabButton=New tab
 tabview.groupItem.defaultName=Name this tab group…
 tabview.groupItem.undoCloseGroup=Undo Close Group
 tabview.search.otherWindowTabs=Tabs from other windows
+tabview.notification.sessionStore=Tabs and groups will automatically be restored the next time you start %S.
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -93,16 +93,15 @@ if [ "$ENABLE_TESTS" ]; then
     browser/components/sessionstore/test/Makefile
     browser/components/sessionstore/test/browser/Makefile
     browser/components/shell/test/Makefile
     browser/components/feeds/test/Makefile
     browser/components/feeds/test/chrome/Makefile
     browser/components/places/tests/Makefile
     browser/components/places/tests/chrome/Makefile
     browser/components/places/tests/browser/Makefile
-    browser/components/places/tests/perf/Makefile
     browser/components/privatebrowsing/test/Makefile
     browser/components/privatebrowsing/test/browser/Makefile
     browser/components/safebrowsing/content/test/Makefile
     browser/components/wintaskbar/test/Makefile
     browser/fuel/test/Makefile
   "
 fi
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -1,87 +1,134 @@
 import subprocess
 from devicemanager import DeviceManager, DMError
 import re
+import os
 
 class DeviceManagerADB(DeviceManager):
 
-  def __init__(self, host = None, port = 20701, retrylimit = 5):
+  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
-    self.getDeviceRoot()
+    self.Init(packageName)
+
+  def Init(self, packageName):
+    # Initialization code that may fail: Catch exceptions here to allow
+    # successful initialization even if, for example, adb is not installed.
+    try:
+      root = self.getDeviceRoot()
+      self.verifyPackage(packageName)
+      self.tmpDir = root + "/tmp"
+      if (not self.dirExists(self.tmpDir)):
+        self.mkDir(self.tmpDir)
+    except:
+      self.packageName = None
+      self.tmpDir = None
     try:
       # a test to see if we have root privs
       self.checkCmd(["shell", "ls", "/sbin"])
     except:
       try:
         self.checkCmd(["root"])
       except:
         print "restarting as root failed"
 
   # external function
   # returns:
   #  success: True
   #  failure: False
   def pushFile(self, localname, destname):
     try:
-      self.checkCmd(["push", localname, destname])
+      if (os.name == "nt"):
+        destname = destname.replace('\\', '/')
+      if (self.packageName):
+        remoteTmpFile = self.tmpDir + "/" + os.path.basename(localname)
+        self.checkCmd(["push", os.path.realpath(localname), remoteTmpFile])
+        self.checkCmdAs(["shell", "cp", remoteTmpFile, destname])
+        self.checkCmd(["shell", "rm", remoteTmpFile])
+      else:
+        self.checkCmd(["push", os.path.realpath(localname), destname])
+      if (self.isDir(destname)):
+        destname = destname + "/" + os.path.basename(localname)
       self.chmodDir(destname)
       return True
     except:
       return False
 
   # external function
   # returns:
   #  success: directory name
   #  failure: None
   def mkDir(self, name):
     try:
-      self.checkCmd(["shell", "mkdir", name])
+      self.checkCmdAs(["shell", "mkdir", name])
       self.chmodDir(name)
       return name
     except:
       return None
 
   # make directory structure on the device
   # external function
   # returns:
   #  success: directory structure that we created
   #  failure: None
   def mkDirs(self, filename):
-    self.checkCmd(["shell", "mkdir", "-p ", name])
-    return filename
+    parts = filename.split('/')
+    name = ""
+    for part in parts:
+      if (part == parts[-1]): break
+      if (part != ""):
+        name += '/' + part
+        if (not self.dirExists(name)):
+          if (self.mkDir(name) == None):
+            print "failed making directory: " + str(name)
+            return None
+    return name
 
   # push localDir from host to remoteDir on the device
   # external function
   # returns:
   #  success: remoteDir
   #  failure: None
   def pushDir(self, localDir, remoteDir):
+    # adb "push" accepts a directory as an argument, but if the directory
+    # contains symbolic links, the links are pushed, rather than the linked
+    # files; we push file-by-file to get around this limitation
     try:
-      self.checkCmd(["push", localDir, remoteDir])
-      self.chmodDir(remoteDir)
+      for root, dirs, files in os.walk(localDir):
+        relRoot = os.path.relpath(root, localDir)
+        for file in files:
+          localFile = os.path.join(root, file)
+          remoteFile = remoteDir + "/"
+          if (relRoot!="."):
+            remoteFile = remoteFile + relRoot + "/"
+          remoteFile = remoteFile + file
+          self.pushFile(localFile, remoteFile)
+        for dir in dirs:
+          targetDir = remoteDir + "/"
+          if (relRoot!="."):
+            targetDir = targetDir + relRoot + "/"
+          targetDir = targetDir + dir
+          if (not self.dirExists(targetDir)):
+            self.mkDir(targetDir)
+      self.checkCmdAs(["shell", "chmod", "777", remoteDir])
       return True
     except:
       print "pushing " + localDir + " to " + remoteDir + " failed"
       return False
 
   # external function
   # returns:
   #  success: True
   #  failure: False
   def dirExists(self, dirname):
-    try:
-      self.checkCmd(["shell", "ls", dirname])
-      return True
-    except:
-      return False
+    return self.isDir(dirname)
 
   # Because we always have / style paths we make this a lot easier with some
   # assumptions
   # external function
   # returns:
   #  success: True
   #  failure: False
   def fileExists(self, filepath):
@@ -107,38 +154,38 @@ class DeviceManagerADB(DeviceManager):
   def removeDir(self, remoteDir):
       out = ""
       if (self.isDir(remoteDir)):
           files = self.listFiles(remoteDir.strip())
           for f in files:
               if (self.isDir(remoteDir.strip() + "/" + f.strip())):
                   out += self.removeDir(remoteDir.strip() + "/" + f.strip())
               else:
-                  out += self.removeFile(remoteDir.strip())
-          out += self.removeSingleDir(remoteDir)
+                  out += self.removeFile(remoteDir.strip() + "/" + f.strip())
+          out += self.removeSingleDir(remoteDir.strip())
       else:
           out += self.removeFile(remoteDir.strip())
       return out
 
   def isDir(self, remotePath):
-      p = self.runCmd(["shell", "ls", remotePath])
+      p = self.runCmd(["shell", "ls", "-a", remotePath])
       data = p.stdout.readlines()
       if (len(data) == 0):
           return True
       if (len(data) == 1):
-          if (data[0] == remotePath):
+          if (data[0].rstrip() == remotePath):
               return False
           if (data[0].find("No such file or directory") != -1):
               return False
           if (data[0].find("Not a directory") != -1):
               return False
       return True
 
   def listFiles(self, rootdir):
-      p = self.runCmd(["shell", "ls", rootdir])
+      p = self.runCmd(["shell", "ls", "-a", rootdir])
       data = p.stdout.readlines()
       if (len(data) == 1):
           if (data[0] == rootdir):
               return []
           if (data[0].find("No such file or directory") != -1):
               return []
           if (data[0].find("Not a directory") != -1):
               return []
@@ -160,25 +207,29 @@ class DeviceManagerADB(DeviceManager):
       proc =  p.stdout.readline()
     return ret
 
   # external function
   # returns:
   #  success: pid
   #  failure: None
   def fireProcess(self, appname, failIfRunning=False):
-    return self.runCmd(["shell", appname]).pid
+    #strip out env vars
+    parts = appname.split('"');
+    if (len(parts) > 2):
+      parts = parts[2:]
+    return self.launchProcess(parts, failIfRunning)
 
   # external function
   # returns:
   #  success: output filename
   #  failure: None
   def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
     acmd = ["shell", "am","start"]
-    cmd = ' '.join(cmd)
+    cmd = ' '.join(cmd).strip()
     i = cmd.find(" ")
     acmd.append("-n")
     acmd.append(cmd[0:i] + "/.App")
     acmd.append("--es")
     acmd.append("args")
     acmd.append(cmd[i:])
     print acmd
     self.checkCmd(acmd)
@@ -294,19 +345,28 @@ class DeviceManagerADB(DeviceManager):
   #       /reftest
   #       /mochitest
   #
   # external function
   # returns:
   #  success: path for device root
   #  failure: None
   def getDeviceRoot(self):
-    if (not self.dirExists("/data/local/tests")):
-      self.mkDir("/data/local/tests")
-    return "/data/local/tests"
+    # /mnt/sdcard/tests is preferred to /data/local/tests, but this can be
+    # over-ridden by creating /data/local/tests
+    testRoot = "/data/local/tests"
+    if (self.dirExists(testRoot)):
+      return testRoot
+    root = "/mnt/sdcard"
+    if (not self.dirExists(root)):
+      root = "/data/local"
+    testRoot = root + "/tests"
+    if (not self.dirExists(testRoot)):
+      self.mkDir(testRoot)
+    return testRoot
 
   # Either we will have /tests/fennec or /tests/firefox but we will never have
   # both.  Return the one that exists
   # TODO: ensure we can support org.mozilla.firefox
   # external function
   # returns:
   #  success: path for app root
   #  failure: None
@@ -314,20 +374,26 @@ class DeviceManagerADB(DeviceManager):
     devroot = self.getDeviceRoot()
     if (devroot == None):
       return None
 
     if (self.dirExists(devroot + '/fennec')):
       return devroot + '/fennec'
     elif (self.dirExists(devroot + '/firefox')):
       return devroot + '/firefox'
-    elif (self.dirExsts('/data/data/org.mozilla.fennec')):
-      return 'org.mozilla.fennec'
+    elif (self.dirExists('/data/data/org.mozilla.fennec')):
+      return '/data/data/org.mozilla.fennec'
     elif (self.dirExists('/data/data/org.mozilla.firefox')):
-      return 'org.mozilla.firefox'
+      return '/data/data/org.mozilla.firefox'
+    elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
+      return '/data/data/org.mozilla.fennec_unofficial'
+    elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
+      return '/data/data/org.mozilla.fennec_aurora'
+    elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
+      return '/data/data/org.mozilla.firefox_beta'
 
     # Failure (either not installed or not a recognized platform)
     return None
 
   # Gets the directory location on the device for a specific test type
   # Type is one of: xpcshell|reftest|mochitest
   # external function
   # returns:
@@ -418,23 +484,39 @@ class DeviceManagerADB(DeviceManager):
   def runCmd(self, args):
     args.insert(0, "adb")
     return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
   def checkCmd(self, args):
     args.insert(0, "adb")
     return subprocess.check_call(args)
 
+  def checkCmdAs(self, args):
+    if (self.packageName):
+      args.insert(1, "run-as")
+      args.insert(2, self.packageName)
+    return self.checkCmd(args)
+
   def chmodDir(self, remoteDir):
-    print "called chmodDir"
     if (self.isDir(remoteDir)):
       files = self.listFiles(remoteDir.strip())
       for f in files:
         if (self.isDir(remoteDir.strip() + "/" + f.strip())):
           self.chmodDir(remoteDir.strip() + "/" + f.strip())
         else:
-          self.checkCmd(["shell", "chmod", "777", remoteDir.strip()])
+          self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
           print "chmod " + remoteDir.strip()
-      self.checkCmd(["shell", "chmod", "777", remoteDir])
+      self.checkCmdAs(["shell", "chmod", "777", remoteDir])
       print "chmod " + remoteDir
     else:
-      self.checkCmd(["shell", "chmod", "777", remoteDir.strip()])
-      print "chmod " + remoteDir
+      self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()])
+      print "chmod " + remoteDir.strip()
+
+  def verifyPackage(self, packageName):
+    # If a valid package name is specified, it will be used for certain
+    # file operations, so that pushed files and directories are created
+    # by the uid associated with the package.
+    self.packageName = None
+    if (packageName):
+      data = self.runCmd(["shell", "run-as", packageName, "pwd"]).stdout.read()
+      if (not re.search('is unknown', data)):
+        self.packageName = packageName
+        print "package set: " + self.packageName
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -411,16 +411,19 @@ int do_relocation_section(Elf *elf, unsi
     Elf_SymValue *sym = symtab->lookup("__cxa_pure_virtual");
 
     std::vector<Rel_Type> new_rels;
     Elf_RelHack relhack_entry;
     relhack_entry.r_offset = relhack_entry.r_info = 0;
     int entry_sz = (elf->getClass() == ELFCLASS32) ? 4 : 8;
     for (typename std::vector<Rel_Type>::iterator i = section->rels.begin();
          i != section->rels.end(); i++) {
+        // We don't need to keep R_*_NONE relocations
+        if (!ELF32_R_TYPE(i->r_info))
+            continue;
         ElfSection *section = elf->getSectionAt(i->r_offset);
         // __cxa_pure_virtual is a function used in vtables to point at pure
         // virtual methods. The __cxa_pure_virtual function usually abort()s.
         // These functions are however normally never called. In the case
         // where they would, jumping to the NULL address instead of calling
         // __cxa_pure_virtual is going to work just as well. So we can remove
         // relocations for the __cxa_pure_virtual symbol and NULL out the
         // content at the offset pointed by the relocation.
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2707,17 +2707,17 @@ nsScriptSecurityManager::CheckConfirmDia
 
     //-- Get a prompter for the current window.
     nsCOMPtr<nsIPrompt> prompter;
     if (cx)
     {
         nsIScriptContext *scriptContext = GetScriptContext(cx);
         if (scriptContext)
         {
-            nsCOMPtr<nsIDOMWindowInternal> domWin =
+            nsCOMPtr<nsIDOMWindow> domWin =
                 do_QueryInterface(scriptContext->GetGlobalObject());
             if (domWin)
                 domWin->GetPrompter(getter_AddRefs(prompter));
         }
     }
 
     if (!prompter)
     {
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -59,17 +59,17 @@
 #include "nsCSSStyleSheet.h"
 #include "nsIConsoleService.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMLocation.h"
 #include "nsIDOMWindowCollection.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIIOService.h"
 #include "nsIJARProtocolHandler.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIProtocolHandler.h"
 #include "nsIScriptError.h"
 #include "nsIWindowMediator.h"
 
@@ -346,17 +346,17 @@ nsChromeRegistry::ConvertChromeURL(nsIUR
   return NS_NewURI(aResult, path, nsnull, baseURI);
 }
 
 ////////////////////////////////////////////////////////////////////////
 
 // theme stuff
 
 
-static void FlushSkinBindingsForWindow(nsIDOMWindowInternal* aWindow)
+static void FlushSkinBindingsForWindow(nsIDOMWindow* aWindow)
 {
   // Get the DOM document.
   nsCOMPtr<nsIDOMDocument> domDocument;
   aWindow->GetDocument(getter_AddRefs(domDocument));
   if (!domDocument)
     return;
 
   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
@@ -378,32 +378,32 @@ NS_IMETHODIMP nsChromeRegistry::RefreshS
   nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
   windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
   PRBool more;
   windowEnumerator->HasMoreElements(&more);
   while (more) {
     nsCOMPtr<nsISupports> protoWindow;
     windowEnumerator->GetNext(getter_AddRefs(protoWindow));
     if (protoWindow) {
-      nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(protoWindow);
+      nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(protoWindow);
       if (domWindow)
         FlushSkinBindingsForWindow(domWindow);
     }
     windowEnumerator->HasMoreElements(&more);
   }
 
   FlushSkinCaches();
 
   windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
   windowEnumerator->HasMoreElements(&more);
   while (more) {
     nsCOMPtr<nsISupports> protoWindow;
     windowEnumerator->GetNext(getter_AddRefs(protoWindow));
     if (protoWindow) {
-      nsCOMPtr<nsIDOMWindowInternal> domWindow = do_QueryInterface(protoWindow);
+      nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(protoWindow);
       if (domWindow)
         RefreshWindow(domWindow);
     }
     windowEnumerator->HasMoreElements(&more);
   }
    
   return NS_OK;
 }
@@ -423,29 +423,28 @@ static PRBool IsChromeURI(nsIURI* aURI)
 {
     PRBool isChrome=PR_FALSE;
     if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome)
         return PR_TRUE;
     return PR_FALSE;
 }
 
 // XXXbsmedberg: move this to windowmediator
-nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindowInternal* aWindow)
+nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
 {
   // Deal with our subframes first.
   nsCOMPtr<nsIDOMWindowCollection> frames;
   aWindow->GetFrames(getter_AddRefs(frames));
   PRUint32 length;
   frames->GetLength(&length);
   PRUint32 j;
   for (j = 0; j < length; j++) {
     nsCOMPtr<nsIDOMWindow> childWin;
     frames->Item(j, getter_AddRefs(childWin));
-    nsCOMPtr<nsIDOMWindowInternal> childInt(do_QueryInterface(childWin));
-    RefreshWindow(childInt);
+    RefreshWindow(childWin);
   }
 
   nsresult rv;
   // Get the DOM document.
   nsCOMPtr<nsIDOMDocument> domDocument;
   aWindow->GetDocument(getter_AddRefs(domDocument));
   if (!domDocument)
     return NS_OK;
@@ -563,18 +562,17 @@ nsChromeRegistry::ReloadChrome()
       // Get each dom window
       PRBool more;
       rv = windowEnumerator->HasMoreElements(&more);
       if (NS_FAILED(rv)) return rv;
       while (more) {
         nsCOMPtr<nsISupports> protoWindow;
         rv = windowEnumerator->GetNext(getter_AddRefs(protoWindow));
         if (NS_SUCCEEDED(rv)) {
-          nsCOMPtr<nsIDOMWindowInternal> domWindow =
-            do_QueryInterface(protoWindow);
+          nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(protoWindow);
           if (domWindow) {
             nsCOMPtr<nsIDOMLocation> location;
             domWindow->GetLocation(getter_AddRefs(location));
             if (location) {
               rv = location->Reload(PR_FALSE);
               if (NS_FAILED(rv)) return rv;
             }
           }
--- a/chrome/src/nsChromeRegistry.h
+++ b/chrome/src/nsChromeRegistry.h
@@ -58,17 +58,17 @@
 #include "nsURIHashKey.h"
 #include "nsInterfaceHashtable.h"
 #include "nsXULAppAPI.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIXPConnect.h"
 
 #include "mozilla/Omnijar.h"
 
-class nsIDOMWindowInternal;
+class nsIDOMWindow;
 class nsIURL;
 
 // The chrome registry is actually split between nsChromeRegistryChrome and
 // nsChromeRegistryContent. The work/data that is common to both resides in
 // the shared nsChromeRegistry implementation, with operations that only make
 // sense for one side erroring out in the other.
 
 // for component registration
@@ -125,17 +125,17 @@ protected:
   virtual nsIURI* GetBaseURIFromPackage(const nsCString& aPackage,
                                         const nsCString& aProvider,
                                         const nsCString& aPath) = 0;
   virtual nsresult GetFlagsFromPackage(const nsCString& aPackage,
                                        PRUint32* aFlags) = 0;
 
   nsresult SelectLocaleFromPref(nsIPrefBranch* prefs);
 
-  static nsresult RefreshWindow(nsIDOMWindowInternal* aWindow);
+  static nsresult RefreshWindow(nsIDOMWindow* aWindow);
   static nsresult GetProviderAndPath(nsIURL* aChromeURL,
                                      nsACString& aProvider, nsACString& aPath);
 
 public:
   static already_AddRefed<nsChromeRegistry> GetSingleton();
 
   struct ManifestProcessingContext
   {
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -107,16 +107,17 @@ MOZ_JSDEBUGGER  = @MOZ_JSDEBUGGER@
 MOZ_IPDL_TESTS 	= @MOZ_IPDL_TESTS@
 MOZ_LEAKY	= @MOZ_LEAKY@
 MOZ_MEMORY      = @MOZ_MEMORY@
 MOZ_PROFILING   = @MOZ_PROFILING@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
+MOZ_ETW         = @MOZ_ETW@
 MOZ_TRACE_JSCALLS = @MOZ_TRACE_JSCALLS@
 MOZ_TRACEVIS    = @MOZ_TRACEVIS@
 DEHYDRA_PATH    = @DEHYDRA_PATH@
 
 NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
 USE_ELF_DYNSTR_GC = @USE_ELF_DYNSTR_GC@
 USE_ELF_HACK = @USE_ELF_HACK@
 STDCXX_COMPAT = @STDCXX_COMPAT@
@@ -203,17 +204,16 @@ MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = 
 MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS = @MOZ_JEMALLOC_STANDALONE_GLUE_LDOPTS@
 MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@
 
 MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@
 
 XPCOM_FROZEN_LDOPTS=@XPCOM_FROZEN_LDOPTS@
 XPCOM_LIBS=@XPCOM_LIBS@
 LIBXUL_LIBS=@LIBXUL_LIBS@
-MOZ_TIMELINE=@MOZ_TIMELINE@
 
 ENABLE_STRIP	= @ENABLE_STRIP@
 PKG_SKIP_STRIP	= @PKG_SKIP_STRIP@
 
 ClientWallet=1
 CookieManagement=1
 SingleSignon=1
 
@@ -338,16 +338,17 @@ AR_EXTRACT	= @AR_EXTRACT@
 AR_LIST		= @AR_LIST@
 AR_DELETE	= @AR_DELETE@
 AS		= @AS@
 ASFLAGS		= @ASFLAGS@
 AS_DASH_C_FLAG	= @AS_DASH_C_FLAG@
 LD		= @LD@
 RC		= @RC@
 RCFLAGS		= @RCFLAGS@
+MC		= @MC@
 WINDRES		= @WINDRES@
 IMPLIB		= @IMPLIB@
 FILTER		= @FILTER@
 BIN_FLAGS	= @BIN_FLAGS@
 MIDL		= @MIDL@
 MIDL_FLAGS	= @MIDL_FLAGS@
 _MSC_VER	= @_MSC_VER@
 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -2015,16 +2015,17 @@ showbuild:
 	@echo "CPP                = $(CPP)"
 	@echo "LD                 = $(LD)"
 	@echo "AR                 = $(AR)"
 	@echo "IMPLIB             = $(IMPLIB)"
 	@echo "FILTER             = $(FILTER)"
 	@echo "MKSHLIB            = $(MKSHLIB)"
 	@echo "MKCSHLIB           = $(MKCSHLIB)"
 	@echo "RC                 = $(RC)"
+	@echo "MC                 = $(MC)"
 	@echo "CFLAGS             = $(CFLAGS)"
 	@echo "OS_CFLAGS          = $(OS_CFLAGS)"
 	@echo "COMPILE_CFLAGS     = $(COMPILE_CFLAGS)"
 	@echo "CXXFLAGS           = $(CXXFLAGS)"
 	@echo "OS_CXXFLAGS        = $(OS_CXXFLAGS)"
 	@echo "COMPILE_CXXFLAGS   = $(COMPILE_CXXFLAGS)"
 	@echo "COMPILE_CMFLAGS    = $(COMPILE_CMFLAGS)"
 	@echo "COMPILE_CMMFLAGS   = $(COMPILE_CMMFLAGS)"
--- a/configure.in
+++ b/configure.in
@@ -118,17 +118,17 @@ dnl ====================================
 GLIB_VERSION=1.2.0
 LIBIDL_VERSION=0.6.3
 PERL_VERSION=5.006
 PYTHON_VERSION=2.5
 CAIRO_VERSION=1.10
 PANGO_VERSION=1.14.0
 GTK2_VERSION=2.10.0
 WINDRES_VERSION=2.14.90
-W32API_VERSION=3.8
+W32API_VERSION=3.14
 GNOMEVFS_VERSION=2.0
 GNOMEUI_VERSION=2.2.0
 GCONF_VERSION=1.2.1
 GIO_VERSION=2.18
 STARTUP_NOTIFICATION_VERSION=0.8
 DBUS_VERSION=0.60
 SQLITE_VERSION=3.7.5
 LIBNOTIFY_VERSION=0.4
@@ -312,16 +312,22 @@ case "$target" in
     LD="$android_toolchain"/bin/"$android_tool_prefix"-ld
     AR="$android_toolchain"/bin/"$android_tool_prefix"-ar
     RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib
     STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip
 
     if test -e "$android_ndk/sources/cxx-stl/stlport/libs/armeabi-v7a/libstlport_static.a" ; then
        STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/stlport/stlport"
        STLPORT_LDFLAGS="-L$android_ndk/sources/cxx-stl/stlport/libs/armeabi-v7a/  -lstlport_static"
+    elif  test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/armeabi-v7a/libstlport_static.a" ; then
+       STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/stlport/stlport"
+       STLPORT_LDFLAGS="-L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/armeabi-v7a  -lstlport_static"
+    elif test "$target" != "arm-android-eabi"; then
+       dnl fail if we're not building with NDKr4
+       AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
     fi
 
     CPPFLAGS="-I$android_platform/usr/include $STLPORT_CPPFLAGS $CPPFLAGS"
     CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS"
     CXXFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CXXFLAGS"
     LIBS="$LIBS $STLPORT_LDFLAGS"
 
     dnl Add -llog by default, since we use it all over the place.
@@ -865,18 +871,17 @@ EOF
                 "$_WINDRES_MINOR_VERSION" -lt "$WINDRES_MINOR_VERSION" -o \
                 "$_WINDRES_MAJOR_VERSION" -eq "$WINDRES_MAJOR_VERSION" -a \
                 "$_WINDRES_MINOR_VERSION" -eq "$WINDRES_MINOR_VERSION" -a \
                 "$_WINDRES_RELEASE_VERSION" -lt "$WINDRES_RELEASE_VERSION"
         then
             AC_MSG_ERROR([windres version $WINDRES_VERSION or higher is required to build.])
         fi
 
-        # Server 2003 is the highest version supported
-        MOZ_WINSDK_MAXVER=0x05020000
+        MOZ_WINSDK_MAXVER=0x06010000
     fi # !GNU_CC
 
     AC_DEFINE_UNQUOTED(WINVER,0x$WINVER)
     AC_DEFINE_UNQUOTED(_WIN32_WINNT,0x$WINVER)
     # Require OS features provided by IE 5.0
     AC_DEFINE_UNQUOTED(_WIN32_IE,0x0500)
 
     # If the maximum version supported by this SDK is lower than the target
@@ -2250,23 +2255,27 @@ ia64*-hpux*)
     ;;
     i*86)
     	USE_ELF_DYNSTR_GC=1
     ;;
     mips*)
         MOZ_DEBUG_FLAGS="-g" # We want inlining
     ;;
     esac
-    ;;
-
+
+    if test -z "$MC"; then 
+        MC=mc.exe  
+    fi
+    ;;
 *-mingw*)
     DSO_CFLAGS=
     DSO_PIC_CFLAGS=
     DLL_SUFFIX=.dll
     RC=rc.exe
+    MC=mc.exe
     # certain versions of cygwin's makedepend barf on the 
     # #include <string> vs -I./dist/include/string issue so don't use it
     SYSTEM_MAKEDEPEND=
     if test -n "$GNU_CC"; then
         CC="$CC -mwindows"
         CXX="$CXX -mwindows"
         CPP="$CPP -mwindows"
         CFLAGS="$CFLAGS -mms-bitfields"
@@ -2544,16 +2553,17 @@ ia64*-hpux*)
     MOZ_DEBUG_FLAGS="-g -fno-inline"
     MOZ_OPTIMIZE_FLAGS="-O2"
     MOZ_OPTIMIZE_LDFLAGS="-s -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA"
     DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
     LIBXUL_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
     TARGET_MD_ARCH=os2
     _PLATFORM_DEFAULT_TOOLKIT="cairo-os2"
     RC=rc.exe
+    MC=mc.exe
     RCFLAGS='-n'
     MOZ_USER_DIR="Mozilla"
     ZIP="$ZIP -X"
 
     if test "$MOZTOOLS"; then
         MOZ_TOOLS_DIR=`echo $MOZTOOLS | sed -e 's|\\\\|/|g'`
     else
         AC_MSG_ERROR([MOZTOOLS is not set])
@@ -4802,17 +4812,16 @@ MOZ_PSM=1
 MOZ_RDF=1
 MOZ_REFLOW_PERF=
 MOZ_SAFE_BROWSING=
 MOZ_HELP_VIEWER=
 MOZ_SPELLCHECK=1
 MOZ_SPLASHSCREEN=
 MOZ_STORAGE=1
 MOZ_SVG_DLISTS=
-MOZ_TIMELINE=
 MOZ_TOOLKIT_SEARCH=1
 MOZ_UI_LOCALE=en-US
 MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_XSLT_STANDALONE=
 MOZ_XTF=1
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
@@ -7455,22 +7464,30 @@ else
       if test ! -d "$WIN32_CRT_SRC_DIR"; then
         AC_MSG_ERROR([Invalid Win32 CRT source directory: ${WIN32_CRT_SRC_DIR}])
       fi
       WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
       _objdir_win=`pwd -W`
       WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
       MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
     else
-      MOZ_MEMORY_LDFLAGS='-MANIFEST:NO -LIBPATH:$(DIST)/lib -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt'
       if test -z "$MOZ_DEBUG"; then
         WIN32_CRT_LIBS="msvcrt.lib msvcprt.lib"
       else
         WIN32_CRT_LIBS="msvcrtd.lib msvcprtd.lib"
       fi
+      dnl Look for a broken crtdll.obj
+      WIN32_CRTDLL_FULLPATH=`lib -list $WIN32_CRT_LIBS | grep crtdll\\.obj`
+      lib -OUT:crtdll.obj $WIN32_CRT_LIBS -EXTRACT:$WIN32_CRTDLL_FULLPATH
+      if grep -q '__imp__\{0,1\}free' crtdll.obj; then
+        MOZ_MEMORY_LDFLAGS='-MANIFEST:NO -LIBPATH:$(DIST)/lib -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt'
+      else
+        MOZ_MEMORY_LDFLAGS='$(DIST)/../memory/jemalloc/jemalloc.lib'
+      fi
+      rm crtdll.obj
     fi
     dnl Also pass this to NSPR/NSS
     DLLFLAGS="$DLLFLAGS $MOZ_MEMORY_LDFLAGS"
     export DLLFLAGS
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
@@ -7543,16 +7560,36 @@ MOZ_ARG_ENABLE_BOOL(gctimer,
 [  --enable-gctimer        Enable GC timer (default=no)],
     MOZ_GCTIMER=1,
     MOZ_GCTIMER= )
 if test -n "$MOZ_GCTIMER"; then
     AC_DEFINE(MOZ_GCTIMER)
 fi
 
 dnl ========================================================
+dnl ETW - Event Tracing for Windows
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(ETW,
+[  --enable-ETW            Enable ETW (Event Tracing for Windows) event reporting
+                          (needs Windows Vista+ SDK)],
+    MOZ_ETW=1,
+    MOZ_ETW= )
+if test -n "$MOZ_ETW"; then
+    AC_DEFINE(MOZ_ETW)
+fi
+
+if test -n "$MOZ_ETW"; then
+    if test -z "$MOZ_WINSDK_TARGETVER"; then
+        AC_MSG_ERROR([--enable-ETW is only valid on Windows])
+    elif test "$MOZ_WINSDK_TARGETVER" -lt "06000000"; then
+        AC_MSG_ERROR([--enable-ETW requires the Windows Vista SDK or newer])
+    fi
+fi
+
+dnl ========================================================
 dnl Zealous JavaScript GC
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gczeal,
 [  --enable-gczeal         Enable zealous JavaScript GCing],
     JS_GC_ZEAL=1,
     JS_GC_ZEAL= )
 if test -n "$JS_GC_ZEAL"; then
     AC_DEFINE(JS_GC_ZEAL)
@@ -7706,29 +7743,16 @@ fi
 dnl ========================================================
 dnl = 
 dnl = Profiling and Instrumenting
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Profiling and Instrumenting)
 
 dnl ========================================================
-dnl = Enable timeline service, which provides lightweight
-dnl = instrumentation of mozilla for performance measurement.
-dnl = Timeline is off by default.
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(timeline,
-[  --enable-timeline       Enable timeline services ],
-    MOZ_TIMELINE=1,
-    MOZ_TIMELINE= )
-if test -n "$MOZ_TIMELINE"; then
-    AC_DEFINE(MOZ_TIMELINE)
-fi
-
-dnl ========================================================
 dnl = Enable NS_FUNCTION_TIMER, which provides Function 
 dnl = timing for identifying code bottlenecks 
 dnl = NS_FUNCTION_TIMER is off by default.
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(functiontimer,
 [  --enable-functiontimer  Enable NS_FUNCTION_TIMER ],
     NS_FUNCTION_TIMER=1,
     NS_FUNCTION_TIMER= )
@@ -8846,16 +8870,17 @@ AC_SUBST(AR_LIST)
 AC_SUBST(AR_EXTRACT)
 AC_SUBST(AR_DELETE)
 AC_SUBST(AS)
 AC_SUBST(ASFLAGS)
 AC_SUBST(AS_DASH_C_FLAG)
 AC_SUBST(LD)
 AC_SUBST(RC)
 AC_SUBST(RCFLAGS)
+AC_SUBST(MC)
 AC_SUBST(WINDRES)
 AC_SUBST(IMPLIB)
 AC_SUBST(FILTER)
 AC_SUBST(BIN_FLAGS)
 AC_SUBST(NS_USE_NATIVE)
 AC_SUBST(MOZ_WIDGET_TOOLKIT)
 AC_SUBST(MOZ_UPDATE_XTERM)
 AC_SUBST(MINIMO)
@@ -8878,16 +8903,17 @@ AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST(MOZ_EXTENSIONS)
 AC_SUBST(MOZ_JSDEBUGGER)
 AC_SUBST(MOZ_LOG_REFCNT)
 AC_SUBST(MOZ_LEAKY)
 AC_SUBST(MOZ_JPROF)
 AC_SUBST(MOZ_SHARK)
 AC_SUBST(MOZ_CALLGRIND)
 AC_SUBST(MOZ_VTUNE)
+AC_SUBST(MOZ_ETW)
 AC_SUBST(MOZ_PROFILING)
 AC_SUBST(MOZ_QUANTIFY)
 AC_SUBST(LIBICONV)
 AC_SUBST(MOZ_PLACES)
 AC_SUBST(MOZ_STORAGE)
 AC_SUBST(MOZ_TOOLKIT_SEARCH)
 AC_SUBST(MOZ_FEEDS)
 AC_SUBST(NS_PRINTING)
@@ -8934,17 +8960,16 @@ AC_SUBST(XPCOM_STANDALONE_GLUE_LDOPTS)
 
 AC_SUBST(USE_DEPENDENT_LIBS)
 
 AC_SUBST(MOZ_BUILD_ROOT)
 AC_SUBST(MOZ_OS2_TOOLS)
 
 AC_SUBST(MOZ_POST_DSO_LIB_COMMAND)
 AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
-AC_SUBST(MOZ_TIMELINE)
 
 # The following variables are available to branding and application
 # configuration ($BRANDING/configure.sh and $APPLICATION/confvars.sh):
 # - MOZ_APP_VENDOR: Used for application.ini's "Vendor" field, which also
 # impacts profile location and user-visible fields.
 # - MOZ_APP_BASENAME: Typically stays consistent for multiple branded
 # versions of a given application (e.g. Aurora and Firefox both use
 # "Firefox"), but may vary for full rebrandings (e.g. Iceweasel). Used
@@ -8977,16 +9002,20 @@ AC_DEFINE_UNQUOTED(FIREFOX_VERSION,$FIRE
 AC_SUBST(FIREFOX_VERSION)
 AC_DEFINE_UNQUOTED(MOZ_UA_BUILDID, "$MOZ_UA_BUILDID")
 AC_SUBST(MOZ_UA_BUILDID)
 
 AC_SUBST(MOZ_PKG_SPECIAL)
 
 AC_SUBST(MOZILLA_OFFICIAL)
 
+if test "$MOZ_TELEMETRY_REPORTING"; then
+    AC_DEFINE(MOZ_TELEMETRY_REPORTING)
+fi
+
 dnl win32 options
 AC_SUBST(MOZ_MAPINFO)
 AC_SUBST(MOZ_BROWSE_INFO)
 AC_SUBST(MOZ_TOOLS_DIR)
 AC_SUBST(WIN32_REDIST_DIR)
 AC_SUBST(PYTHON)
 AC_SUBST(MAKENSISU)
 
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -37,16 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_Element_h__
 #define mozilla_dom_Element_h__
 
 #include "nsIContent.h"
 #include "nsEventStates.h"
+#include "nsDOMMemoryReporter.h"
 
 class nsEventStateManager;
 class nsGlobalWindow;
 class nsFocusManager;
 
 // Element-specific flags
 enum {
   // Set if the element has a pending style change.
@@ -92,16 +93,18 @@ class Element : public nsIContent
 public:
 #ifdef MOZILLA_INTERNAL_API
   Element(already_AddRefed<nsINodeInfo> aNodeInfo) :
     nsIContent(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
   {}
 #endif // MOZILLA_INTERNAL_API
 
+  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(Element, nsIContent)
+
   /**
    * Method to get the full state of this element.  See nsEventStates.h for
    * the possible bits that could be set here.
    */
   nsEventStates State() const {
     // mState is maintained by having whoever might have changed it
     // call UpdateState() or one of the other mState mutators.
     return mState;
--- a/content/base/src/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -842,8 +842,26 @@ nsAttrAndChildArray::SetChildAtPos(void*
     previous->mNextSibling = aChild;
   }
   if (aIndex != aChildCount) {
     nsIContent* next = static_cast<nsIContent*>(*(aPos + 1));
     aChild->mNextSibling = next;
     next->mPreviousSibling = aChild;
   }
 }
+
+PRInt64
+nsAttrAndChildArray::SizeOf() const
+{
+  PRInt64 size = sizeof(*this);
+
+  if (mImpl) {
+    // Don't add the size taken by *mMappedAttrs because it's shared.
+
+    // mBuffer cointains InternalAttr and nsIContent* (even if it's void**)
+    // so, we just have to compute the size of *mBuffer given that this object
+    // doesn't own the children list.
+    size += mImpl->mBufferSize * sizeof(*(mImpl->mBuffer)) + NS_IMPL_EXTRA_SIZE;
+  }
+
+  return size;
+}
+
--- a/content/base/src/nsAttrAndChildArray.h
+++ b/content/base/src/nsAttrAndChildArray.h
@@ -126,16 +126,18 @@ public:
   void Compact();
 
   bool CanFitMoreAttrs() const
   {
     return AttrSlotCount() < ATTRCHILD_ARRAY_MAX_ATTR_COUNT ||
            !AttrSlotIsTaken(ATTRCHILD_ARRAY_MAX_ATTR_COUNT - 1);
   }
 
+  PRInt64 SizeOf() const;
+
 private:
   nsAttrAndChildArray(const nsAttrAndChildArray& aOther); // Not to be implemented
   nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther); // Not to be implemented
 
   void Clear();
 
   PRUint32 NonMappedAttrCount() const;
   PRUint32 MappedAttrCount() const;
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -61,17 +61,17 @@
 #include "nsIParser.h"
 #include "nsContentErrors.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIViewManager.h"
 #include "nsIContentViewer.h"
 #include "nsIAtom.h"
 #include "nsGkAtoms.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsNetCID.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIScriptSecurityManager.h"
@@ -510,17 +510,17 @@ nsContentSink::ProcessHeaderData(nsIAtom
 
     // Note that a non-codebase principal (eg the system principal) will return
     // a null URI.
     nsCOMPtr<nsIURI> codebaseURI;
     rv = mDocument->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
     NS_ENSURE_TRUE(codebaseURI, rv);
 
     nsCOMPtr<nsIPrompt> prompt;
-    nsCOMPtr<nsIDOMWindowInternal> window (do_QueryInterface(mDocument->GetScriptGlobalObject()));
+    nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(mDocument->GetScriptGlobalObject());
     if (window) {
       window->GetPrompter(getter_AddRefs(prompt));
     }
 
     nsCOMPtr<nsIChannel> channel;
     if (mParser) {
       mParser->GetChannel(getter_AddRefs(channel));
     }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2319,16 +2319,17 @@ nsContentUtils::LoadImage(nsIURI* aURI, 
   // Make the URI immutable so people won't change it under us
   NS_TryToSetImmutable(aURI);
 
   // XXXbz using "documentURI" for the initialDocumentURI is not quite
   // right, but the best we can do here...
   return imgLoader->LoadImage(aURI,                 /* uri to load */
                               documentURI,          /* initialDocumentURI */
                               aReferrer,            /* referrer */
+                              aLoadingPrincipal,    /* loading principal */
                               loadGroup,            /* loadgroup */
                               aObserver,            /* imgIDecoderObserver */
                               aLoadingDocument,     /* uniquification key */
                               aLoadFlags,           /* load flags */
                               nsnull,               /* cache key */
                               nsnull,               /* existing request*/
                               channelPolicy,        /* CSP info */
                               aRequest);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -111,17 +111,17 @@
 #include "nsIWebNavigation.h"
 #include "nsIScriptError.h"
 
 #include "nsNetUtil.h"     // for NS_MakeAbsoluteURI
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsFocusManager.h"
 
 // for radio group stuff
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
@@ -5090,31 +5090,30 @@ nsDocument::GetDefaultView(nsIDOMWindow*
 }
 
 NS_IMETHODIMP
 nsDocument::GetLocation(nsIDOMLocation **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nsnull;
 
-  nsCOMPtr<nsIDOMWindowInternal> w(do_QueryInterface(mScriptGlobalObject));
+  nsCOMPtr<nsIDOMWindow> w = do_QueryInterface(mScriptGlobalObject);
 
   if (!w) {
     return NS_OK;
   }
 
   return w->GetLocation(_retval);
 }
 
 Element*
 nsIDocument::GetHtmlElement()
 {
   Element* rootElement = GetRootElement();
-  if (rootElement && rootElement->Tag() == nsGkAtoms::html &&
-      rootElement->IsHTML())
+  if (rootElement && rootElement->IsHTML(nsGkAtoms::html))
     return rootElement;
   return nsnull;
 }
 
 Element*
 nsIDocument::GetHtmlChildElement(nsIAtom* aTag)
 {
   Element* html = GetHtmlElement();
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -141,16 +141,17 @@
 
 #include "mozAutoDocUpdate.h"
 
 #include "nsCSSParser.h"
 #include "nsTPtrArray.h"
 #include "prprf.h"
 
 #include "nsSVGFeatures.h"
+#include "nsDOMMemoryReporter.h"
 
 using namespace mozilla::dom;
 namespace css = mozilla::css;
 
 NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
 
 PRInt32 nsIContent::sTabFocusModel = eTabFocus_any;
 PRBool nsIContent::sTabFocusModelAppliesToXUL = PR_FALSE;
@@ -1325,17 +1326,17 @@ nsIContent::HasIndependentSelection()
   nsIFrame* frame = GetPrimaryFrame();
   return (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION);
 }
 
 nsIContent*
 nsIContent::GetEditingHost()
 {
   // If this isn't editable, return NULL.
-  NS_ENSURE_TRUE(HasFlag(NODE_IS_EDITABLE), nsnull);
+  NS_ENSURE_TRUE(IsEditableInternal(), nsnull);
 
   nsIDocument* doc = GetCurrentDoc();
   NS_ENSURE_TRUE(doc, nsnull);
   // If this is in designMode, we should return <body>
   if (doc->HasFlag(NODE_IS_EDITABLE)) {
     return doc->GetBodyElement();
   }
 
@@ -5367,8 +5368,20 @@ nsNSElementTearoff::MozMatchesSelector(c
 {
   NS_PRECONDITION(aReturn, "Null out param?");
 
   nsresult rv;
   *aReturn = mContent->MozMatchesSelector(aSelector, &rv);
 
   return rv;
 }
+
+PRInt64
+nsGenericElement::SizeOf() const
+{
+  PRInt64 size = MemoryReporter::GetBasicSize<nsGenericElement, Element>(this);
+
+  size -= sizeof(mAttrsAndChildren);
+  size += mAttrsAndChildren.SizeOf();
+
+  return size;
+}
+
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -235,16 +235,18 @@ class nsGenericElement : public mozilla:
 public:
   nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericElement();
 
   friend class nsNSElementTearoff;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
+  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
+
   /**
    * Called during QueryInterface to give the binding manager a chance to
    * get an interface for this element.
    */
   nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   // nsINode interface methods
   virtual PRUint32 GetChildCount() const;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -251,16 +251,17 @@ GK_ATOM(control, "control")
 #ifdef MOZ_MEDIA
 GK_ATOM(controls, "controls")
 #endif
 GK_ATOM(coords, "coords")
 GK_ATOM(copy, "copy")
 GK_ATOM(copyOf, "copy-of")
 GK_ATOM(count, "count")
 GK_ATOM(crop, "crop")
+GK_ATOM(crossorigin, "crossorigin")
 GK_ATOM(curpos, "curpos")
 GK_ATOM(current, "current")
 GK_ATOM(currentloop, "currentloop")
 GK_ATOM(cycler, "cycler")
 GK_ATOM(data, "data")
 GK_ATOM(datalist, "datalist")
 GK_ATOM(dataType, "data-type")
 GK_ATOM(dateTime, "date-time")
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -714,23 +714,31 @@ nsImageLoadingContent::LoadImage(nsIURI*
   nsContentUtils::CanLoadImage(aNewURI, this, aDocument,
                                aDocument->NodePrincipal(), &cpDecision);
   if (!NS_CP_ACCEPTED(cpDecision)) {
     FireEvent(NS_LITERAL_STRING("error"));
     SetBlockedRequest(aNewURI, cpDecision);
     return NS_OK;
   }
 
+  nsLoadFlags loadFlags = aLoadFlags;
+  PRInt32 corsmode = GetCORSMode();
+  if (corsmode == nsImageLoadingContent::CORS_ANONYMOUS) {
+    loadFlags |= imgILoader::LOAD_CORS_ANONYMOUS;
+  } else if (corsmode == nsImageLoadingContent::CORS_USE_CREDENTIALS) {
+    loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS;
+  }
+
   // Not blocked. Do the load.
   nsCOMPtr<imgIRequest>& req = PrepareNextRequest();
   nsresult rv;
   rv = nsContentUtils::LoadImage(aNewURI, aDocument,
                                  aDocument->NodePrincipal(),
                                  aDocument->GetDocumentURI(),
-                                 this, aLoadFlags,
+                                 this, loadFlags,
                                  getter_AddRefs(req));
   if (NS_SUCCEEDED(rv)) {
     TrackImage(req);
   } else {
     // If we don't have a current URI, we might as well store this URI so people
     // know what we tried (and failed) to load.
     if (!mCurrentRequest)
       mCurrentURI = aNewURI;
@@ -1081,8 +1089,13 @@ nsImageLoadingContent::CreateStaticImage
   aDest->mStateChangerDepth = mStateChangerDepth;
   aDest->mIsImageStateForced = mIsImageStateForced;
   aDest->mLoading = mLoading;
   aDest->mBroken = mBroken;
   aDest->mUserDisabled = mUserDisabled;
   aDest->mSuppressed = mSuppressed;
 }
 
+nsImageLoadingContent::CORSMode
+nsImageLoadingContent::GetCORSMode()
+{
+  return CORS_NONE;
+}
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -64,16 +64,35 @@ class nsImageLoadingContent : public nsI
 public:
   nsImageLoadingContent();
   virtual ~nsImageLoadingContent();
 
   NS_DECL_IMGICONTAINEROBSERVER
   NS_DECL_IMGIDECODEROBSERVER
   NS_DECL_NSIIMAGELOADINGCONTENT
 
+  enum CORSMode {
+    /**
+     * The default of not using CORS to validate cross-origin loads.
+     */
+    CORS_NONE,
+
+    /**
+     * Validate cross-site loads using CORS, but do not send any credentials
+     * (cookies, HTTP auth logins, etc) along with the request.
+     */
+    CORS_ANONYMOUS,
+
+    /**
+     * Validate cross-site loads using CORS, and send credentials such as cookies
+     * and HTTP auth logins along with the request.
+     */
+    CORS_USE_CREDENTIALS
+  };
+
 protected:
   /**
    * LoadImage is called by subclasses when the appropriate
    * attributes (eg 'src' for <img> tags) change.  The string passed
    * in is the new uri string; this consolidates the code for getting
    * the charset, constructing URI objects, and any other incidentals
    * into this superclass.   
    *
@@ -154,16 +173,22 @@ protected:
   void ClearBrokenState() { mBroken = PR_FALSE; }
 
   PRBool LoadingEnabled() { return mLoadingEnabled; }
 
   // Sets blocking state only if the desired state is different from the
   // current one. See the comment for mBlockingOnload for more information.
   void SetBlockingOnload(PRBool aBlocking);
 
+  /**
+   * Returns the CORS mode that will be used for all future image loads. The
+   * default implementation returns CORS_NONE unconditionally.
+   */
+  virtual CORSMode GetCORSMode();
+
 private:
   /**
    * Struct used to manage the image observers.
    */
   struct ImageObserver {
     ImageObserver(imgIDecoderObserver* aObserver) :
       mObserver(aObserver),
       mNext(nsnull)
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -48,16 +48,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIDocument.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsXULElement.h"
 #include "nsIDOMSVGStylable.h"
+#include "nsContentUtils.h"
 
 namespace css = mozilla::css;
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsIAtom*
 nsStyledElementNotElementCSSInlineStyle::GetClassAttributeName() const
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -3555,35 +3555,42 @@ WebGLContext::DOMElementToImageSurface(n
         nsLayoutUtils::SurfaceFromElement(imageOrCanvas, flags);
     if (!res.mSurface)
         return NS_ERROR_FAILURE;
     if (res.mSurface->GetType() != gfxASurface::SurfaceTypeImage) {
         // SurfaceFromElement lied!
         return NS_ERROR_FAILURE;
     }
 
-    // Bug 656277 - Prevent loading WebGL textures from cross-domain images
+    // We disallow loading cross-domain images that have not been validated
+    // with CORS as WebGL textures. The reason for doing that is that timing
+    // attacks on WebGL shaders are able to retrieve approximations of the
+    // pixel values in WebGL textures; see bug 655987.
     //
-    // We disallow loading cross-domain images as WebGL textures. The reason for doing that
-    // is that timing attacks on WebGL shaders are able to retrieve approximations of the pixel values
-    // in WebGL textures, see bug 655987.
-    //
-    // To prevent a loophole where a Canvas2D would be used as a proxy to load cross-domain textures,
-    // we also disallow loading textures from write-only Canvas2D's.
-
-    // part 1: check that the DOM element is same-origin.
+    // To prevent a loophole where a Canvas2D would be used as a proxy to load
+    // cross-domain textures, we also disallow loading textures from write-only
+    // Canvas2D's.
+
+    // part 1: check that the DOM element is same-origin, or has otherwise been
+    // validated for cross-domain use.
     // if res.mPrincipal == null, no need for the origin check. See DoDrawImageSecurityCheck.
     // this case happens in the mochitest for images served from mochi.test:8888
     if (res.mPrincipal) {
         PRBool subsumes;
         nsresult rv = HTMLCanvasElement()->NodePrincipal()->Subsumes(res.mPrincipal, &subsumes);
         if (NS_FAILED(rv) || !subsumes) {
-            LogMessageIfVerbose("It is forbidden to load a WebGL texture from a cross-domain element. "
-                                "See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
-            return NS_ERROR_DOM_SECURITY_ERR;
+            PRInt32 corsmode;
+            if (!res.mImageRequest || NS_FAILED(res.mImageRequest->GetCORSMode(&corsmode))) {
+                corsmode = imgIRequest::CORS_NONE;
+            }
+            if (corsmode == imgIRequest::CORS_NONE) {
+                LogMessageIfVerbose("It is forbidden to load a WebGL texture from a cross-domain element that has not been validated with CORS. "
+                                    "See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures");
+                return NS_ERROR_DOM_SECURITY_ERR;
+            }
         }
     }
 
     // part 2: if the DOM element is a canvas, check that it's not write-only. That would indicate a tainted canvas,
     // i.e. a canvas that could contain cross-domain image data.
     nsCOMPtr<nsIContent> maybeDOMCanvas = do_QueryInterface(imageOrCanvas);
     if (maybeDOMCanvas && maybeDOMCanvas->IsHTML(nsGkAtoms::canvas)) {
         nsHTMLCanvasElement *canvas = static_cast<nsHTMLCanvasElement*>(maybeDOMCanvas.get());
--- a/content/canvas/src/WebGLContextNotSupported.cpp
+++ b/content/canvas/src/WebGLContextNotSupported.cpp
@@ -47,8 +47,9 @@ DOMCI_DATA(WebGLRenderingContext, void)
 DOMCI_DATA(WebGLBuffer, void)
 DOMCI_DATA(WebGLTexture, void)
 DOMCI_DATA(WebGLProgram, void)
 DOMCI_DATA(WebGLShader, void)
 DOMCI_DATA(WebGLFramebuffer, void)
 DOMCI_DATA(WebGLRenderbuffer, void)
 DOMCI_DATA(WebGLUniformLocation, void)
 DOMCI_DATA(WebGLActiveInfo, void)
+DOMCI_DATA(WebGLExtension, void)
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -98,16 +98,17 @@
 #include "gfxPlatform.h"
 #include "gfxFont.h"
 #include "gfxTextRunCache.h"
 #include "gfxBlur.h"
 #include "gfxUtils.h"
 
 #include "nsFrameManager.h"
 #include "nsFrameLoader.h"
+#include "nsBidi.h"
 #include "nsBidiPresUtils.h"
 #include "Layers.h"
 #include "CanvasUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsStyleUtil.h"
 #include "CanvasImageCache.h"
 
 #include <algorithm>
@@ -1063,16 +1064,18 @@ nsCanvasRenderingContext2D::SetDimension
     // Check that the dimensions are sane
     gfxIntSize size(width, height);
     if (gfxASurface::CheckSurfaceSize(size, 0xffff)) {
         // Zero sized surfaces have problems, so just use a 1 by 1.
         if (height == 0 || width == 0) {
             mZero = PR_TRUE;
             height = 1;
             width = 1;
+        } else {
+            mZero = PR_FALSE;
         }
 
         gfxASurface::gfxImageFormat format = GetImageFormat();
 
         if (!PR_GetEnv("MOZ_CANVAS_IMAGE_SURFACE")) {
             nsCOMPtr<nsIContent> content =
                 do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
             nsIDocument* ownerDoc = nsnull;
@@ -2731,20 +2734,16 @@ nsCanvasRenderingContext2D::DrawOrMeasur
     }
 
     nsIPresShell* presShell = GetPresShell();
     if (!presShell)
         return NS_ERROR_FAILURE;
 
     nsIDocument* document = presShell->GetDocument();
 
-    nsBidiPresUtils* bidiUtils = presShell->GetPresContext()->GetBidiUtils();
-    if (!bidiUtils)
-        return NS_ERROR_FAILURE;
-
     // replace all the whitespace characters with U+0020 SPACE
     nsAutoString textToDraw(aRawText);
     TextReplaceWhitespaceCharacters(textToDraw);
 
     // for now, default to ltr if not in doc
     PRBool isRTL = PR_FALSE;
 
     if (content && content->IsInDoc()) {
@@ -2780,25 +2779,27 @@ nsCanvasRenderingContext2D::DrawOrMeasur
 
     processor.mFontgrp = GetCurrentFontStyle();
     NS_ASSERTION(processor.mFontgrp, "font group is null");
 
     nscoord totalWidthCoord;
 
     // calls bidi algo twice since it needs the full text width and the
     // bounding boxes before rendering anything
-    rv = bidiUtils->ProcessText(textToDraw.get(),
-                                textToDraw.Length(),
-                                isRTL ? NSBIDI_RTL : NSBIDI_LTR,
-                                presShell->GetPresContext(),
-                                processor,
-                                nsBidiPresUtils::MODE_MEASURE,
-                                nsnull,
-                                0,
-                                &totalWidthCoord);
+    nsBidi bidiEngine;
+    rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
+                                      textToDraw.Length(),
+                                      isRTL ? NSBIDI_RTL : NSBIDI_LTR,
+                                      presShell->GetPresContext(),
+                                      processor,
+                                      nsBidiPresUtils::MODE_MEASURE,
+                                      nsnull,
+                                      0,
+                                      &totalWidthCoord,
+                                      &bidiEngine);
     if (NS_FAILED(rv))
         return rv;
 
     float totalWidth = float(totalWidthCoord) / processor.mAppUnitsPerDevPixel;
     if (aWidth)
         *aWidth = totalWidth;
 
     // if only measuring, don't need to do any more work
@@ -2887,25 +2888,26 @@ nsCanvasRenderingContext2D::DrawOrMeasur
 
         gfxContext* ctx = ShadowInitialize(drawExtents, blur);
 
         if (ctx) {
             CopyContext(ctx, mThebes);
             ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
             processor.mThebes = ctx;
 
-            rv = bidiUtils->ProcessText(textToDraw.get(),
-                                        textToDraw.Length(),
-                                        isRTL ? NSBIDI_RTL : NSBIDI_LTR,
-                                        presShell->GetPresContext(),
-                                        processor,
-                                        nsBidiPresUtils::MODE_DRAW,
-                                        nsnull,
-                                        0,
-                                        nsnull);
+            rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
+                                              textToDraw.Length(),
+                                              isRTL ? NSBIDI_RTL : NSBIDI_LTR,
+                                              presShell->GetPresContext(),
+                                              processor,
+                                              nsBidiPresUtils::MODE_DRAW,
+                                              nsnull,
+                                              0,
+                                              nsnull,
+                                              &bidiEngine);
             if (NS_FAILED(rv))
                 return rv;
 
             ShadowFinalize(blur);
         }
 
         processor.mThebes = mThebes;
     }
@@ -2924,25 +2926,26 @@ nsCanvasRenderingContext2D::DrawOrMeasur
 
             // don't want operators to be applied twice
             mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
         }
 
         ApplyStyle(STYLE_FILL);
     }
 
-    rv = bidiUtils->ProcessText(textToDraw.get(),
-                                textToDraw.Length(),
-                                isRTL ? NSBIDI_RTL : NSBIDI_LTR,
-                                presShell->GetPresContext(),
-                                processor,
-                                nsBidiPresUtils::MODE_DRAW,
-                                nsnull,
-                                0,
-                                nsnull);
+    rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
+                                      textToDraw.Length(),
+                                      isRTL ? NSBIDI_RTL : NSBIDI_LTR,
+                                      presShell->GetPresContext(),
+                                      processor,
+                                      nsBidiPresUtils::MODE_DRAW,
+                                      nsnull,
+                                      0,
+                                      nsnull,
+                                      &bidiEngine);
 
     // this needs to be restored before function can return
     if (doUseIntermediateSurface) {
         mThebes->PopGroupToSource();
         DirtyAllStyles();
     }
 
     if (NS_FAILED(rv))
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -95,16 +95,17 @@
 #include "gfxPlatform.h"
 #include "gfxFont.h"
 #include "gfxTextRunCache.h"
 #include "gfxBlur.h"
 #include "gfxUtils.h"
 
 #include "nsFrameManager.h"
 #include "nsFrameLoader.h"
+#include "nsBidi.h"
 #include "nsBidiPresUtils.h"
 #include "Layers.h"
 #include "CanvasUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsStyleUtil.h"
 #include "CanvasImageCache.h"
 
 #include <algorithm>
@@ -821,22 +822,27 @@ protected:
       AlignedStorage2<SurfacePattern> mSurfacePattern;
     };
     Pattern *mPattern;
   };
 
   /* This is an RAII based class that can be used as a drawtarget for
    * operations that need a shadow drawn. It will automatically provide a
    * temporary target when needed, and if so blend it back with a shadow.
+   *
+   * aBounds specifies the bounds of the drawing operation that will be
+   * drawn to the target, it is given in device space! This function will
+   * change aBounds to incorporate shadow bounds. If this is NULL the drawing
+   * operation will be assumed to cover an infinite rect.
    */
   class AdjustedTarget
   {
   public:
     AdjustedTarget(nsCanvasRenderingContext2DAzure *ctx,
-                   const mgfx::Rect *aBounds = nsnull)
+                   mgfx::Rect *aBounds = nsnull)
       : mCtx(nsnull)
     {
       if (!ctx->NeedToDrawShadow()) {
         mTarget = ctx->mTarget;
         return;
       }
       mCtx = ctx;
 
@@ -844,86 +850,80 @@ protected:
 
       mSigma = state.shadowBlur / 2.0f;
 
       if (mSigma > SIGMA_MAX) {
         mSigma = SIGMA_MAX;
       }
         
       Matrix transform = mCtx->mTarget->GetTransform();
-      if (!aBounds) {
-        mTempSize = IntSize(ctx->mWidth, ctx->mHeight);
-
-        // We need to enlarge an possibly offset our temporary surface
-        // so that things outside of the canvas may cast shadows.
-        if (state.shadowOffset.x > 0) {
-          mTempSize.width += state.shadowOffset.x;
-          mSurfOffset.x = -state.shadowOffset.x;
-          transform._31 += state.shadowOffset.x;
-        } else {
-          mTempSize.width -= state.shadowOffset.x;
-        }
-        if (state.shadowOffset.y > 0) {
-          mTempSize.height += state.shadowOffset.y;
-          mSurfOffset.y = -state.shadowOffset.y;
-          transform._32 += state.shadowOffset.y;
-        } else {
-          mTempSize.height -= state.shadowOffset.y;
-        }
-
-        if (mSigma > 0) {
-          float blurRadius = mSigma * 3;
-          mSurfOffset.x -= blurRadius;
-          mSurfOffset.y -= blurRadius;
-          mTempSize.width += blurRadius;
-          mTempSize.height += blurRadius;
-          transform._31 += blurRadius;
-          transform._32 += blurRadius;
-        }
-      } // XXX - Implement aBounds path! See bug 666452.
+
+      mTempRect = mgfx::Rect(0, 0, ctx->mWidth, ctx->mHeight);
+
+      Float blurRadius = mSigma * 3;
+
+      // We need to enlarge and possibly offset our temporary surface
+      // so that things outside of the canvas may cast shadows.
+      mTempRect.Inflate(Margin(blurRadius + NS_MAX<Float>(state.shadowOffset.x, 0),
+                               blurRadius + NS_MAX<Float>(state.shadowOffset.y, 0),
+                               blurRadius + NS_MAX<Float>(-state.shadowOffset.x, 0),
+                               blurRadius + NS_MAX<Float>(-state.shadowOffset.y, 0)));
+
+      if (aBounds) {
+        // We actually include the bounds of the shadow blur, this makes it
+        // easier to execute the actual blur on hardware, and shouldn't affect
+        // the amount of pixels that need to be touched.
+        aBounds->Inflate(Margin(blurRadius, blurRadius,
+                                blurRadius, blurRadius));
+        mTempRect = mTempRect.Intersect(*aBounds);
+      }
+
+      mTempRect.ScaleRoundOut(1.0f);
+
+      transform._31 -= mTempRect.x;
+      transform._32 -= mTempRect.y;
         
       mTarget =
-        mCtx->mTarget->CreateSimilarDrawTarget(mTempSize,
-                                                FORMAT_B8G8R8A8);
-
-      mTarget->SetTransform(transform);
+        mCtx->mTarget->CreateSimilarDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)),
+                                               FORMAT_B8G8R8A8);
 
       if (!mTarget) {
         // XXX - Deal with the situation where our temp size is too big to
         // fit in a texture.
         mTarget = ctx->mTarget;
         mCtx = nsnull;
+      } else {
+        mTarget->SetTransform(transform);
       }
     }
 
     ~AdjustedTarget()
     {
       if (!mCtx) {
         return;
       }
 
       RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
       
-      mCtx->mTarget->DrawSurfaceWithShadow(snapshot, mSurfOffset,
+      mCtx->mTarget->DrawSurfaceWithShadow(snapshot, mTempRect.TopLeft(),
                                            Color::FromABGR(mCtx->CurrentState().shadowColor),
                                            mCtx->CurrentState().shadowOffset, mSigma,
                                            mCtx->CurrentState().op);
     }
 
     DrawTarget* operator->()
     {
       return mTarget;
     }
 
   private:
     RefPtr<DrawTarget> mTarget;
     nsCanvasRenderingContext2DAzure *mCtx;
     Float mSigma;
-    IntSize mTempSize;
-    Point mSurfOffset;
+    mgfx::Rect mTempRect;
   };
 
   nsAutoTArray<ContextState, 3> mStyleStack;
 
   inline ContextState& CurrentState() {
     return mStyleStack[mStyleStack.Length() - 1];
   }
     
@@ -1221,16 +1221,18 @@ nsCanvasRenderingContext2DAzure::SetDime
 {
   RefPtr<DrawTarget> target;
 
   // Zero sized surfaces cause issues, so just go with 1x1.
   if (height == 0 || width == 0) {
     mZero = PR_TRUE;
     height = 1;
     width = 1;
+  } else {
+    mZero = PR_FALSE;
   }
 
   // Check that the dimensions are sane
   IntSize size(width, height);
   if (size.width <= 0xFFFF && size.height <= 0xFFFF &&
       size.width >= 0 && size.height >= 0) {
     SurfaceFormat format = GetSurfaceFormat();
     nsCOMPtr<nsIContent> content =
@@ -2106,67 +2108,83 @@ nsCanvasRenderingContext2DAzure::FillRec
         h = patternSize.height - y;
         if (h < 0) {
           h = 0;
         }
       }
     }
   }
 
-  AdjustedTarget(this)->FillRect(mgfx::Rect(x, y, w, h),
-                                  GeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
-                                  DrawOptions(state.globalAlpha, UsedOperation()));
+  mgfx::Rect bounds;
+  
+  if (NeedToDrawShadow()) {
+    bounds = mgfx::Rect(x, y, w, h);
+    bounds = mTarget->GetTransform().TransformBounds(bounds);
+  }
+
+  AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
+    FillRect(mgfx::Rect(x, y, w, h),
+             GeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
+             DrawOptions(state.globalAlpha, UsedOperation()));
 
   return RedrawUser(gfxRect(x, y, w, h));
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::StrokeRect(float x, float y, float w, float h)
 {
   if (!FloatValidate(x,y,w,h)) {
     return NS_OK;
   }
 
   const ContextState &state = CurrentState();
 
+  mgfx::Rect bounds;
+  
+  if (NeedToDrawShadow()) {
+    bounds = mgfx::Rect(x - state.lineWidth / 2.0f, y - state.lineWidth / 2.0f,
+                        w + state.lineWidth, h + state.lineWidth);
+    bounds = mTarget->GetTransform().TransformBounds(bounds);
+  }
+
   if (!w && !h) {
     return NS_OK;
   } else if (!h) {
     CapStyle cap = CAP_BUTT;
     if (state.lineJoin == JOIN_ROUND) {
       cap = CAP_ROUND;
     }
-    AdjustedTarget(this)->
+    AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
       StrokeLine(Point(x, y), Point(x + w, y),
                   GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
                   StrokeOptions(state.lineWidth, state.lineJoin,
                                 cap, state.miterLimit,
                                 state.dash.Length(),
                                 state.dash.Elements(),
                                 state.dashOffset),
                   DrawOptions(state.globalAlpha, UsedOperation()));
     return NS_OK;
   } else if (!w) {
     CapStyle cap = CAP_BUTT;
     if (state.lineJoin == JOIN_ROUND) {
       cap = CAP_ROUND;
     }
-    AdjustedTarget(this)->
+    AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
       StrokeLine(Point(x, y), Point(x, y + h),
                   GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
                   StrokeOptions(state.lineWidth, state.lineJoin,
                                 cap, state.miterLimit,
                                 state.dash.Length(),
                                 state.dash.Elements(),
                                 state.dashOffset),
                   DrawOptions(state.globalAlpha, UsedOperation()));
     return NS_OK;
   }
 
-  AdjustedTarget(this)->
+  AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
     StrokeRect(mgfx::Rect(x, y, w, h),
                 GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
                 StrokeOptions(state.lineWidth, state.lineJoin,
                               state.lineCap, state.miterLimit,
                               state.dash.Length(),
                               state.dash.Elements(),
                               state.dashOffset),
                 DrawOptions(state.globalAlpha, UsedOperation()));
@@ -2206,17 +2224,23 @@ NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Fill()
 {
   EnsureUserSpacePath();
 
   if (!mPath) {
     return NS_OK;
   }
 
-  AdjustedTarget(this)->
+  mgfx::Rect bounds;
+
+  if (NeedToDrawShadow()) {
+    bounds = mPath->GetBounds(mTarget->GetTransform());
+  }
+
+  AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
     Fill(mPath, GeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
          DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   return Redraw();
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Stroke()
@@ -2224,24 +2248,30 @@ nsCanvasRenderingContext2DAzure::Stroke(
   EnsureUserSpacePath();
 
   if (!mPath) {
     return NS_OK;
   }
 
   const ContextState &state = CurrentState();
 
-  AdjustedTarget(this)->
+  StrokeOptions strokeOptions(state.lineWidth, state.lineJoin,
+                              state.lineCap, state.miterLimit,
+                              state.dash.Length(), state.dash.Elements(),
+                              state.dashOffset);
+
+  mgfx::Rect bounds;
+  if (NeedToDrawShadow()) {
+    bounds =
+      mPath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
+  }
+
+  AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
     Stroke(mPath, GeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
-            StrokeOptions(state.lineWidth, state.lineJoin,
-                          state.lineCap, state.miterLimit,
-                          state.dash.Length(),
-                          state.dash.Elements(),
-                          state.dashOffset),
-            DrawOptions(state.globalAlpha, UsedOperation()));
+           strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
   return Redraw();
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::Clip()
 {
   EnsureUserSpacePath();
@@ -3189,21 +3219,16 @@ nsCanvasRenderingContext2DAzure::DrawOrM
   }
 
   nsIPresShell* presShell = GetPresShell();
   if (!presShell)
       return NS_ERROR_FAILURE;
 
   nsIDocument* document = presShell->GetDocument();
 
-  nsBidiPresUtils* bidiUtils = presShell->GetPresContext()->GetBidiUtils();
-  if (!bidiUtils) {
-    return NS_ERROR_FAILURE;
-  }
-
   // replace all the whitespace characters with U+0020 SPACE
   nsAutoString textToDraw(aRawText);
   TextReplaceWhitespaceCharacters(textToDraw);
 
   // for now, default to ltr if not in doc
   PRBool isRTL = PR_FALSE;
 
   if (content && content->IsInDoc()) {
@@ -3244,25 +3269,27 @@ nsCanvasRenderingContext2DAzure::DrawOrM
 
   processor.mFontgrp = GetCurrentFontStyle();
   NS_ASSERTION(processor.mFontgrp, "font group is null");
 
   nscoord totalWidthCoord;
 
   // calls bidi algo twice since it needs the full text width and the
   // bounding boxes before rendering anything
-  rv = bidiUtils->ProcessText(textToDraw.get(),
-                              textToDraw.Length(),
-                              isRTL ? NSBIDI_RTL : NSBIDI_LTR,
-                              presShell->GetPresContext(),
-                              processor,
-                              nsBidiPresUtils::MODE_MEASURE,
-                              nsnull,
-                              0,
-                              &totalWidthCoord);
+  nsBidi bidiEngine;
+  rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
+                                textToDraw.Length(),
+                                isRTL ? NSBIDI_RTL : NSBIDI_LTR,
+                                presShell->GetPresContext(),
+                                processor,
+                                nsBidiPresUtils::MODE_MEASURE,
+                                nsnull,
+                                0,
+                                &totalWidthCoord,
+                                &bidiEngine);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   float totalWidth = float(totalWidthCoord) / processor.mAppUnitsPerDevPixel;
   if (aWidth) {
     *aWidth = totalWidth;
   }
@@ -3343,25 +3370,26 @@ nsCanvasRenderingContext2DAzure::DrawOrM
   }
 
   // save the previous bounding box
   gfxRect boundingBox = processor.mBoundingBox;
 
   // don't ever need to measure the bounding box twice
   processor.mDoMeasureBoundingBox = PR_FALSE;
 
-  rv = bidiUtils->ProcessText(textToDraw.get(),
-                              textToDraw.Length(),
-                              isRTL ? NSBIDI_RTL : NSBIDI_LTR,
-                              presShell->GetPresContext(),
-                              processor,
-                              nsBidiPresUtils::MODE_DRAW,
-                              nsnull,
-                              0,
-                              nsnull);
+  rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
+                                    textToDraw.Length(),
+                                    isRTL ? NSBIDI_RTL : NSBIDI_LTR,
+                                    presShell->GetPresContext(),
+                                    processor,
+                                    nsBidiPresUtils::MODE_DRAW,
+                                    nsnull,
+                                    0,
+                                    nsnull,
+                                    &bidiEngine);
 
 
   mTarget->SetTransform(oldTransform);
 
   if (aOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL && !doDrawShadow)
     return RedrawUser(boundingBox);
 
   return Redraw();
@@ -3751,17 +3779,24 @@ nsCanvasRenderingContext2DAzure::DrawIma
 
   Filter filter;
 
   if (CurrentState().imageSmoothingEnabled)
     filter = mgfx::FILTER_LINEAR;
   else
     filter = mgfx::FILTER_POINT;
 
-  AdjustedTarget(this)->
+  mgfx::Rect bounds;
+  
+  if (NeedToDrawShadow()) {
+    bounds = mgfx::Rect(dx, dy, dw, dh);
+    bounds = mTarget->GetTransform().TransformBounds(bounds);
+  }
+
+  AdjustedTarget(this, bounds.IsEmpty() ? nsnull : &bounds)->
     DrawSurface(srcSurf,
                 mgfx::Rect(dx, dy, dw, dh),
                 mgfx::Rect(sx, sy, sw, sh),
                 DrawSurfaceOptions(filter),
                 DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   return RedrawUser(gfxRect(dx, dy, dw, dh));
 }
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -21387,16 +21387,37 @@ function test_zero_dimensions_imagedata(
   var isTransparentBlack = true;
   for (var i = 0; i < imgdata.data.length; ++i)
       if (imgdata.data[i] !== 0)
           isTransparentBlack = false;
   ok(isTransparentBlack, "isTransparentBlack");
 }
 </script>
 
+<p>Canvas test: getImageData_after_zero_canvas</p>
+<canvas id="c686" width="100" height="100"></canvas>
+<script type="text/javascript">
+function test_getImageData_after_zero_canvas() {
+    var c = document.getElementById("c686");
+    var ctx = c.getContext("2d");
+    ctx.fillStyle = "rgba(0, 0, 0, 1.0)";
+    ctx.fillRect(0, 0, c.width, c.height);
+    var oldimgdata = ctx.getImageData(0, 0, c.width, c.height);
+    c.width = c.height = 0;
+    c.width = c.height = 100;
+    ctx.fillRect(0, 0, c.width, c.height);
+    var imgdata = ctx.getImageData(0, 0, c.width, c.height);
+    var same = false;
+    ok(imgdata.data.length === oldimgdata.data.length, "not the same length");
+    for (var i = 0; i < imgdata.data.length; ++i)
+        same = imgdata.data[i] === oldimgdata.data[i];
+    ok(same, "changing dimensions broke canvas");
+}
+</script>
+
 <script>
 
 function asyncTestsDone() {
 	if (isDone_test_2d_drawImage_animated_apng &&
 		isDone_test_2d_drawImage_animated_gif) {
 		SimpleTest.finish();
 	} else {
 		setTimeout(asyncTestsDone, 500);
@@ -24657,16 +24678,22 @@ function runTests() {
   ok(false, "unexpected exception thrown in: test_zero_dimensions");
  }
  try {
   test_zero_dimensions_imagedata();
  } catch(e) {
   ok(false, "unexpected exception thrown in: test_zero_dimensions_imagedata");
  }
  try {
+  test_getImageData_after_zero_canvas();
+ } catch(e) {
+  throw e;
+  ok(false, "unexpected exception thrown in: test_getImageData_after_zero_canvas");
+ }
+ try {
   // run this test last since it replaces the getContext method
   test_type_replace();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_type_replace");
  }
  
  //run the asynchronous tests
  try {
--- a/content/canvas/test/webgl/Makefile.in
+++ b/content/canvas/test/webgl/Makefile.in
@@ -51,9 +51,10 @@ include $(topsrcdir)/config/rules.mk
   failing_tests_mac.txt \
   $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 	$(TAR) -cf - -C $(srcdir) \
 	  resources \
 	  conformance \
+          crossorigin \
 	  | $(TAR) -xf - -C $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df24ac6d3404325e473981930ade85065cf7fb9a
GIT binary patch
literal 844
zc$@)D1GD^zP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000j<000lL0ajJ30{{R5?ny*JR5*=wlU-<Abr{Bf|C4iak|t@k
znyz1_UD|b9CpwyStJbl)wOETfHyJ}l1+P@RQUvu%@X{{?1uq7I;FT95IyVX`Q#a>W
zH*l4W#u<{PNz9VwG#}^W<0L1?t5qG#bM^8*@B6!Y9%v)~sZWR7dH<ET*YfDQ-@UD+
zw7tRIec8-L-Mt*iY#7<fwOXnA4VT_5w*{yN-Ve=&dp<aHa{PEAtBZKDNbK(-ZdJzT
zQE|zVCdrO>&b>bO@tq&Xo#Dw37Y`VD<Kh#CN5=CNOJw5(mJ@jtVdL&l@%vOP8+RtJ
z&-?ctbLE%5`f(HR;<r~jN?H9E>*5zZgOd|P&R*cpRtL#MfnqdAF}{lF@u3x}h-M2d
zU7YIQ_0*!aayBIc)N=ZX)vMQouRK=b_uDDdE|ux^&sgX-sRT#)>9+`tv>+u9Av<NN
zH&!Lt?|m7#A_FWft?lnDrFrzFXYnVh40Oei?E%6Er;(c#UOh3uYp1VZ$RV^?8d?IO
zDEj~*0VGy(s>c)Hp(D?+Cny*kpJ8n71zf|E=pEaMtqb<=?8Ppd$Yvc+rx&+J-U2uz
z01;V>&4(3AT8;+~%~LWAvbi!#=YJ*{T_H3YWP0WZTfGgoZNHzEaIlfcn1GN0gvI&w
zN*BH@U5I9l(LEzH^a4Bj2BEHF*LCd5I_~5-jNVg74nf&4Qh?<EFpbN})LQ@3xyYIR
zPFdqVpMu9JgK1#b%Gh-smzibpQk|8wO3N~-=l=MzS&e?b86;Qt!jxiGerS~A%I*=R
z@yu+m{`kRAU~H&cxUnde8-y2rWyAE+vdmhoa`|B>T>oDZ72o0K<(7D_Y2>a+IG1f<
z1;P(F$7ZLt?Xv8?z$c&I5RxR>Mm_V9#b0j#*4<qY;N0P0I3(fi5l8`OIrdGA%|vgd
z<`k!+naSNcZ4rM9(A$>jU)YfP$i(Ean>QmzT`s3}TZ?`T+8Lm6&oZ?KZQix+Hva+S
WQ#UA?9#7r?0000<MNUMnLSTYXW|E5l
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/crossorigin/image-allow-credentials.png^headers^
@@ -0,0 +1,2 @@
+Access-Control-Allow-Origin: http://mochi.test:8888
+Access-Control-Allow-Credentials: true
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df24ac6d3404325e473981930ade85065cf7fb9a
GIT binary patch
literal 844
zc$@)D1GD^zP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000j<000lL0ajJ30{{R5?ny*JR5*=wlU-<Abr{Bf|C4iak|t@k
znyz1_UD|b9CpwyStJbl)wOETfHyJ}l1+P@RQUvu%@X{{?1uq7I;FT95IyVX`Q#a>W
zH*l4W#u<{PNz9VwG#}^W<0L1?t5qG#bM^8*@B6!Y9%v)~sZWR7dH<ET*YfDQ-@UD+
zw7tRIec8-L-Mt*iY#7<fwOXnA4VT_5w*{yN-Ve=&dp<aHa{PEAtBZKDNbK(-ZdJzT
zQE|zVCdrO>&b>bO@tq&Xo#Dw37Y`VD<Kh#CN5=CNOJw5(mJ@jtVdL&l@%vOP8+RtJ
z&-?ctbLE%5`f(HR;<r~jN?H9E>*5zZgOd|P&R*cpRtL#MfnqdAF}{lF@u3x}h-M2d
zU7YIQ_0*!aayBIc)N=ZX)vMQouRK=b_uDDdE|ux^&sgX-sRT#)>9+`tv>+u9Av<NN
zH&!Lt?|m7#A_FWft?lnDrFrzFXYnVh40Oei?E%6Er;(c#UOh3uYp1VZ$RV^?8d?IO
zDEj~*0VGy(s>c)Hp(D?+Cny*kpJ8n71zf|E=pEaMtqb<=?8Ppd$Yvc+rx&+J-U2uz
z01;V>&4(3AT8;+~%~LWAvbi!#=YJ*{T_H3YWP0WZTfGgoZNHzEaIlfcn1GN0gvI&w
zN*BH@U5I9l(LEzH^a4Bj2BEHF*LCd5I_~5-jNVg74nf&4Qh?<EFpbN})LQ@3xyYIR
zPFdqVpMu9JgK1#b%Gh-smzibpQk|8wO3N~-=l=MzS&e?b86;Qt!jxiGerS~A%I*=R
z@yu+m{`kRAU~H&cxUnde8-y2rWyAE+vdmhoa`|B>T>oDZ72o0K<(7D_Y2>a+IG1f<
z1;P(F$7ZLt?Xv8?z$c&I5RxR>Mm_V9#b0j#*4<qY;N0P0I3(fi5l8`OIrdGA%|vgd
z<`k!+naSNcZ4rM9(A$>jU)YfP$i(Ean>QmzT`s3}TZ?`T+8Lm6&oZ?KZQix+Hva+S
WQ#UA?9#7r?0000<MNUMnLSTYXW|E5l
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/crossorigin/image-allow-star.png^headers^
@@ -0,0 +1,1 @@
+Access-Control-Allow-Origin: *
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df24ac6d3404325e473981930ade85065cf7fb9a
GIT binary patch
literal 844
zc$@)D1GD^zP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004b3#c}2nYxW
zd<bNS00009a7bBm000j<000lL0ajJ30{{R5?ny*JR5*=wlU-<Abr{Bf|C4iak|t@k
znyz1_UD|b9CpwyStJbl)wOETfHyJ}l1+P@RQUvu%@X{{?1uq7I;FT95IyVX`Q#a>W
zH*l4W#u<{PNz9VwG#}^W<0L1?t5qG#bM^8*@B6!Y9%v)~sZWR7dH<ET*YfDQ-@UD+
zw7tRIec8-L-Mt*iY#7<fwOXnA4VT_5w*{yN-Ve=&dp<aHa{PEAtBZKDNbK(-ZdJzT
zQE|zVCdrO>&b>bO@tq&Xo#Dw37Y`VD<Kh#CN5=CNOJw5(mJ@jtVdL&l@%vOP8+RtJ
z&-?ctbLE%5`f(HR;<r~jN?H9E>*5zZgOd|P&R*cpRtL#MfnqdAF}{lF@u3x}h-M2d
zU7YIQ_0*!aayBIc)N=ZX)vMQouRK=b_uDDdE|ux^&sgX-sRT#)>9+`tv>+u9Av<NN
zH&!Lt?|m7#A_FWft?lnDrFrzFXYnVh40Oei?E%6Er;(c#UOh3uYp1VZ$RV^?8d?IO
zDEj~*0VGy(s>c)Hp(D?+Cny*kpJ8n71zf|E=pEaMtqb<=?8Ppd$Yvc+rx&+J-U2uz
z01;V>&4(3AT8;+~%~LWAvbi!#=YJ*{T_H3YWP0WZTfGgoZNHzEaIlfcn1GN0gvI&w
zN*BH@U5I9l(LEzH^a4Bj2BEHF*LCd5I_~5-jNVg74nf&4Qh?<EFpbN})LQ@3xyYIR
zPFdqVpMu9JgK1#b%Gh-smzibpQk|8wO3N~-=l=MzS&e?b86;Qt!jxiGerS~A%I*=R
z@yu+m{`kRAU~H&cxUnde8-y2rWyAE+vdmhoa`|B>T>oDZ72o0K<(7D_Y2>a+IG1f<
z1;P(F$7ZLt?Xv8?z$c&I5RxR>Mm_V9#b0j#*4<qY;N0P0I3(fi5l8`OIrdGA%|vgd
z<`k!+naSNcZ4rM9(A$>jU)YfP$i(Ean>QmzT`s3}TZ?`T+8Lm6&oZ?KZQix+Hva+S
WQ#UA?9#7r?0000<MNUMnLSTYXW|E5l
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/crossorigin/test_webgl_crossorigin_textures.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML>
+<title>WebGL cross-origin textures test</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="canvas" style="border: none;" width="100" height="100">
+  <p class="fallback"> FAIL (fallback content) </p>
+</canvas>
+<script>
+
+  SimpleTest.waitForExplicitFinish();
+
+  const SECURITY_ERR = 0x805303e8;
+  const OK = 0;
+
+  var gl;
+  var number_of_tests_live = 0;
+  var all_tests_started = false;
+
+  function nameForErrorCode(code) {
+    switch(code) {
+      case OK: return "no error";
+      case SECURITY_ERR: return "security error";
+    }
+    return "unexpected error (" + code + ")";
+  }
+
+  function verifyError(actual_error, expected_error, message) {
+    ok(actual_error == expected_error,
+       message + ": expected " + nameForErrorCode(expected_error)
+               + ", got " + nameForErrorCode(actual_error));
+  }
+
+  function testTexture(url, crossOriginAttribute, expected_result) {
+    number_of_tests_live++;
+    var image = new Image();
+    if (crossOriginAttribute != "leave-default-crossOrigin-attribute")
+      image.crossOrigin = crossOriginAttribute;
+
+    function testDone() {
+      number_of_tests_live--;
+        
+      if (number_of_tests_live == 0 && all_tests_started)
+        SimpleTest.finish();
+    }
+
+    image.onload = function() {
+      var tex = gl.createTexture();
+      gl.bindTexture(gl.TEXTURE_2D, tex);
+      var actual_result = OK;
+      try {
+        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+      } catch(e) {
+        actual_result = e.result;
+      }
+      verifyError(actual_result, expected_result, "texImage2D on " + url + " with crossOrigin=" + image.crossOrigin);
+
+      testDone();
+    };
+
+    image.onerror = function(event) {
+      ok(expected_result != OK, "Got an error but expected OK!");
+
+      testDone();
+    }
+
+    image.src = url;
+  }
+
+  MochiKit.DOM.addLoadEvent(function () {
+    var canvas = document.getElementById("canvas");
+    try {
+      gl = canvas.getContext("experimental-webgl");
+    } catch (e) {
+      SimpleTest.finish();
+      return;
+    }
+
+    testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "leave-default-crossOrigin-attribute",
+                OK);
+
+    testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "",
+                OK);
+
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "leave-default-crossOrigin-attribute",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "",
+                SECURITY_ERR);
+
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
+                "leave-default-crossOrigin-attribute",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
+                "",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
+                "anonymous",
+                OK);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
+                "use-credentials",
+                SECURITY_ERR);
+
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
+                "leave-default-crossOrigin-attribute",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
+                "",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
+                "anonymous",
+                OK);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
+                "use-credentials",
+                OK);
+
+    // Test that bad values for crossorigin="..." are interpreted as default.
+    testTexture("http://mochi.test:8888/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "foobar",
+                OK);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image.png",
+                "foobar",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-star.png",
+                "foobar",
+                SECURITY_ERR);
+    testTexture("http://example.com/tests/content/canvas/test/webgl/crossorigin/image-allow-credentials.png",
+                "foobar",
+                SECURITY_ERR);
+
+    all_tests_started = true;
+  });
+</script>
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -38,17 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "base/basictypes.h"
 #include "IPC/IPCMessageUtils.h"
 #include "nsCOMPtr.h"
 #include "nsDOMUIEvent.h"
 #include "nsIPresShell.h"
 #include "nsIInterfaceRequestorUtils.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIDOMNode.h"
 #include "nsIContent.h"
 #include "nsContentUtils.h"
 #include "nsEventStateManager.h"
 #include "nsIFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsIScrollableFrame.h"
 
@@ -90,17 +90,17 @@ nsDOMUIEvent::nsDOMUIEvent(nsPresContext
   }
 
   mView = nsnull;
   if (mPresContext)
   {
     nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
     if (container)
     {
-       nsCOMPtr<nsIDOMWindowInternal> window = do_GetInterface(container);
+       nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
        if (window)
           mView = do_QueryInterface(window);
     }
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMUIEvent)
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -60,37 +60,24 @@
 #include "nsIPresShell.h"
 #include "nsDOMEvent.h"
 #include "nsGkAtoms.h"
 #include "nsIEditorDocShell.h"
 #include "nsIFormControl.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIScrollableFrame.h"
 #include "nsIDOMNSHTMLElement.h"
-#include "nsIDOMHTMLAnchorElement.h"
-#include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLLabelElement.h"
-#include "nsIDOMHTMLSelectElement.h"
-#include "nsIDOMHTMLTextAreaElement.h"
-#include "nsIDOMHTMLAreaElement.h"
-#include "nsIDOMHTMLButtonElement.h"
-#include "nsIDOMHTMLObjectElement.h"
-#include "nsIDOMHTMLImageElement.h"
-#include "nsIDOMHTMLMapElement.h"
-#include "nsIDOMHTMLBodyElement.h"
 #include "nsIDOMXULControlElement.h"
-#include "nsIDOMXULTextboxElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsIBaseWindow.h"
 #include "nsIView.h"
 #include "nsIViewManager.h"
 #include "nsISelection.h"
 #include "nsFrameSelection.h"
 #include "nsIPrivateDOMEvent.h"
-#include "nsIDOMWindowInternal.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsIEnumerator.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeNode.h"
 #include "nsIWebNavigation.h"
 #include "nsIContentViewer.h"
 #ifdef MOZ_XUL
@@ -111,17 +98,16 @@
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIDOMMouseScrollEvent.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsDOMDragEvent.h"
 #include "nsIDOMNSEditableElement.h"
 
-#include "nsIDOMRange.h"
 #include "nsCaret.h"
 #include "nsILookAndFeel.h"
 #include "nsWidgetsCID.h"
 
 #include "nsSubDocumentFrame.h"
 #include "nsIFrameTraversal.h"
 #include "nsLayoutCID.h"
 #include "nsLayoutUtils.h"
@@ -213,17 +199,17 @@ PrintDocTree(nsIDocShellTreeItem* aParen
   nsRefPtr<nsPresContext> presContext;
   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
   nsCOMPtr<nsIContentViewer> cv;
   parentAsDocShell->GetContentViewer(getter_AddRefs(cv));
   nsCOMPtr<nsIDOMDocument> domDoc;
   if (cv)
     cv->GetDOMDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
-  nsCOMPtr<nsIDOMWindowInternal> domwin = doc ? doc->GetWindow() : nsnull;
+  nsCOMPtr<nsIDOMWindow> domwin = doc ? doc->GetWindow() : nsnull;
   nsIURI* uri = doc ? doc->GetDocumentURI() : nsnull;
 
   printf("DS %p  Type %s  Cnt %d  Doc %p  DW %p  EM %p%c",
     static_cast<void*>(parentAsDocShell.get()),
     type==nsIDocShellTreeItem::typeChrome?"Chrome":"Content",
     childWebshellCount, static_cast<void*>(doc.get()),
     static_cast<void*>(domwin.get()),
     static_cast<void*>(presContext ? presContext->EventStateManager() : nsnull),
@@ -1207,52 +1193,17 @@ nsEventStateManager::PreHandleEvent(nsPr
   case NS_MOUSE_SCROLL:
     {
       nsIContent* content = GetFocusedContent();
       if (content)
         mCurrentTargetContent = content;
 
       nsMouseScrollEvent* msEvent = static_cast<nsMouseScrollEvent*>(aEvent);
 
-      PRBool useSysNumLines = UseSystemScrollSettingFor(msEvent);
-      PRInt32 action = GetWheelActionFor(msEvent);
-
-      if (!useSysNumLines) {
-        // If the scroll event's delta isn't to our liking, we can
-        // override it with the "numlines" parameter.  There are two
-        // things we can do:
-        //
-        // (1) Pick a different number.  Instead of scrolling 3
-        //     lines ("delta" in Gtk2), we would scroll 1 line.
-        // (2) Swap directions.  Instead of scrolling down, scroll up.
-        //
-        // For the first item, the magnitude of the parameter is
-        // used instead of the magnitude of the delta.  For the
-        // second item, if the parameter is negative we swap
-        // directions.
-
-        PRInt32 numLines = GetScrollLinesFor(msEvent);
-
-        PRBool swapDirs = (numLines < 0);
-        PRInt32 userSize = swapDirs ? -numLines : numLines;
-
-        PRBool deltaUp = (msEvent->delta < 0);
-        if (swapDirs) {
-          deltaUp = !deltaUp;
-        }
-
-        msEvent->delta = deltaUp ? -userSize : userSize;
-      }
-      if ((useSysNumLines &&
-           (msEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage)) ||
-          action == MOUSE_SCROLL_PAGE) {
-          msEvent->delta = (msEvent->delta > 0)
-            ? PRInt32(nsIDOMNSUIEvent::SCROLL_PAGE_DOWN)
-            : PRInt32(nsIDOMNSUIEvent::SCROLL_PAGE_UP);
-      }
+      msEvent->delta = ComputeWheelDeltaFor(msEvent);
     }
     break;
   case NS_MOUSE_PIXEL_SCROLL:
     {
       nsIContent* content = GetFocusedContent();
       if (content)
         mCurrentTargetContent = content;
 
@@ -2416,17 +2367,17 @@ nsEventStateManager::GetMarkupDocumentVi
   if(!fm) return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMWindow> focusedWindow;
   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
 
   nsCOMPtr<nsPIDOMWindow> ourWindow = do_QueryInterface(focusedWindow);
   if(!ourWindow) return NS_ERROR_FAILURE;
 
-  nsIDOMWindowInternal *rootWindow = ourWindow->GetPrivateRoot();
+  nsIDOMWindow *rootWindow = ourWindow->GetPrivateRoot();
   if(!rootWindow) return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIDOMWindow> contentWindow;
   rootWindow->GetContent(getter_AddRefs(contentWindow));
   if(!contentWindow) return NS_ERROR_FAILURE;
 
   nsIDocument *doc = GetDocumentFromWindow(contentWindow);
   if(!doc) return NS_ERROR_FAILURE;
@@ -2630,16 +2581,55 @@ nsEventStateManager::SendPixelScrollEven
   event.scrollFlags = aEvent->scrollFlags;
   event.inputSource = static_cast<nsMouseEvent_base*>(aEvent)->inputSource;
   event.delta = aPresContext->AppUnitsToIntCSSPixels(aEvent->delta * lineHeight);
 
   nsEventDispatcher::Dispatch(targetContent, aPresContext, &event, nsnull, aStatus);
 }
 
 PRInt32
+nsEventStateManager::ComputeWheelDeltaFor(nsMouseScrollEvent* aMouseEvent)
+{
+  PRInt32 delta = aMouseEvent->delta;
+  PRBool useSysNumLines = UseSystemScrollSettingFor(aMouseEvent);
+  if (!useSysNumLines) {
+    // If the scroll event's delta isn't to our liking, we can
+    // override it with the "numlines" parameter.  There are two
+    // things we can do:
+    //
+    // (1) Pick a different number.  Instead of scrolling 3
+    //     lines ("delta" in Gtk2), we would scroll 1 line.
+    // (2) Swap directions.  Instead of scrolling down, scroll up.
+    //
+    // For the first item, the magnitude of the parameter is
+    // used instead of the magnitude of the delta.  For the
+    // second item, if the parameter is negative we swap
+    // directions.
+
+    PRInt32 numLines = GetScrollLinesFor(aMouseEvent);
+
+    PRBool swapDirs = (numLines < 0);
+    PRInt32 userSize = swapDirs ? -numLines : numLines;
+
+    PRBool deltaUp = (delta < 0);
+    if (swapDirs) {
+      deltaUp = !deltaUp;
+    }
+    delta = deltaUp ? -userSize : userSize;
+  }
+
+  if (ComputeWheelActionFor(aMouseEvent, useSysNumLines) == MOUSE_SCROLL_PAGE) {
+    delta = (delta > 0) ? PRInt32(nsIDOMNSUIEvent::SCROLL_PAGE_DOWN) :
+                          PRInt32(nsIDOMNSUIEvent::SCROLL_PAGE_UP);
+  }
+
+  return delta;
+}
+
+PRInt32
 nsEventStateManager::ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent,
                                            PRBool aUseSystemSettings)
 {
   PRInt32 action = GetWheelActionFor(aMouseEvent);
   if (aUseSystemSettings &&
       (aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsFullPage)) {
     action = MOUSE_SCROLL_PAGE;
   }
@@ -2814,16 +2804,31 @@ nsEventStateManager::DoScrollText(nsIFra
         frameToScroll->GetPageScrollAmount().height / appUnitsPerDevPixel;
       aQueryEvent->mReply.mPageWidth =
         frameToScroll->GetPageScrollAmount().width / appUnitsPerDevPixel;
 
       // Returns computed numLines to widget which is needed to compute the
       // pixel scrolling amout for high resolution scrolling.
       aQueryEvent->mReply.mComputedScrollAmount = numLines;
 
+      switch (aScrollQuantity) {
+        case nsIScrollableFrame::LINES:
+          aQueryEvent->mReply.mComputedScrollAction =
+            nsQueryContentEvent::SCROLL_ACTION_LINE;
+          break;
+        case nsIScrollableFrame::PAGES:
+          aQueryEvent->mReply.mComputedScrollAction =
+            nsQueryContentEvent::SCROLL_ACTION_PAGE;
+          break;
+        default:
+          aQueryEvent->mReply.mComputedScrollAction =
+            nsQueryContentEvent::SCROLL_ACTION_NONE;
+          break;
+      }
+
       aQueryEvent->mSucceeded = PR_TRUE;
       return NS_OK;
     }
 
     PRInt32 scrollX = 0;
     PRInt32 scrollY = numLines;
 
     if (isHorizontal) {
@@ -4762,45 +4767,51 @@ nsEventStateManager::DoContentCommandScr
   sf->ScrollBy(pt, scrollUnit, nsIScrollableFrame::INSTANT);
   return NS_OK;
 }
 
 void
 nsEventStateManager::DoQueryScrollTargetInfo(nsQueryContentEvent* aEvent,
                                              nsIFrame* aTargetFrame)
 {
-  nsMouseScrollEvent* msEvent = aEvent->mInput.mMouseScrollEvent;
-
-  // Don't use high resolution scrolling when user customize the scrolling
-  // speed.
-  if (!UseSystemScrollSettingFor(msEvent)) {
-    return;
-  }
+  // Don't modify the test event which in mInput.
+  nsMouseScrollEvent msEvent(
+    NS_IS_TRUSTED_EVENT(aEvent->mInput.mMouseScrollEvent),
+    aEvent->mInput.mMouseScrollEvent->message,
+    aEvent->mInput.mMouseScrollEvent->widget);
+
+  msEvent.isShift = aEvent->mInput.mMouseScrollEvent->isShift;
+  msEvent.isControl = aEvent->mInput.mMouseScrollEvent->isControl;
+  msEvent.isAlt = aEvent->mInput.mMouseScrollEvent->isAlt;
+  msEvent.isMeta = aEvent->mInput.mMouseScrollEvent->isMeta;
+
+  msEvent.scrollFlags = aEvent->mInput.mMouseScrollEvent->scrollFlags;
+  msEvent.delta = ComputeWheelDeltaFor(aEvent->mInput.mMouseScrollEvent);
+  msEvent.scrollOverflow = aEvent->mInput.mMouseScrollEvent->scrollOverflow;
+
+  PRBool useSystemSettings = UseSystemScrollSettingFor(&msEvent);
 
   nsIScrollableFrame::ScrollUnit unit;
   PRBool allowOverrideSystemSettings;
-  switch (ComputeWheelActionFor(msEvent, PR_TRUE)) {
+  switch (ComputeWheelActionFor(&msEvent, useSystemSettings)) {
     case MOUSE_SCROLL_N_LINES:
       unit = nsIScrollableFrame::LINES;
-      allowOverrideSystemSettings = PR_TRUE;
+      allowOverrideSystemSettings = useSystemSettings;
       break;
     case MOUSE_SCROLL_PAGE:
       unit = nsIScrollableFrame::PAGES;
       allowOverrideSystemSettings = PR_FALSE;
       break;
-    case MOUSE_SCROLL_PIXELS:
-      unit = nsIScrollableFrame::DEVICE_PIXELS;
-      allowOverrideSystemSettings = PR_FALSE;
     default:
       // Don't use high resolution scrolling when the action doesn't scroll
       // contents.
       return;
   }
 
-  DoScrollText(aTargetFrame, msEvent, unit,
+  DoScrollText(aTargetFrame, &msEvent, unit,
                allowOverrideSystemSettings, aEvent);
 }
 
 void
 nsEventStateManager::SetActiveManager(nsEventStateManager* aNewESM,
                                       nsIContent* aContent)
 {
   if (sActiveESM && aNewESM != sActiveESM) {
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -326,16 +326,22 @@ protected:
                         PRBool aAllowScrollSpeedOverride,
                         nsQueryContentEvent* aQueryEvent = nsnull);
   void DoScrollHistory(PRInt32 direction);
   void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
   nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
   nsresult ChangeTextSize(PRInt32 change);
   nsresult ChangeFullZoom(PRInt32 change);
   /**
+   * Computes actual delta value used for scrolling.  If user customized the
+   * scrolling speed and/or direction, this would return the customized value.
+   * Otherwise, it would return the original delta value of aMouseEvent.
+   */
+  PRInt32 ComputeWheelDeltaFor(nsMouseScrollEvent* aMouseEvent);
+  /**
    * Computes the action for the aMouseEvent with prefs.  The result is
    * MOUSE_SCROLL_N_LINES, MOUSE_SCROLL_PAGE, MOUSE_SCROLL_HISTORY,
    * MOUSE_SCROLL_ZOOM, MOUSE_SCROLL_PIXELS or -1.
    * When the result is -1, nothing happens for the event.
    *
    * @param aUseSystemSettings    Set the result of UseSystemScrollSettingFor().
    */
   PRInt32 ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent,
--- a/content/html/content/public/nsIFormSubmitObserver.idl
+++ b/content/html/content/public/nsIFormSubmitObserver.idl
@@ -36,24 +36,24 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsISupports.idl"
 
 interface nsIDOMHTMLFormElement;
-interface nsIDOMWindowInternal;
+interface nsIDOMWindow;
 interface nsIURI;
 interface nsIArray;
 
-[scriptable, uuid(0b3cc84d-25d2-448e-ae71-746ee6e41c2d)]
+[scriptable, uuid(534ab795-6a99-4195-bfab-cfdd7836657d)]
 interface nsIFormSubmitObserver: nsISupports
 {
-  void notify(in nsIDOMHTMLFormElement formNode, in nsIDOMWindowInternal window, in nsIURI actionURL, out boolean cancelSubmit);
+  void notify(in nsIDOMHTMLFormElement formNode, in nsIDOMWindow window, in nsIURI actionURL, out boolean cancelSubmit);
 
   void notifyInvalidSubmit(in nsIDOMHTMLFormElement formNode,
                            in nsIArray invalidElements);
 };
 
 %{C++
 #define NS_FORMSUBMIT_SUBJECT "formsubmit"
 #define NS_EARLYFORMSUBMIT_SUBJECT "earlyformsubmit"
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -40,17 +40,16 @@
 #include "nsImageLoadingContent.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsMappedAttributes.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsSize.h"
 #include "nsIDocument.h"
-#include "nsIDOMWindowInternal.h"
 #include "nsIDOMDocument.h"
 #include "nsIScriptContext.h"
 #include "nsIURL.h"
 #include "nsIIOService.h"
 #include "nsIServiceManager.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsIFrame.h"
@@ -103,16 +102,19 @@ public:
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLImageElement
   NS_DECL_NSIDOMHTMLIMAGEELEMENT
 
   // override from nsGenericHTMLElement
   NS_IMETHOD GetDraggable(PRBool* aDraggable);
 
+  // override from nsImageLoadingContent
+  nsImageLoadingContent::CORSMode GetCORSMode();
+
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
                         JSObject* aObj, PRUint32 argc, jsval* argv);
 
   // nsIContent
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
@@ -220,16 +222,27 @@ NS_IMPL_STRING_ATTR(nsHTMLImageElement, 
 NS_IMPL_INT_ATTR(nsHTMLImageElement, Hspace, hspace)
 NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap)
 NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc)
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc)
 NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src)
 NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap)
 NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace)
 
+static const nsAttrValue::EnumTable kCrossOriginTable[] = {
+  { "",                nsImageLoadingContent::CORS_NONE },
+  { "anonymous",       nsImageLoadingContent::CORS_ANONYMOUS },
+  { "use-credentials", nsImageLoadingContent::CORS_USE_CREDENTIALS },
+  { 0 }
+};
+// Default crossOrigin mode is CORS_NONE.
+static const nsAttrValue::EnumTable* kCrossOriginDefault = &kCrossOriginTable[0];
+
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLImageElement, CrossOrigin, crossorigin, kCrossOriginDefault->tag)
+
 NS_IMETHODIMP
 nsHTMLImageElement::GetDraggable(PRBool* aDraggable)
 {
   // images may be dragged unless the draggable attribute is false
   *aDraggable = !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
                              nsGkAtoms::_false, eIgnoreCase);
   return NS_OK;
 }
@@ -333,16 +346,19 @@ nsHTMLImageElement::ParseAttribute(PRInt
                                    nsIAtom* aAttribute,
                                    const nsAString& aValue,
                                    nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
+    if (aAttribute == nsGkAtoms::crossorigin) {
+      return aResult.ParseEnumValue(aValue, kCrossOriginTable, PR_FALSE);
+    }
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return PR_TRUE;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
@@ -628,8 +644,21 @@ nsHTMLImageElement::GetNaturalWidth(PRUi
 nsresult
 nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const
 {
   if (aDest->GetOwnerDoc()->IsStaticDocument()) {
     CreateStaticImageClone(static_cast<nsHTMLImageElement*>(aDest));
   }
   return nsGenericHTMLElement::CopyInnerTo(aDest);
 }
+
+nsImageLoadingContent::CORSMode
+nsHTMLImageElement::GetCORSMode()
+{
+  nsImageLoadingContent::CORSMode ret = nsImageLoadingContent::CORS_NONE;
+
+  const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin);
+  if (value && value->Type() == nsAttrValue::eEnum) {
+    ret = (nsImageLoadingContent::CORSMode) value->GetEnumValue();
+  }
+
+  return ret;
+}
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -32,16 +32,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "nsHTMLInputElement.h"
+
 #include "nsIDOMHTMLInputElement.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIPhonetic.h"
 
 #include "nsIControllers.h"
 #include "nsFocusManager.h"
@@ -106,32 +108,29 @@
 #include "nsIContentURIGrouper.h"
 #include "nsIContentPrefService.h"
 #include "nsIObserverService.h"
 #include "nsIPopupWindowManager.h"
 #include "nsGlobalWindow.h"
 
 // input type=image
 #include "nsImageLoadingContent.h"
-#include "nsIDOMWindowInternal.h"
 
 #include "mozAutoDocUpdate.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsRadioVisitor.h"
 
 #include "nsTextEditRules.h"
 
 // JS headers are needed for the pattern attribute.
 #include "jsapi.h"
 #include "jscntxt.h"
 
-#include "nsHTMLInputElement.h"
-
 using namespace mozilla::dom;
 
 // XXX align=left, hspace, vspace, border? other nav4 attrs
 
 static NS_DEFINE_CID(kXULControllersCID,  NS_XULCONTROLLERS_CID);
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 
 // First bits are needed for the control type.
@@ -263,17 +262,17 @@ protected:
   PopupControlState mPopupControlState;
 };
 
 NS_IMETHODIMP
 AsyncClickHandler::Run()
 {
   nsresult rv;
 
-  // Get parent nsIDOMWindowInternal object.
+  // Get parent nsPIDOMWindow object.
   nsCOMPtr<nsIDocument> doc = mInput->GetOwnerDoc();
   if (!doc)
     return NS_ERROR_FAILURE;
 
   nsPIDOMWindow* win = doc->GetWindow();
   if (!win) {
     return NS_ERROR_FAILURE;
   }
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -394,17 +394,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsHTMLMediaElement)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
 
 // nsIDOMHTMLMediaElement
 NS_IMPL_URI_ATTR(nsHTMLMediaElement, Src, src)
 NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Controls, controls)
 NS_IMPL_BOOL_ATTR(nsHTMLMediaElement, Autoplay, autoplay)
-NS_IMPL_STRING_ATTR(nsHTMLMediaElement, Preload, preload)
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLMediaElement, Preload, preload, NULL)
 
 /* readonly attribute nsIDOMHTMLMediaElement mozAutoplayEnabled; */
 NS_IMETHODIMP nsHTMLMediaElement::GetMozAutoplayEnabled(PRBool *aAutoplayEnabled)
 {
   *aAutoplayEnabled = mAutoplayEnabled;
 
   return NS_OK;
 }
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -263,19 +263,21 @@ include $(topsrcdir)/config/rules.mk
 		test_bug636336.html \
 		test_bug610212.html \
 		test_bug633058.html \
 		test_bug641219.html \
 		test_bug643051.html \
 		test_bug583514.html \
 		test_bug514437.html \
 		test_bug560112.html \
+		test_bug586786.html \
 		test_bug649134.html \
 		test_bug658746.html \
 		test_bug659596.html \
 		test_bug659743.xml \
 		test_bug660663.html \
-		test_bug586786.html \
+		test_bug664299.html \
+		test_bug666666.html \
 		test_restore_from_parser_fragment.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug664299.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=664299
+-->
+<head>
+  <title>Test for Bug 664299</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="reflect.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=664299">Mozilla Bug 664299</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test to ensure we reflect <img crossorigin> correctly **/
+reflectLimitedEnumerated({
+  element: new Image(),
+  attribute: "crossOrigin",
+  validValues: [ "", "anonymous", "use-credentials" ],
+  invalidValues: [ "foobar" ],
+  defaultValue: "" });
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug666666.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=666666
+-->
+<head>
+  <title>Test for Bug 666666</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="reflect.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666666">Mozilla Bug 666666</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 666666 **/
+["audio", "video"].forEach(function(element) {
+  reflectLimitedEnumerated({
+    element: document.createElement(element),
+    attribute: "preload",
+    validValues: ["none", "metadata", "auto"],
+    invalidValues: ["cheesecake", ""]
+  });
+});
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1523,17 +1523,17 @@ nsHTMLDocument::Open(const nsAString& aC
                      JSContext* cx, PRUint8 aOptionalArgCount,
                      nsISupports** aReturn)
 {
   NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
                "XOW should have caught this!");
 
   // When called with 3 or more arguments, document.open() calls window.open().
   if (aOptionalArgCount > 2) {
-    nsCOMPtr<nsIDOMWindowInternal> window = GetWindowInternal();
+    nsCOMPtr<nsIDOMWindow> window = GetWindowInternal();
     if (!window) {
       return NS_OK;
     }
     nsCOMPtr<nsIDOMWindow> newWindow;
     nsresult rv = window->Open(aContentTypeOrUrl, aReplaceOrName, aFeatures,
                                getter_AddRefs(newWindow));
     *aReturn = newWindow.forget().get();
     return rv;
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -934,17 +934,17 @@ nsOggReader::IndexedSeekResult nsOggRead
 }
 
 nsresult nsOggReader::SeekInBufferedRange(PRInt64 aTarget,
                                           PRInt64 aStartTime,
                                           PRInt64 aEndTime,
                                           const nsTArray<SeekRange>& aRanges,
                                           const SeekRange& aRange)
 {
-  LOG(PR_LOG_DEBUG, ("%p Seeking in buffered data to %lldms using bisection search", mDecoder, aTarget));
+  LOG(PR_LOG_DEBUG, ("%p Seeking in buffered data to %lld using bisection search", mDecoder, aTarget));
 
   // We know the exact byte range in which the target must lie. It must
   // be buffered in the media cache. Seek there.
   nsresult res = SeekBisection(aTarget, aRange, 0);
   if (NS_FAILED(res) || !HasVideo()) {
     return res;
   }
 
@@ -978,33 +978,22 @@ nsresult nsOggReader::SeekInBufferedRang
                                   aStartTime,
                                   aEndTime,
                                   PR_FALSE);
     res = SeekBisection(keyframeTime, k, SEEK_FUZZ_USECS);
   }
   return res;
 }
 
-PRBool nsOggReader::CanDecodeToTarget(PRInt64 aTarget,
-                                      PRInt64 aCurrentTime)
-{
-  // We can decode to the target if the target is no further than the
-  // maximum keyframe offset ahead of the current playback position, if
-  // we have video, or SEEK_DECODE_MARGIN if we don't have video.
-  PRInt64 margin = HasVideo() ? mTheoraState->MaxKeyframeOffset() : SEEK_DECODE_MARGIN;
-  return aTarget >= aCurrentTime &&
-         aTarget - aCurrentTime < margin;
-}
-
 nsresult nsOggReader::SeekInUnbuffered(PRInt64 aTarget,
                                        PRInt64 aStartTime,
                                        PRInt64 aEndTime,
                                        const nsTArray<SeekRange>& aRanges)
 {
-  LOG(PR_LOG_DEBUG, ("%p Seeking in unbuffered data to %lldms using bisection search", mDecoder, aTarget));
+  LOG(PR_LOG_DEBUG, ("%p Seeking in unbuffered data to %lld using bisection search", mDecoder, aTarget));
   
   // If we've got an active Theora bitstream, determine the maximum possible
   // time in usecs which a keyframe could be before a given interframe. We
   // subtract this from our seek target, seek to the new target, and then
   // will decode forward to the original seek target. We should encounter a
   // keyframe in that interval. This prevents us from needing to run two
   // bisections; one for the seek target frame, and another to find its
   // keyframe. It's usually faster to just download this extra data, rather
@@ -1025,17 +1014,17 @@ nsresult nsOggReader::SeekInUnbuffered(P
 }
 
 nsresult nsOggReader::Seek(PRInt64 aTarget,
                            PRInt64 aStartTime,
                            PRInt64 aEndTime,
                            PRInt64 aCurrentTime)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
-  LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mDecoder, aTarget));
+  LOG(PR_LOG_DEBUG, ("%p About to seek to %lld", mDecoder, aTarget));
   nsresult res;
   nsMediaStream* stream = mDecoder->GetCurrentStream();
   NS_ENSURE_TRUE(stream != nsnull, NS_ERROR_FAILURE);
 
   if (aTarget == aStartTime) {
     // We've seeked to the media start. Just seek to the offset of the first
     // content page.
     res = stream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
@@ -1045,19 +1034,16 @@ nsresult nsOggReader::Seek(PRInt64 aTarg
     res = ResetDecode();
     NS_ENSURE_SUCCESS(res,res);
 
     NS_ASSERTION(aStartTime != -1, "mStartTime should be known");
     {
       ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
       mDecoder->UpdatePlaybackPosition(aStartTime);
     }
-  } else if (CanDecodeToTarget(aTarget, aCurrentTime)) {
-    LOG(PR_LOG_DEBUG, ("%p Seek target (%lld) is close to current time (%lld), "
-        "will just decode to it", mDecoder, aCurrentTime, aTarget));
   } else {
     IndexedSeekResult sres = SeekToKeyframeUsingIndex(aTarget);
     NS_ENSURE_TRUE(sres != SEEK_FATAL_ERROR, NS_ERROR_FAILURE);
     if (sres == SEEK_INDEX_FAIL) {
       // No index or other non-fatal index-related failure. Try to seek
       // using a bisection search. Determine the already downloaded data
       // in the media cache, so we can try to seek in the cached data first.
       nsAutoTArray<SeekRange, 16> ranges;
@@ -1376,17 +1362,17 @@ nsresult nsOggReader::SeekBisection(PRIn
       NS_ENSURE_SUCCESS(res,res);
       mPageOffset = startOffset;
       if (NS_FAILED(ResetDecode())) {
         return NS_ERROR_FAILURE;
       }
       break;
     }
 
-    SEEK_LOG(PR_LOG_DEBUG, ("Time at offset %lld is %lldms", guess, granuleTime));
+    SEEK_LOG(PR_LOG_DEBUG, ("Time at offset %lld is %lld", guess, granuleTime));
     if (granuleTime < seekTarget && granuleTime > seekLowerBound) {
       // We're within the fuzzy region in which we want to terminate the search.
       res = stream->Seek(nsISeekableStream::NS_SEEK_SET, pageOffset);
       NS_ENSURE_SUCCESS(res,res);
       mPageOffset = pageOffset;
       if (NS_FAILED(ResetDecode())) {
         return NS_ERROR_FAILURE;
       }
@@ -1396,17 +1382,18 @@ nsresult nsOggReader::SeekBisection(PRIn
 
     if (granuleTime >= seekTarget) {
       // We've landed after the seek target.
       NS_ASSERTION(pageOffset < endOffset, "offset_end must decrease");
       endOffset = pageOffset;
       endTime = granuleTime;
     } else if (granuleTime < seekTarget) {
       // Landed before seek target.
-      NS_ASSERTION(pageOffset > startOffset, "offset_start must increase");
+      NS_ASSERTION(pageOffset >= startOffset + startLength,
+        "Bisection point should be at or after end of first page in interval");
       startOffset = pageOffset;
       startLength = pageLength;
       startTime = granuleTime;
     }
     NS_ASSERTION(startTime < seekTarget, "Must be before seek target");
     NS_ASSERTION(endTime >= seekTarget, "End must be after seek target");
   }
 
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -84,23 +84,16 @@ public:
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
 private:
 
   PRBool HasSkeleton() {
     return mSkeletonState != 0 && mSkeletonState->mActive;
   }
 
-  // Returns PR_TRUE if we should decode up to the seek target rather than
-  // seeking to the target using a bisection search or index-assisted seek.
-  // We should do this if the seek target (aTarget, in usecs), lies not too far
-  // ahead of the current playback position (aCurrentTime, in usecs).
-  PRBool CanDecodeToTarget(PRInt64 aTarget,
-                           PRInt64 aCurrentTime);
-
   // Seeks to the keyframe preceeding the target time using available
   // keyframe indexes.
   enum IndexedSeekResult {
     SEEK_OK,          // Success.
     SEEK_INDEX_FAIL,  // Failure due to no index, or invalid index.
     SEEK_FATAL_ERROR  // Error returned by a stream operation.
   };
   IndexedSeekResult SeekToKeyframeUsingIndex(PRInt64 aTarget);
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -745,41 +745,29 @@ PRBool nsWebMReader::DecodeVideoFrame(PR
         "Expect only 1 frame per chunk per packet in WebM...");
       mVideoQueue.Push(v);
     }
   }
 
   return PR_TRUE;
 }
 
-PRBool nsWebMReader::CanDecodeToTarget(PRInt64 aTarget,
-                                       PRInt64 aCurrentTime)
-{
-  return aTarget >= aCurrentTime &&
-         aTarget - aCurrentTime < SEEK_DECODE_MARGIN;
-}
-
 nsresult nsWebMReader::Seek(PRInt64 aTarget, PRInt64 aStartTime, PRInt64 aEndTime,
                             PRInt64 aCurrentTime)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   LOG(PR_LOG_DEBUG, ("%p About to seek to %lldms", mDecoder, aTarget));
-  if (CanDecodeToTarget(aTarget, aCurrentTime)) {
-    LOG(PR_LOG_DEBUG, ("%p Seek target (%lld) is close to current time (%lld), "
-                       "will just decode to it", mDecoder, aCurrentTime, aTarget));
-  } else {
-    if (NS_FAILED(ResetDecode())) {
-      return NS_ERROR_FAILURE;
-    }
-    PRUint32 trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
-    int r = nestegg_track_seek(mContext, trackToSeek, aTarget * NS_PER_USEC);
-    if (r != 0) {
-      return NS_ERROR_FAILURE;
-    }
+  if (NS_FAILED(ResetDecode())) {
+    return NS_ERROR_FAILURE;
+  }
+  PRUint32 trackToSeek = mHasVideo ? mVideoTrack : mAudioTrack;
+  int r = nestegg_track_seek(mContext, trackToSeek, aTarget * NS_PER_USEC);
+  if (r != 0) {
+    return NS_ERROR_FAILURE;
   }
   return DecodeToTarget(aTarget);
 }
 
 nsresult nsWebMReader::GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime)
 {
   nsMediaStream* stream = mDecoder->GetCurrentStream();
 
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -185,22 +185,16 @@ private:
   // must be held during this call. This function will free the packet
   // so the caller must not use the packet after calling.
   PRBool DecodeAudioPacket(nestegg_packet* aPacket, PRInt64 aOffset);
 
   // Release context and set to null. Called when an error occurs during
   // reading metadata or destruction of the reader itself.
   void Cleanup();
 
-  // Returns PR_TRUE if we should decode up to the seek target rather than
-  // seeking to the target using an index-assisted seek.  We should do this
-  // if the seek target (aTarget, in usecs), lies not too far ahead of the
-  // current playback position (aCurrentTime, in usecs).
-  PRBool CanDecodeToTarget(PRInt64 aTarget, PRInt64 aCurrentTime);
-
 private:
   // libnestegg context for webm container. Access on state machine thread
   // or decoder thread only.
   nestegg* mContext;
 
   // VP8 decoder state
   vpx_codec_ctx_t  mVP8;
 
--- a/content/smil/nsDOMTimeEvent.cpp
+++ b/content/smil/nsDOMTimeEvent.cpp
@@ -57,17 +57,17 @@ nsDOMTimeEvent::nsDOMTimeEvent(nsPresCon
   }
 
   mEvent->flags |= NS_EVENT_FLAG_CANT_BUBBLE |
                    NS_EVENT_FLAG_CANT_CANCEL;
 
   if (mPresContext) {
     nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
     if (container) {
-      nsCOMPtr<nsIDOMWindowInternal> window = do_GetInterface(container);
+      nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
       if (window) {
         mView = do_QueryInterface(window);
       }
     }
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTimeEvent)
--- a/content/smil/nsSMILParserUtils.cpp
+++ b/content/smil/nsSMILParserUtils.cpp
@@ -309,19 +309,17 @@ ParseAccessKey(const nsAString& aSpec, n
   aResult = result;
 
   return NS_OK;
 }
 
 const PRUnichar*
 GetTokenEnd(const nsAString& aStr, PRBool aBreakOnDot)
 {
-  const PRUnichar* start;
-  const PRUnichar* tokenEnd;
-  start = tokenEnd = aStr.BeginReading();
+  const PRUnichar* tokenEnd = aStr.BeginReading();
   const PRUnichar* const end = aStr.EndReading();
   PRBool escape = PR_FALSE;
   while (tokenEnd != end) {
     PRUnichar c = *tokenEnd;
     if (IsSpace(c) ||
        (!escape && (c == '+' || c == '-' || (aBreakOnDot && c == '.')))) {
       break;
     }
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -48,16 +48,19 @@
 #include "nsReadableUtils.h"
 #include "nsMathUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "prdtoa.h"
 #include "plstr.h"
 #include "prtime.h"
 #include "nsString.h"
+#include "mozilla/AutoRestore.h"
+
+using namespace mozilla;
 
 //----------------------------------------------------------------------
 // Helper class: InstanceTimeComparator
 
 // Upon inserting an instance time into one of our instance time lists we assign
 // it a serial number. This allows us to sort the instance times in such a way
 // that where we have several equal instance times, the ones added later will
 // sort later. This means that when we call UpdateCurrentInterval during the
@@ -1910,23 +1913,22 @@ nsSMILTimedElement::UpdateCurrentInterva
   if (mElementState == STATE_STARTUP)
     return;
 
   // Check that we aren't stuck in infinite recursion updating some syncbase
   // dependencies. Generally such situations should be detected in advance and
   // the chain broken in a sensible and predictable manner, so if we're hitting
   // this assertion we need to work out how to detect the case that's causing
   // it. In release builds, just bail out before we overflow the stack.
+  AutoRestore<PRUint16> depthRestorer(mUpdateIntervalRecursionDepth);
   if (++mUpdateIntervalRecursionDepth > sMaxUpdateIntervalRecursionDepth) {
     NS_ABORT_IF_FALSE(PR_FALSE,
         "Update current interval recursion depth exceeded threshold");
     return;
   }
-  // NO EARLY RETURNS ALLOWED AFTER THIS POINT! (If we need one, then switch
-  // mUpdateIntervalRecursionDepth to use an auto incrementer/decrementer.)
 
   // If the interval is active the begin time is fixed.
   const nsSMILInstanceTime* beginTime = mElementState == STATE_ACTIVE
                                       ? mCurrentInterval->Begin()
                                       : nsnull;
   nsSMILInterval updatedInterval;
   if (GetNextInterval(GetPreviousInterval(), mCurrentInterval,
                       beginTime, updatedInterval)) {
@@ -1976,18 +1978,16 @@ nsSMILTimedElement::UpdateCurrentInterva
       // The transition to the postactive state will take place on the next
       // sample (along with firing end events, clearing intervals etc.)
       RegisterMilestone();
     } else if (mElementState == STATE_WAITING) {
       mElementState = STATE_POSTACTIVE;
       ResetCurrentInterval();
     }
   }
-
-  --mUpdateIntervalRecursionDepth;
 }
 
 void
 nsSMILTimedElement::SampleSimpleTime(nsSMILTime aActiveTime)
 {
   if (mClient) {
     PRUint32 repeatIteration;
     nsSMILTime simpleTime =
--- a/content/svg/content/src/nsSVGFilterElement.cpp
+++ b/content/svg/content/src/nsSVGFilterElement.cpp
@@ -237,27 +237,40 @@ nsSVGFilterElement::GetEnumInfo()
 
 nsSVGElement::StringAttributesInfo
 nsSVGFilterElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               NS_ARRAY_LENGTH(sStringInfo));
 }
 
-void
-nsSVGFilterElement::DidAnimateLength(PRUint8 aAttrEnum)
+inline static void DidAnimateAttr(nsSVGFilterElement *aFilterElement)
 {
-  // nsSVGFilterFrame does not implement a useful AttributeChanged
-  nsIFrame* frame = GetPrimaryFrame();
+  // nsSVGFilterFrame doesn't implement a useful AttributeChanged
+  nsIFrame* frame = aFilterElement->GetPrimaryFrame();
   if (frame) {
     nsSVGEffects::InvalidateRenderingObservers(frame);
   }
 }
 
 void
+nsSVGFilterElement::DidAnimateLength(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
+}
+
+void
+nsSVGFilterElement::DidAnimateIntegerPair(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
+}
+
+void
 nsSVGFilterElement::DidAnimateEnum(PRUint8 aAttrEnum)
 {
-  // nsSVGFilterFrame does not implement a useful AttributeChanged
-  nsIFrame* frame = GetPrimaryFrame();
-  if (frame) {
-    nsSVGEffects::InvalidateRenderingObservers(frame);
-  }
+  DidAnimateAttr(this);
 }
+
+void
+nsSVGFilterElement::DidAnimateString(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
+}
--- a/content/svg/content/src/nsSVGFilterElement.h
+++ b/content/svg/content/src/nsSVGFilterElement.h
@@ -84,17 +84,19 @@ public:
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual IntegerPairAttributesInfo GetIntegerPairInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
+  virtual void DidAnimateIntegerPair(PRUint8 aAttrEnum);
   virtual void DidAnimateEnum(PRUint8 aAttrEnum);
+  virtual void DidAnimateString(PRUint8 aAttrEnum);
 
   enum { X, Y, WIDTH, HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
   enum { FILTERRES };
   nsSVGIntegerPair mIntegerPairAttributes[1];
   static IntegerPairInfo sIntegerPairInfo[1];
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -305,17 +305,18 @@ inline static void DidAnimateAttr(Elemen
 {
   // nsSVGLeafFrame doesn't implement AttributeChanged.
   nsIFrame* frame = aFilterPrimitive->GetPrimaryFrame();
   if (frame) {
     nsSVGEffects::InvalidateRenderingObservers(frame);
   }
 }
 
-inline static void DidAnimateAttrViaParent(Element *aFilterPrimitive) {
+inline static void DidAnimateAttrViaParent(Element *aFilterPrimitive)
+{
   // No frame, use parent's
   NS_ASSERTION(!aFilterPrimitive->GetPrimaryFrame(), "Not expecting a frame");
   nsIContent *parent = aFilterPrimitive->GetFlattenedTreeParent();
   if (parent && parent->IsElement()) {
     DidAnimateAttr(parent->AsElement());
   }
 }
 
--- a/content/xbl/builtin/emacs/platformHTMLBindings.xml
+++ b/content/xbl/builtin/emacs/platformHTMLBindings.xml
@@ -64,20 +64,16 @@
     <handler event="keypress" keycode="VK_LEFT" modifiers="shift,control" 
         command="cmd_selectWordPrevious"/>
     <handler event="keypress" keycode="VK_RIGHT" modifiers="shift,control" 
         command="cmd_selectWordNext"/>
     <handler event="keypress" key="y" modifiers="accel"
         command="cmd_redo"/>
     <handler event="keypress" key="a" modifiers="alt"
         command="cmd_selectAll"/>
-    <handler event="keypress" keycode="VK_F20" command="cmd_cut" />
-    <handler event="keypress" keycode="VK_F16" command="cmd_copy" />
-    <handler event="keypress" keycode="VK_F18" command="cmd_paste" />
-    <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
     </handlers>
   </binding>
 
   <binding id="textAreas">
     <handlers>
 #include ../textareas-base.inc
     <!-- Emacsish single-line motion and delete keys -->
     <handler event="keypress" key="a" modifiers="control"
@@ -152,20 +148,16 @@
     <handler event="keypress" keycode="VK_RIGHT" modifiers="shift,control" 
         command="cmd_selectWordNext"/>
     <handler event="keypress" keycode="VK_BACK" modifiers="control"
         command="cmd_deleteWordBackward"/>
     <handler event="keypress" key="y" modifiers="accel"
         command="cmd_redo"/>
     <handler event="keypress" key="a" modifiers="alt"
         command="cmd_selectAll"/>
-    <handler event="keypress" keycode="VK_F20" command="cmd_cut" />
-    <handler event="keypress" keycode="VK_F16" command="cmd_copy" />
-    <handler event="keypress" keycode="VK_F18" command="cmd_paste" />
-    <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
     </handlers>
   </binding>
 
   <binding id="browser">
     <handlers>
 #include ../browser-base.inc
       <handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
@@ -177,20 +169,16 @@
       <handler event="keypress" keycode="VK_INSERT" modifiers="control" command="cmd_copy" /> 
       <handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_scrollTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_scrollBottom"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" /> 
       <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" /> 
 
-      <handler event="keypress" keycode="VK_F20" command="cmd_cut" /> 
-      <handler event="keypress" keycode="VK_F16" command="cmd_copy" /> 
-      <handler event="keypress" keycode="VK_F18" command="cmd_paste" /> 
-      <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="control,shift" command="cmd_selectWordPrevious" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="control,shift" command="cmd_selectWordNext" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectCharPrevious" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectCharNext" />
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
@@ -235,15 +223,11 @@
       <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
       <handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
       <handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
-      <handler event="keypress" keycode="VK_F20" command="cmd_cut" />
-      <handler event="keypress" keycode="VK_F16" command="cmd_copy" />
-      <handler event="keypress" keycode="VK_F18" command="cmd_paste" />
-      <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
     </handlers>
   </binding>
 </bindings>
--- a/content/xbl/builtin/unix/platformHTMLBindings.xml
+++ b/content/xbl/builtin/unix/platformHTMLBindings.xml
@@ -8,33 +8,28 @@
     <handlers>
 #include ../input-fields-base.inc
     <handler event="keypress" key="a" modifiers="alt"
         command="cmd_selectAll"/>
     <handler event="keypress" key="y" modifiers="accel"
         command="cmd_redo"/>
     <handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
     <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
-    <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
     </handlers>
   </binding>
 
   <binding id="textAreas">
     <handlers>
 #include ../textareas-base.inc
     <handler event="keypress" key="a" modifiers="alt"
         command="cmd_selectAll"/>
     <handler event="keypress" key="y" modifiers="accel"
         command="cmd_redo"/>
     <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
     <handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
-    <handler event="keypress" keycode="VK_F20" command="cmd_cut" />
-    <handler event="keypress" keycode="VK_F16" command="cmd_copy" />
-    <handler event="keypress" keycode="VK_F18" command="cmd_paste" />
-    <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
     </handlers>
   </binding>
 
   <binding id="browser">
     <handlers>
 #include ../browser-base.inc
       <handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
@@ -46,20 +41,16 @@
       <handler event="keypress" keycode="VK_INSERT" modifiers="control" command="cmd_copy" /> 
       <handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_scrollTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_scrollBottom"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" /> 
       <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" /> 
 
-      <handler event="keypress" keycode="VK_F20" command="cmd_cut" /> 
-      <handler event="keypress" keycode="VK_F16" command="cmd_copy" /> 
-      <handler event="keypress" keycode="VK_F18" command="cmd_paste" /> 
-      <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="control,shift" command="cmd_selectWordPrevious" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="control,shift" command="cmd_selectWordNext" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectCharPrevious" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectCharNext" />
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
@@ -71,15 +62,11 @@
 
   <binding id="editor">
     <handlers>
 #include ../editor-base.inc
       <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
       <handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
       <handler event="keypress" key="y" modifiers="accel"   command="cmd_redo"/>
       <handler event="keypress" key="a" modifiers="alt" command="cmd_selectAll"/>
-      <handler event="keypress" keycode="VK_F20" command="cmd_cut" />
-      <handler event="keypress" keycode="VK_F16" command="cmd_copy" />
-      <handler event="keypress" keycode="VK_F18" command="cmd_paste" />
-      <handler event="keypress" keycode="VK_F14" command="cmd_undo" />
     </handlers>
   </binding>
 </bindings>
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp
+++ b/content/xbl/src/nsXBLPrototypeHandler.cpp
@@ -60,17 +60,17 @@
 #include "nsFocusManager.h"
 #include "nsEventListenerManager.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMEventListener.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptError.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsGkAtoms.h"
 #include "nsGUIEvent.h"
 #include "nsIXPConnect.h"
 #include "nsIDOMScriptObjectFactory.h"
@@ -565,17 +565,17 @@ nsXBLPrototypeHandler::GetController(nsI
 
   if (!controllers) {
     nsCOMPtr<nsIDOMHTMLInputElement> htmlInputElement(do_QueryInterface(aTarget));
     if (htmlInputElement)
       htmlInputElement->GetControllers(getter_AddRefs(controllers));
   }
 
   if (!controllers) {
-    nsCOMPtr<nsIDOMWindowInternal> domWindow(do_QueryInterface(aTarget));
+    nsCOMPtr<nsIDOMWindow> domWindow(do_QueryInterface(aTarget));
     if (domWindow)
       domWindow->GetControllers(getter_AddRefs(controllers));
   }
 
   // Return the first controller.
   // XXX This code should be checking the command name and using supportscommand and
   // iscommandenabled.
   nsIController* controller;
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -49,17 +49,16 @@
 #include "nsXBLService.h"
 #include "nsIServiceManager.h"
 #include "nsGkAtoms.h"
 #include "nsXBLDocumentInfo.h"
 #include "nsIDOMElement.h"
 #include "nsINativeKeyBindings.h"
 #include "nsIController.h"
 #include "nsIControllers.h"
-#include "nsIDOMWindowInternal.h"
 #include "nsFocusManager.h"
 #include "nsPIWindowRoot.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsIDOMDocument.h"
 #include "nsPIWindowRoot.h"
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -75,17 +75,16 @@
 #include "nsIScriptElement.h"
 #include "nsScriptLoader.h"
 #include "nsStyleLinkElement.h"
 #include "nsIImageLoadingContent.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsICookieService.h"
 #include "nsIPrompt.h"
-#include "nsIDOMWindowInternal.h"
 #include "nsIChannel.h"
 #include "nsIPrincipal.h"
 #include "nsXMLPrettyPrinter.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIContentPolicy.h"
 #include "nsIDocumentViewer.h"
 #include "nsContentPolicyUtils.h"
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -133,17 +133,16 @@
 #include "prlog.h"
 #include "rdf.h"
 #include "nsIControllers.h"
 
 // The XUL doc interface
 #include "nsIDOMXULDocument.h"
 
 #include "nsReadableUtils.h"
-#include "nsITimelineService.h"
 #include "nsIFrame.h"
 #include "nsNodeInfoManager.h"
 #include "nsXBLBinding.h"
 #include "nsEventDispatcher.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIDOMXULCommandEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsCCUncollectableMarker.h"
@@ -2997,17 +2996,16 @@ nsXULPrototypeScript::SerializeOutOfLine
 
 
 nsresult
 nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
                                   nsIScriptGlobalObject* aGlobal,
                                   nsIURI* aDocumentURI,
                                   const nsCOMArray<nsINodeInfo> *aNodeInfos)
 {
-    NS_TIMELINE_MARK_FUNCTION("chrome script deserialize");
     nsresult rv;
 
     NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull ||
                  !mScriptObject.mObject,
                  "prototype script not well-initialized when deserializing?!");
 
     // Read basic prototype data
     aStream->Read32(&mLineNo);
--- a/content/xul/content/src/nsXULPopupListener.cpp
+++ b/content/xul/content/src/nsXULPopupListener.cpp
@@ -52,17 +52,17 @@
 #include "nsIDOMNodeList.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsContentCID.h"
 #include "nsContentUtils.h"
 #include "nsXULPopupManager.h"
 #include "nsEventStateManager.h"
 #include "nsIScriptContext.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDocument.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMNSEvent.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
--- a/content/xul/document/public/nsIController.idl
+++ b/content/xul/document/public/nsIController.idl
@@ -65,17 +65,17 @@ interface nsICommandController : nsISupp
     
   void        doCommandWithParams(in string command, in nsICommandParams aCommandParams);
 
 };
 
 
 /*
   An API for registering commands in groups, to allow for 
-  updating via nsIDOMWindowInternal::UpdateCommands.
+  updating via nsIDOMWindow::UpdateCommands.
 */
 interface nsISimpleEnumerator;
 
 [scriptable, uuid(9F82C404-1C7B-11D5-A73C-ECA43CA836FC)]
 interface nsIControllerCommandGroup : nsISupports
 {
 
   void  addCommandToGroup(in string aCommand, in string aGroup);
--- a/content/xul/document/src/nsXULCommandDispatcher.cpp
+++ b/content/xul/document/src/nsXULCommandDispatcher.cpp
@@ -45,17 +45,17 @@
 
 #include "nsIContent.h"
 #include "nsFocusManager.h"
 #include "nsIControllers.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsRDFCID.h"
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -1,11 +1,10 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
@@ -39,17 +38,17 @@
 
 #include "nsDocShell.h"
 #include "nsDSURIContentListener.h"
 #include "nsIChannel.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXPIDLString.h"
 #include "nsDocShellCID.h"
 #include "nsIWebNavigationInfo.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsAutoPtr.h"
 #include "nsIHttpChannel.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetError.h"
 
 //*****************************************************************************
 //***    nsDSURIContentListener: Object Management
 //*****************************************************************************
@@ -153,17 +152,17 @@ nsDSURIContentListener::DoContent(const 
     }
 
     if (NS_FAILED(rv)) {
        // it's okay if we don't know how to handle the content   
         return NS_OK;
     }
 
     if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {
-        nsCOMPtr<nsIDOMWindowInternal> domWindow = do_GetInterface(static_cast<nsIDocShell*>(mDocShell));
+        nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(static_cast<nsIDocShell*>(mDocShell));
         NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
         domWindow->Focus();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -48,17 +48,16 @@
 
 #include "nsIBrowserDOMWindow.h"
 #include "nsIComponentManager.h"
 #include "nsIContent.h"
 #include "mozilla/dom/Element.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMElement.h"
-#include "nsIDOMStorageObsolete.h"
 #include "nsIDOMStorage.h"
 #include "nsPIDOMStorage.h"
 #include "nsIDocumentViewer.h"
 #include "nsIDocumentLoaderFactory.h"
 #include "nsCURILoader.h"
 #include "nsURILoader.h"
 #include "nsDocShellCID.h"
 #include "nsLayoutCID.h"
@@ -66,17 +65,17 @@
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsNetUtil.h"
 #include "nsRect.h"
 #include "prprf.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsIDOMChromeWindow.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsPoint.h"
 #include "nsGfxCIID.h"
 #include "nsIObserverService.h"
 #include "nsIPrompt.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
 #include "nsTextFormatter.h"
@@ -170,19 +169,16 @@
 #include "nsPIWindowRoot.h"
 #include "nsIDOMDocument.h"
 #include "nsICachingChannel.h"
 #include "nsICacheVisitor.h"
 #include "nsICacheEntryDescriptor.h"
 #include "nsIMultiPartChannel.h"
 #include "nsIWyciwygChannel.h"
 
-// The following are for bug #13871: Prevent frameset spoofing
-#include "nsIHTMLDocument.h"
-
 // For reporting errors with the console service.
 // These can go away if error reporting is propagated up past nsDocShell.
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 
 // used to dispatch urls to default protocol handlers
 #include "nsCExternalHandlerService.h"
 #include "nsIExternalProtocolService.h"
@@ -918,18 +914,17 @@ NS_IMETHODIMP nsDocShell::GetInterface(c
     }
     else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
         *aSink = mContentListener;
     }
     else if (aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)) &&
              NS_SUCCEEDED(EnsureScriptEnvironment())) {
         *aSink = mScriptGlobal;
     }
-    else if ((aIID.Equals(NS_GET_IID(nsIDOMWindowInternal)) ||
-              aIID.Equals(NS_GET_IID(nsPIDOMWindow)) ||
+    else if ((aIID.Equals(NS_GET_IID(nsPIDOMWindow)) ||
               aIID.Equals(NS_GET_IID(nsIDOMWindow))) &&
              NS_SUCCEEDED(EnsureScriptEnvironment())) {
         return mScriptGlobal->QueryInterface(aIID, aSink);
     }
     else if (aIID.Equals(NS_GET_IID(nsIDOMDocument)) &&
              NS_SUCCEEDED(EnsureContentViewer())) {
         mContentViewer->GetDOMDocument((nsIDOMDocument **) aSink);
         return *aSink ? NS_OK : NS_NOINTERFACE;
@@ -2771,40 +2766,38 @@ nsDocShell::CanAccessItem(nsIDocShellTre
         return PR_FALSE;
     }
 
     if (!aConsiderOpener) {
         // All done here
         return PR_FALSE;
     }
 
-    nsCOMPtr<nsIDOMWindow> targetWindow(do_GetInterface(aTargetItem));
-    nsCOMPtr<nsIDOMWindowInternal> targetInternal(do_QueryInterface(targetWindow));
-    if (!targetInternal) {
+    nsCOMPtr<nsIDOMWindow> targetWindow = do_GetInterface(aTargetItem);
+    if (!targetWindow) {
         NS_ERROR("This should not happen, really");
         return PR_FALSE;
     }
 
-    nsCOMPtr<nsIDOMWindowInternal> targetOpener;
-    targetInternal->GetOpener(getter_AddRefs(targetOpener));
+    nsCOMPtr<nsIDOMWindow> targetOpener;
+    targetWindow->GetOpener(getter_AddRefs(targetOpener));
     nsCOMPtr<nsIWebNavigation> openerWebNav(do_GetInterface(targetOpener));
     nsCOMPtr<nsIDocShellTreeItem> openerItem(do_QueryInterface(openerWebNav));
 
     if (!openerItem) {
         return PR_FALSE;
     }
 
     return CanAccessItem(openerItem, aAccessingItem, PR_FALSE);    
 }
 
 static PRBool
 ItemIsActive(nsIDocShellTreeItem *aItem)
 {
-    nsCOMPtr<nsIDOMWindow> tmp(do_GetInterface(aItem));
-    nsCOMPtr<nsIDOMWindowInternal> window(do_QueryInterface(tmp));
+    nsCOMPtr<nsIDOMWindow> window(do_GetInterface(aItem));
 
     if (window) {
         PRBool isClosed;
 
         if (NS_SUCCEEDED(window->GetClosed(&isClosed)) && !isClosed) {
             return PR_TRUE;
         }
     }
@@ -2984,17 +2977,17 @@ PrintDocTree(nsIDocShellTreeItem * aPare
   PRInt32 type;
   aParentNode->GetItemType(&type);
   nsCOMPtr<nsIPresShell> presShell;
   parentAsDocShell->GetPresShell(getter_AddRefs(presShell));
   nsRefPtr<nsPresContext> presContext;
   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
   nsIDocument *doc = presShell->GetDocument();
 
-  nsCOMPtr<nsIDOMWindowInternal> domwin(doc->GetWindow());
+  nsCOMPtr<nsIDOMWindow> domwin(doc->GetWindow());
 
   nsCOMPtr<nsIWidget> widget;
   nsIViewManager* vm = presShell->GetViewManager();
   if (vm) {
     vm->GetWidget(getter_AddRefs(widget));
   }
   dom::Element* rootElement = doc->GetRootElement();
 
@@ -8229,17 +8222,17 @@ nsDocShell::InternalLoad(nsIURI * aURI,
         nsCOMPtr<nsIDocShellTreeItem> targetItem;
         FindItemWithName(aWindowTarget, nsnull, this,
                          getter_AddRefs(targetItem));
 
         nsCOMPtr<nsIDocShell> targetDocShell = do_QueryInterface(targetItem);
         
         PRBool isNewWindow = PR_FALSE;
         if (!targetDocShell) {
-            nsCOMPtr<nsIDOMWindowInternal> win =
+            nsCOMPtr<nsIDOMWindow> win =
                 do_GetInterface(GetAsSupports(this));
             NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE);
 
             nsDependentString name(aWindowTarget);
             nsCOMPtr<nsIDOMWindow> newWin;
             rv = win->Open(EmptyString(), // URL to load
                            name,          // window name
                            EmptyString(), // Features
@@ -8285,17 +8278,17 @@ nsDocShell::InternalLoad(nsIURI * aURI,
                 if (isNewWindow) {
                     //
                     // At this point, a new window has been created, but the
                     // URI did not have any data associated with it...
                     //
                     // So, the best we can do, is to tear down the new window
                     // that was just created!
                     //
-                    nsCOMPtr<nsIDOMWindowInternal> domWin =
+                    nsCOMPtr<nsIDOMWindow> domWin =
                         do_GetInterface(targetDocShell);
                     if (domWin) {
                         domWin->Close();
                     }
                 }
                 //
                 // NS_ERROR_NO_CONTENT should not be returned to the
                 // caller... This is an internal error code indicating that
--- a/docshell/base/nsIContentViewerFile.idl
+++ b/docshell/base/nsIContentViewerFile.idl
@@ -35,36 +35,35 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIPrintSettings.idl"
 
-interface nsIDOMWindowInternal;
+interface nsIDOMWindow;
 interface nsIWebProgressListener;
 
 %{ C++
 #include <stdio.h>
 %}
 
 [ptr] native FILE(FILE);
 
 /**
  * The nsIDocShellFile    
  */
 
-[scriptable, uuid(6317f32c-9bc7-11d3-bccc-0060b0fc76bd)]
+[scriptable, uuid(1b373597-6132-49f7-940e-6ff62fca5d35)]
 interface nsIContentViewerFile : nsISupports
 {
-  /* readonly attribute boolean printable; */
   readonly attribute boolean printable;
 
   [noscript] void print(in boolean aSilent,
                         in FILE    aDebugFile, 
                         in nsIPrintSettings aPrintSettings);
 
-  [noscript] void printWithParent(in nsIDOMWindowInternal aParentWin,
+  [noscript] void printWithParent(in nsIDOMWindow aParentWin,
                                   in nsIPrintSettings aThePrintSettings,
                                   in nsIWebProgressListener aWPListener);
 
 };
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -57,17 +57,16 @@ DIRS = \
   interfaces/xbl \
   interfaces/xpath \
   interfaces/load-save \
   interfaces/xul \
   interfaces/storage \
   interfaces/json \
   interfaces/offline \
   interfaces/geolocation \
-  interfaces/threads \
   interfaces/notification \
   interfaces/svg \
   $(NULL)
 
 ifdef MOZ_SMIL
 DIRS += interfaces/smil
 endif
 
@@ -76,16 +75,17 @@ DIRS += \
   base \
   src \
   locales \
   plugins/base \
   plugins/ipc \
   indexedDB \
   system \
   ipc \
+  workers \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
 
 # These subdirs rely on GTK libraries and header files, it is not
 #  buildable on other non-GTK unix builds
 
--- a/dom/base/nsBarProps.cpp
+++ b/dom/base/nsBarProps.cpp
@@ -31,26 +31,27 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "nsBarProps.h"
+
 #include "nsCOMPtr.h"
 #include "nscore.h"
-#include "nsBarProps.h"
 #include "nsGlobalWindow.h"
 #include "nsStyleConsts.h"
 #include "nsIDocShell.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
 #include "nsIWebBrowserChrome.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsDOMClassInfo.h"
 
 //
 //  Basic (virtual) BarProp class implementation
 //
 nsBarProp::nsBarProp(nsGlobalWindow *aWindow)
 {
   mDOMWindow = aWindow;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -109,17 +109,17 @@
 #include "nsJSEnvironment.h"
 
 // DOM base includes
 #include "nsIDOMPluginArray.h"
 #include "nsIDOMPlugin.h"
 #include "nsIDOMMimeTypeArray.h"
 #include "nsIDOMMimeType.h"
 #include "nsIDOMLocation.h"
-#include "nsIDOMWindowInternal.h"
+#include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMJSWindow.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIDOMHistory.h"
 #include "nsIDOMMediaList.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMConstructor.h"
 #include "nsIDOMPerformanceTiming.h"
@@ -455,17 +455,17 @@
 
 // Geolocation
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionCoords.h"
 #include "nsIDOMGeoPositionError.h"
 
 // Workers
-#include "nsDOMWorker.h"
+#include "mozilla/dom/workers/Workers.h"
 
 #include "nsDOMFile.h"
 #include "nsDOMFileReader.h"
 #include "nsIDOMFileException.h"
 #include "nsIDOMFileError.h"
 #include "nsIDOMFormData.h"
 
 #include "nsIDOMDOMStringMap.h"
@@ -594,19 +594,16 @@ static const char kDOMStringBundleURL[] 
 DOMCI_DATA(Crypto, void)
 DOMCI_DATA(CRMFObject, void)
 DOMCI_DATA(SmartCardEvent, void)
 DOMCI_DATA(ContentFrameMessageManager, void)
 
 DOMCI_DATA(DOMPrototype, void)
 DOMCI_DATA(DOMConstructor, void)
 
-DOMCI_DATA(Worker, void)
-DOMCI_DATA(ChromeWorker, void)
-
 #define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper,            \
                                            _flags)                            \
   { #_name,                                                                   \
     nsnull,                                                                   \
     { _helper::doCreate },                                                    \
     nsnull,                                                                   \
     nsnull,                                                                   \
     nsnull,                                                                   \
@@ -1426,21 +1423,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(SimpleGestureEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozTouchEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(MathMLElement, Element, nsElementSH,
                                      ELEMENT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(Worker, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeWorker, nsDOMGenericSH,
-                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(WebGLRenderingContext, nsWebGLViewportHandlerSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLBuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLTexture, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLProgram, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1567,18 +1559,16 @@ struct nsConstructorFuncMapData
   nsDOMConstructorFunc mConstructorFunc;
 };
 
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   { eDOMClassInfo_##_class##_id, _func },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
 PRBool nsDOMClassInfo::sIsInitialized = PR_FALSE;
 PRBool nsDOMClassInfo::sDisableDocumentAllSupport = PR_FALSE;
@@ -2387,49 +2377,41 @@ nsDOMClassInfo::Init()
   rv = stack->GetSafeJSContext(&cx);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (nsGlobalWindow::HasIndexedDBSupport()) {
     if (nsGlobalWindow::HasPerformanceSupport()) {
       DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance)
       DOM_CLASSINFO_MAP_END
     } else {
       DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
       DOM_CLASSINFO_MAP_END
     }
   } else {
     if (nsGlobalWindow::HasPerformanceSupport()) {
       DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance)
       DOM_CLASSINFO_MAP_END
     } else {
       DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
         DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-        DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
       DOM_CLASSINFO_MAP_END
     }
   }
 
   DOM_CLASSINFO_MAP_BEGIN(WindowUtils, nsIDOMWindowUtils)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowUtils)
   DOM_CLASSINFO_MAP_END
 
@@ -3138,20 +3120,18 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMProcessingInstruction)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLinkStyle)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(RangeException, nsIDOMRangeException)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMRangeException)
     DOM_CLASSINFO_MAP_ENTRY(nsIException)
   DOM_CLASSINFO_MAP_END
 
@@ -4033,19 +4013,17 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(DOMStringMap, nsIDOMDOMStringMap)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMStringMap)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataContainerEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
@@ -4151,28 +4129,16 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(MathMLElement, nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(Worker, nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(ChromeWorker, nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(WebGLRenderingContext, nsIDOMWebGLRenderingContext)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWebGLRenderingContext)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLBuffer, nsIWebGLBuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLBuffer)
   DOM_CLASSINFO_MAP_END
 
@@ -5566,17 +5532,17 @@ nsWindowSH::SetProperty(nsIXPConnectWrap
                         JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
 {
   if (id == sLocation_id) {
     JSAutoRequest ar(cx);
 
     JSString *val = ::JS_ValueToString(cx, *vp);
     NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
 
-    nsCOMPtr<nsIDOMWindowInternal> window(do_QueryWrappedNative(wrapper));
+    nsCOMPtr<nsIDOMWindow> window = do_QueryWrappedNative(wrapper);
     NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
 
     nsCOMPtr<nsIDOMLocation> location;
     nsresult rv = window->GetLocation(getter_AddRefs(location));
     NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && location, rv);
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), PR_TRUE,
@@ -6073,18 +6039,40 @@ nsDOMConstructor::HasInstance(nsIXPConne
   JSClass *dom_class = JS_GET_CLASS(cx, dom_obj);
   if (!dom_class) {
     NS_ERROR("nsDOMConstructor::HasInstance can't get class.");
     return NS_ERROR_UNEXPECTED;
   }
 
   const nsGlobalNameStruct *name_struct;
   rv = GetNameStruct(NS_ConvertASCIItoUTF16(dom_class->name), &name_struct);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
   if (!name_struct) {
-    return rv;
+    // This isn't a normal DOM object, see if this constructor lives on its
+    // prototype chain.
+    jsval val;
+    if (!JS_GetProperty(cx, obj, "prototype", &val)) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    JS_ASSERT(!JSVAL_IS_PRIMITIVE(val));
+    JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
+
+    JSObject *proto = JS_GetPrototype(cx, dom_obj);
+    for ( ; proto; proto = JS_GetPrototype(cx, proto)) {
+      if (proto == dot_prototype) {
+        *bp = PR_TRUE;
+        break;
+      }
+    }
+
+    return NS_OK;
   }
 
   if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
       name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo &&
       name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
     // Doesn't have DOM interfaces.
     return NS_OK;
   }
@@ -6709,16 +6697,20 @@ ContentWindowGetter(JSContext *cx, uintN
 {
   JSObject *obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return JS_FALSE;
 
   return ::JS_GetProperty(cx, obj, "content", vp);
 }
 
+static JSNewResolveOp sOtherResolveFuncs[] = {
+  mozilla::dom::workers::ResolveWorkerClasses
+};
+
 NS_IMETHODIMP
 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj, jsid id, PRUint32 flags,
                        JSObject **objp, PRBool *_retval)
 {
   nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
 
   if (!JSID_IS_STRING(id)) {
@@ -6910,17 +6902,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
         // again for this property name.
 
         JSObject *wrapperObj;
         wrapper->GetJSObject(&wrapperObj);
 
         jsval v;
         nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
         rv = WrapNative(cx, wrapperObj, child_win,
-                        &NS_GET_IID(nsIDOMWindowInternal), PR_TRUE, &v,
+                        &NS_GET_IID(nsIDOMWindow), PR_TRUE, &v,
                         getter_AddRefs(holder));
         NS_ENSURE_SUCCESS(rv, rv);
 
         JSAutoRequest ar(cx);
 
         PRBool ok = JS_WrapValue(cx, &v) &&
                     JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull, 0);
         if (!ok) {
@@ -6935,16 +6927,26 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
   }
 
   // It is not worth calling GlobalResolve() if we are resolving
   // for assignment, since only read-write properties get dealt
   // with there.
   if (!(flags & JSRESOLVE_ASSIGNING)) {
     JSAutoRequest ar(cx);
 
+    // Resolve special classes.
+    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sOtherResolveFuncs); i++) {
+      if (!sOtherResolveFuncs[i](cx, obj, id, flags, objp)) {
+        return NS_ERROR_FAILURE;
+      }
+      if (*objp) {
+        return NS_OK;
+      }
+    }
+
     // Call GlobalResolve() after we call FindChildWithName() so
     // that named child frames will override external properties
     // which have been registered with the script namespace manager.
 
     JSBool did_resolve = JS_FALSE;
     rv = GlobalResolve(win, cx, obj, id, &did_resolve);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -457,19 +457,16 @@ DOMCI_CLASS(NotifyPaintEvent)
 DOMCI_CLASS(NotifyAudioAvailableEvent)
 
 DOMCI_CLASS(SimpleGestureEvent)
 
 DOMCI_CLASS(MozTouchEvent)
 
 DOMCI_CLASS(MathMLElement)
 
-DOMCI_CLASS(Worker)
-DOMCI_CLASS(ChromeWorker)
-
 // WebGL
 DOMCI_CLASS(WebGLRenderingContext)
 DOMCI_CLASS(WebGLBuffer)
 DOMCI_CLASS(WebGLTexture)
 DOMCI_CLASS(WebGLProgram)
 DOMCI_CLASS(WebGLShader)
 DOMCI_CLASS(WebGLFramebuffer)
 DOMCI_CLASS(WebGLRenderbuffer)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -86,19 +86,19 @@
 #include "nsPluginHost.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsGeolocation.h"
 #include "nsDesktopNotification.h"
 #include "nsContentCID.h"
 #include "nsLayoutStatics.h"
 #include "nsCycleCollector.h"
 #include "nsCCUncollectableMarker.h"
-#include "nsDOMThreadService.h"
 #include "nsAutoJSValHolder.h"
 #include "nsDOMMediaQueryList.h"
+#include "mozilla/dom/workers/Workers.h"
 
 // Interfaces Needed
 #include "nsIFrame.h"
 #include "nsCanvasFrame.h"
 #include "nsIWidget.h"
 #include "nsIBaseWindow.h"
 #include "nsDeviceMotion.h"
 #include "nsIContent.h"
@@ -1239,28 +1239,21 @@ nsGlobalWindow::ClearScopeWhenAllScripts
 }
 
 void
 nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
 {
   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
 
   // Kill all of the workers for this window.
-  nsDOMThreadService* dts = nsDOMThreadService::get();
-  if (dts) {
-    nsIScriptContext *scx = GetContextInternal();
-
-    JSContext *cx = scx ? (JSContext *)scx->GetNativeContext() : nsnull;
-
-    // Have to suspend this request here because CancelWorkersForGlobal will
-    // lock until the worker has died and that could cause a deadlock.
-    JSAutoSuspendRequest asr(cx);
-
-    dts->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
-  }
+  nsIScriptContext *scx = GetContextInternal();
+  JSContext *cx = scx ?
+                  static_cast<JSContext*>(scx->GetNativeContext()) :
+                  nsnull;
+  mozilla::dom::workers::CancelWorkersForWindow(cx, this);
 
   // Close all IndexedDB databases for this window.
   indexedDB::IndexedDatabaseManager* idbManager =
     indexedDB::IndexedDatabaseManager::Get();
   if (idbManager) {
     idbManager->AbortCloseDatabasesForWindow(this);
   }
 
@@ -1338,24 +1331,22 @@ nsGlobalWindow::FreeInnerObjects(PRBool 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow)
 
 DOMCI_DATA(Window, nsGlobalWindow)
 
 // QueryInterface implementation for nsGlobalWindow
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
   // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMWindowInternal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
   NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow)
   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageIndexedDB)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindowPerformance)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
   OUTER_WINDOW_ONLY
     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   END_OUTER_WINDOW_ONLY
@@ -1834,18 +1825,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   if (aForceReuseInnerWindow &&
       !wouldReuseInnerWindow &&
       mDoc &&
       mDoc->NodePrincipal() != aDocument->NodePrincipal()) {
     NS_ERROR("Attempted forced inner window reuse while changing principal");
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsresult rv = NS_OK;
-
   nsCOMPtr<nsIDocument> oldDoc(do_QueryInterface(mDocument));
 
   nsIScriptContext *scx = GetContextInternal();
   NS_ENSURE_TRUE(scx, NS_ERROR_NOT_INITIALIZED);
 
   JSContext *cx = (JSContext *)scx->GetNativeContext();
 #ifndef MOZ_DISABLE_DOMCRYPTO
   // clear smartcard events, our document has gone away.
@@ -1854,19 +1843,19 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   }
 #endif
   if (!mDocument) {
     // First document load.
 
     // Get our private root. If it is equal to us, then we need to
     // attach our global key bindings that handles browser scrolling
     // and other browser commands.
-    nsIDOMWindowInternal *internal = nsGlobalWindow::GetPrivateRoot();
-
-    if (internal == static_cast<nsIDOMWindowInternal *>(this)) {
+    nsIDOMWindow* privateRoot = nsGlobalWindow::GetPrivateRoot();
+
+    if (privateRoot == static_cast<nsIDOMWindow*>(this)) {
       nsCOMPtr<nsIXBLService> xblService = do_GetService("@mozilla.org/xbl;1");
       if (xblService) {
         xblService->AttachGlobalKeyHandler(mChromeEventHandler);
       }
     }
   }
 
   /* No mDocShell means we're already been partially closed down.  When that
@@ -1879,16 +1868,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   PRBool reUseInnerWindow = aForceReuseInnerWindow || wouldReuseInnerWindow;
 
   // Remember the old document's principal.
   nsIPrincipal *oldPrincipal = nsnull;
   if (oldDoc) {
     oldPrincipal = oldDoc->NodePrincipal();
   }
 
+  nsresult rv = NS_OK;
+
   // Drop our reference to the navigator object unless we're reusing
   // the existing inner window or the new document is from the same
   // origin as the old document.
   if (!reUseInnerWindow && mNavigator && oldPrincipal) {
     PRBool equal;
     rv = oldPrincipal->Equals(aDocument->NodePrincipal(), &equal);
 
     if (NS_FAILED(rv) || !equal) {
@@ -2472,17 +2463,17 @@ nsGlobalWindow::SetDocShell(nsIDocShell*
 
     PRBool docShellActive;
     mDocShell->GetIsActive(&docShellActive);
     mIsBackground = !docShellActive;
   }
 }
 
 void
-nsGlobalWindow::SetOpenerWindow(nsIDOMWindowInternal* aOpener,
+nsGlobalWindow::SetOpenerWindow(nsIDOMWindow* aOpener,
                                 PRBool aOriginalOpener)
 {
   FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
 
   NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled,
                "aOriginalOpener is true, but not first call to "
                "SetOpenerWindow!");
   NS_ASSERTION(aOpener || !aOriginalOpener,
@@ -2907,36 +2898,32 @@ nsGlobalWindow::GetDocument(nsIDOMDocume
   if (!mDocument && (docShell = GetDocShell()))
     nsCOMPtr<nsIDOMDocument> domdoc(do_GetInterface(docShell));
 
   NS_IF_ADDREF(*aDocument = mDocument);
 
   return NS_OK;
 }
 
-//*****************************************************************************
-// nsGlobalWindow::nsIDOMWindowInternal
-//*****************************************************************************
-
-NS_IMETHODIMP
-nsGlobalWindow::GetWindow(nsIDOMWindowInternal** aWindow)
+NS_IMETHODIMP
+nsGlobalWindow::GetWindow(nsIDOMWindow** aWindow)
 {
   FORWARD_TO_OUTER(GetWindow, (aWindow), NS_ERROR_NOT_INITIALIZED);
 
-  *aWindow = static_cast<nsIDOMWindowInternal *>(this);
+  *aWindow = static_cast<nsIDOMWindow*>(this);
   NS_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetSelf(nsIDOMWindowInternal** aWindow)
+nsGlobalWindow::GetSelf(nsIDOMWindow** aWindow)
 {
   FORWARD_TO_OUTER(GetSelf, (aWindow), NS_ERROR_NOT_INITIALIZED);
 
-  *aWindow = static_cast<nsIDOMWindowInternal *>(this);
+  *aWindow = static_cast<nsIDOMWindow*>(this);
   NS_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator)
 {
   FORWARD_TO_OUTER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
@@ -3037,17 +3024,17 @@ nsGlobalWindow::GetParent(nsIDOMWindow**
   docShellAsItem->GetSameTypeParent(getter_AddRefs(parent));
 
   if (parent) {
     nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(parent));
     NS_ENSURE_SUCCESS(CallQueryInterface(globalObject.get(), aParent),
                       NS_ERROR_FAILURE);
   }
   else {
-    *aParent = static_cast<nsIDOMWindowInternal *>(this);
+    *aParent = static_cast<nsIDOMWindow*>(this);
     NS_ADDREF(*aParent);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetTop(nsIDOMWindow** aTop)
 {
@@ -3099,17 +3086,17 @@ nsGlobalWindow::GetContent(nsIDOMWindow*
   if (!primaryContent) {
     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
     GetTreeOwner(getter_AddRefs(treeOwner));
     NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
 
     treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
   }
 
-  nsCOMPtr<nsIDOMWindowInternal> domWindow(do_GetInterface(primaryContent));
+  nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(primaryContent));
   NS_IF_ADDREF(*aContent = domWindow);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt)
 {
@@ -3356,17 +3343,17 @@ nsGlobalWindow::GetControllers(nsIContro
   }
 
   *aResult = mControllers;
   NS_ADDREF(*aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::GetOpener(nsIDOMWindowInternal** aOpener)
+nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
 {
   FORWARD_TO_OUTER(GetOpener, (aOpener), NS_ERROR_NOT_INITIALIZED);
 
   *aOpener = nsnull;
 
   nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
   if (!opener) {
     return NS_OK;
@@ -3408,17 +3395,17 @@ nsGlobalWindow::GetOpener(nsIDOMWindowIn
     }
   }
 
   NS_IF_ADDREF(*aOpener);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsGlobalWindow::SetOpener(nsIDOMWindowInternal* aOpener)
+nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
 {
   // check if we were called from a privileged chrome script.
   // If not, opener is settable only to null.
   if (aOpener && !nsContentUtils::IsCallerTrustedForWrite()) {
     return NS_OK;
   }
 
   SetOpenerWindow(aOpener, PR_FALSE);
@@ -4299,17 +4286,17 @@ nsGlobalWindow::GetLength(PRUint32* aLen
 }
 
 PRBool
 nsGlobalWindow::DispatchCustomEvent(const char *aEventName)
 {
   PRBool defaultActionEnabled = PR_TRUE;
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
   nsContentUtils::DispatchTrustedEvent(doc,
-                                       static_cast<nsIScriptGlobalObject*>(this),
+                                       GetOuterWindow(),
                                        NS_ConvertASCIItoUTF16(aEventName),
                                        PR_TRUE, PR_TRUE, &defaultActionEnabled);
 
   return defaultActionEnabled;
 }
 
 static already_AddRefed<nsIDocShellTreeItem>
 GetCallerDocShellTreeItem()
@@ -4399,17 +4386,17 @@ nsGlobalWindow::SetFullScreen(PRBool aFu
   }
 
   // SetFullScreen needs to be called on the root window, so get that
   // via the DocShell tree, and if we are not already the root,
   // call SetFullScreen on that window instead.
   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
   nsCOMPtr<nsIDocShellTreeItem> rootItem;
   treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
-  nsCOMPtr<nsIDOMWindowInternal> window = do_GetInterface(rootItem);
+  nsCOMPtr<nsIDOMWindow> window = do_GetInterface(rootItem);
   if (!window)
     return NS_ERROR_FAILURE;
   if (rootItem != treeItem)
     return window->SetFullScreen(aFullScreen);
 
   // make sure we don't try to set full screen on a non-chrome window,
   // which might happen in embedding world
   PRInt32 itemType;
@@ -4454,17 +4441,17 @@ nsGlobalWindow::GetFullScreen(PRBool* aF
 
   // Get the fullscreen value of the root window, to always have the value
   // accurate, even when called from content.
   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
   if (treeItem) {
     nsCOMPtr<nsIDocShellTreeItem> rootItem;
     treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
     if (rootItem != treeItem) {
-      nsCOMPtr<nsIDOMWindowInternal> window = do_GetInterface(rootItem);
+      nsCOMPtr<nsIDOMWindow> window = do_GetInterface(rootItem);
       if (window)
         return window->GetFullScreen(aFullScreen);
     }
   }
 
   // We are the root window, or something went wrong. Return our internal value.
   *aFullScreen = mFullScreen;
   return NS_OK;
@@ -4924,19 +4911,19 @@ nsGlobalWindow::Focus()
     baseWin->GetVisibility(&isVisible);
   }
 
   if (!isVisible) {
     // A hidden tab is being focused, ignore this call.
     return NS_OK;
   }
 
-  nsIDOMWindowInternal *caller =
-    static_cast<nsIDOMWindowInternal*>(nsContentUtils::GetWindowFromCaller());
-  nsCOMPtr<nsIDOMWindowInternal> opener;
+  nsIDOMWindow *caller =
+    static_cast<nsIDOMWindow*>(nsContentUtils::GetWindowFromCaller());
+  nsCOMPtr<nsIDOMWindow> opener;
   GetOpener(getter_AddRefs(opener));
 
   // Enforce dom.disable_window_flip (for non-chrome), but still allow the
   // window which opened us to raise us at times when popups are allowed
   // (bugs 355482 and 369306).
   PRBool canFocus = CanSetProperty("dom.disable_window_flip") ||
                     (opener == caller &&
                      RevisePopupAbuseLevel(gPopupControlState) < openAbused);
@@ -4972,17 +4959,17 @@ nsGlobalWindow::Focus()
   nsCOMPtr<nsIPresShell> presShell;
   // Don't look for a presshell if we're a root chrome window that's got
   // about:blank loaded.  We don't want to focus our widget in that case.
   // XXXbz should we really be checking for IsInitialDocument() instead?
   PRBool lookForPresShell = PR_TRUE;
   PRInt32 itemType = nsIDocShellTreeItem::typeContent;
   treeItem->GetItemType(&itemType);
   if (itemType == nsIDocShellTreeItem::typeChrome &&
-      GetPrivateRoot() == static_cast<nsIDOMWindowInternal*>(this) &&
+      GetPrivateRoot() == static_cast<nsIDOMWindow*>(this) &&
       mDocument) {
     nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
     NS_ASSERTION(doc, "Bogus doc?");
     nsIURI* ourURI = doc->GetDocumentURI();
     if (ourURI) {