Merge MC -> JM
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 21 Jul 2011 18:53:37 -0700
changeset 76536 40b7b08eaa123caee88b3e7c59b8c4e811a50898
parent 76535 cdb452875184636ecea5f5daa8fad5d539931652 (current diff)
parent 73543 7a1c228f8f85526f1bc80fd3c8dc8d4e81967ce4 (diff)
child 76537 36813ba5ea40a40794a342335013a9d927730ad6
push idunknown
push userunknown
push dateunknown
milestone8.0a1
Merge MC -> JM
accessible/tests/mochitest/test_keys.html
browser/base/content/browser.js
browser/base/content/test/tabview/test_bug599626.html
browser/installer/precompile_cache.js
browser/themes/gnomestripe/browser/tabview/new-tab.png
browser/themes/pinstripe/browser/tabview/new-tab.png
browser/themes/winstripe/browser/tabview/new-tab.png
content/smil/crashtests/665335-1.svg
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
js/src/Makefile.in
js/src/config/autoconf.mk.in
js/src/configure.in
js/src/jsanalyze.cpp
js/src/jsanalyze.h
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jscntxt.h
js/src/jscompartment.cpp
js/src/jsemit.cpp
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jshashtable.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsinterpinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsopcode.tbl
js/src/jsparse.cpp
js/src/jsparse.h
js/src/jsprobes.cpp
js/src/jsreflect.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jstracer.cpp
js/src/jstracer.h
js/src/jsweakmap.cpp
js/src/jsxdrapi.h
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/LoopState.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
js/src/shell/Makefile.in
js/src/shell/js.cpp
js/src/tests/js1_8_5/extensions/jstests.list
js/src/tests/js1_8_5/regress/jstests.list
js/src/tests/manifest.py
js/src/xpconnect/shell/xpcshell.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
layout/forms/nsIsIndexFrame.cpp
layout/forms/nsIsIndexFrame.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
mobile/app/profile/extensions/feedback@mobile.mozilla.org/install.rdf
mobile/chrome/content/aboutCertError.css
mobile/themes/core/aboutCertError.css
modules/libpref/src/init/all.js
netwerk/cookie/test/unit_ipc/head_ipc_setup.js
netwerk/test/unit_ipc/head_ipc_setup.js
testing/mochitest/tests/SimpleTest/MozillaFileLogger.js
toolkit/content/tests/browser/common/_loadAll.js
toolkit/content/tests/browser/common/mockTransferForContinuing.js
toolkit/content/tests/browser/common/testRunner.js
toolkit/content/tests/browser/common/toolkitFunctions.js
toolkit/crashreporter/content/crash-submit-form.xhtml
toolkit/spatial-navigation/Makefile.in
toolkit/spatial-navigation/SpatialNavigation.js
toolkit/spatial-navigation/tests/Makefile.in
toolkit/spatial-navigation/tests/chrome/SpatialNavUtils.js
toolkit/spatial-navigation/tests/chrome/test_snav.xul
toolkit/spatial-navigation/tests/chrome/test_snav_disabledElement.xul
toolkit/spatial-navigation/tests/chrome/test_snav_prefDisabled.xul
toolkit/spatial-navigation/tests/chrome/test_snav_prefKeyCode.xul
toolkit/spatial-navigation/tests/chrome/test_snav_selects.xul
toolkit/spatial-navigation/tests/chrome/test_snav_textFields.xul
toolkit/spatial-navigation/tests/chrome/test_snav_tightlinks.xul
tools/performance/startup/analyze-timeline-log.pl
tools/performance/startup/measure-simple.pl
tools/performance/startup/printlog.pl
xpcom/ds/nsITimelineService.idl
xpcom/ds/nsTime.h
xpcom/ds/nsTimelineService.cpp
xpcom/ds/nsTimelineService.h
--- a/accessible/src/atk/nsMaiInterfaceAction.cpp
+++ b/accessible/src/atk/nsMaiInterfaceAction.cpp
@@ -106,102 +106,58 @@ getActionNameCB(AtkAction *aAction, gint
     nsresult rv = accWrap->GetActionName(aActionIndex, autoStr);
     NS_ENSURE_SUCCESS(rv, nsnull);
     return nsAccessibleWrap::ReturnString(autoStr);
 }
 
 const gchar *
 getKeyBindingCB(AtkAction *aAction, gint aActionIndex)
 {
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aAction));
-    if (!accWrap)
-        return nsnull;
-
-    //return all KeyBindings including accesskey and shortcut
-    nsAutoString allKeyBinding;
+  nsAccessibleWrap* acc = GetAccessibleWrap(ATK_OBJECT(aAction));
+  if (!acc)
+    return nsnull;
 
-    //get accesskey
-    nsAutoString accessKey;
-    nsresult rv = accWrap->GetKeyboardShortcut(accessKey);
+  // Return all key bindings including access key and keyboard shortcut.
+  nsAutoString keyBindingsStr;
 
-    if (NS_SUCCEEDED(rv) && !accessKey.IsEmpty()) {
-        nsAccessible* parent = accWrap->GetParent();
-        if (parent) {
-          PRUint32 atkRole = atkRoleMap[parent->NativeRole()];
+  // Get access key.
+  KeyBinding keyBinding = acc->AccessKey();
+  if (!keyBinding.IsEmpty()) {
+    keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
 
-            if (atkRole == ATK_ROLE_MENU_BAR) {
-                //it is topmenu, change from "Alt+f" to "f;<Alt>f"
-                nsAutoString rightChar;
-                accessKey.Right(rightChar, 1);
-                allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") +
-                                rightChar;
-            }
-            else if ((atkRole == ATK_ROLE_MENU) || (atkRole == ATK_ROLE_MENU_ITEM)) {
-                //it is submenu, change from "s" to "s;<Alt>f:s"
-                nsAutoString allKey = accessKey;
-                nsAccessible* grandParent = parent;
+    nsAccessible* parent = acc->GetParent();
+    PRUint32 role = parent ? parent->Role() : 0;
+    if (role == nsIAccessibleRole::ROLE_PARENT_MENUITEM ||
+        role == nsIAccessibleRole::ROLE_MENUITEM ||
+        role == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM ||
+        role == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM) {
+      // It is submenu, expose keyboard shortcuts from menu hierarchy like
+      // "s;<Alt>f:s"
+      nsAutoString keysInHierarchyStr = keyBindingsStr;
+      do {
+        KeyBinding parentKeyBinding = parent->AccessKey();
+        if (!parentKeyBinding.IsEmpty()) {
+          nsAutoString str;
+          parentKeyBinding.ToString(str, KeyBinding::eAtkFormat);
+          str.Append(':');
 
-                do {
-                    nsAutoString grandParentKey;
-                    grandParent->GetKeyboardShortcut(grandParentKey);
-
-                    if (!grandParentKey.IsEmpty()) {
-                        nsAutoString rightChar;
-                        grandParentKey.Right(rightChar, 1);
-                        allKey = rightChar + NS_LITERAL_STRING(":") + allKey;
-                    }
-
-                } while ((grandParent = grandParent->GetParent()) &&
-                         atkRoleMap[grandParent->NativeRole()] != ATK_ROLE_MENU_BAR);
-
-                allKeyBinding = accessKey + NS_LITERAL_STRING(";<Alt>") +
-                                allKey;
-            }
+          keysInHierarchyStr.Insert(str, 0);
         }
-        else {
-            //default process, rarely happens.
-            nsAutoString rightChar;
-            accessKey.Right(rightChar, 1);
-            allKeyBinding = rightChar + NS_LITERAL_STRING(";<Alt>") + rightChar;
-        }
-    }
-    else  //don't have accesskey
-        allKeyBinding.AssignLiteral(";");
-
-    //get shortcut
-    nsAutoString subShortcut;
-    nsCOMPtr<nsIDOMDOMStringList> keyBindings;
-    rv = accWrap->GetKeyBindings(aActionIndex, getter_AddRefs(keyBindings));
-
-    if (NS_SUCCEEDED(rv) && keyBindings) {
-        PRUint32 length = 0;
-        keyBindings->GetLength(&length);
-        for (PRUint32 i = 0; i < length; i++) {
-            nsAutoString keyBinding;
-            keyBindings->Item(i, keyBinding);
+      } while ((parent = parent->GetParent()) &&
+               parent->Role() != nsIAccessibleRole::ROLE_MENUBAR);
 
-            //change the shortcut from "Ctrl+Shift+L" to "<Control><Shift>L"
-            PRInt32 oldPos, curPos=0;
-            while ((curPos != -1) && (curPos < (PRInt32)keyBinding.Length())) {
-                oldPos = curPos;
-                nsAutoString subString;
-                curPos = keyBinding.FindChar('+', oldPos);
-                if (curPos == -1) {
-                    keyBinding.Mid(subString, oldPos, keyBinding.Length() - oldPos);
-                    subShortcut += subString;
-                } else {
-                    keyBinding.Mid(subString, oldPos, curPos - oldPos);
+      keyBindingsStr.Append(';');
+      keyBindingsStr.Append(keysInHierarchyStr);
+    }
+  } else {
+    // No access key, add ';' to point this.
+    keyBindingsStr.Append(';');
+  }
 
-                    //change "Ctrl" to "Control"
-                    if (subString.LowerCaseEqualsLiteral("ctrl"))
-                        subString.AssignLiteral("Control");
+  // Get keyboard shortcut.
+  keyBindingsStr.Append(';');
+  keyBinding = acc->KeyboardShortcut();
+  if (!keyBinding.IsEmpty()) {
+    keyBinding.AppendToString(keyBindingsStr, KeyBinding::eAtkFormat);
+  }
 
-                    subShortcut += NS_LITERAL_STRING("<") + subString +
-                                   NS_LITERAL_STRING(">");
-                    curPos++;
-                }
-            }
-        }
-    }
-
-    allKeyBinding += NS_LITERAL_STRING(";") + subShortcut;
-    return nsAccessibleWrap::ReturnString(allKeyBinding);
+  return nsAccessibleWrap::ReturnString(keyBindingsStr);
 }
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -40,16 +40,17 @@
 
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsDocAccessible.h"
 #include "nsEventShell.h"
 #include "nsTextAccessible.h"
 #include "TextUpdater.h"
+#include "mozilla/dom/Element.h"
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // NotificationCollector
 ////////////////////////////////////////////////////////////////////////////////
 
 NotificationController::NotificationController(nsDocAccessible* aDocument,
                                                nsIPresShell* aPresShell) :
@@ -253,27 +254,19 @@ NotificationController::WillRefresh(mozi
   for (PRUint32 idx = 0; idx < childDocCount; idx++) {
     nsDocAccessible* childDoc = mHangingChildDocuments[idx];
 
     nsIContent* ownerContent = mDocument->GetDocumentNode()->
       FindContentForSubDocument(childDoc->GetDocumentNode());
     if (ownerContent) {
       nsAccessible* outerDocAcc = mDocument->GetAccessible(ownerContent);
       if (outerDocAcc && outerDocAcc->AppendChild(childDoc)) {
-        if (mDocument->AppendChildDocument(childDoc)) {
-          // Fire reorder event to notify new accessible document has been
-          // attached to the tree.
-          nsRefPtr<AccEvent> reorderEvent =
-              new AccEvent(nsIAccessibleEvent::EVENT_REORDER, outerDocAcc,
-                           eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
-          if (reorderEvent)
-            QueueEvent(reorderEvent);
+        if (mDocument->AppendChildDocument(childDoc))
+          continue;
 
-          continue;
-        }
         outerDocAcc->RemoveChild(childDoc);
       }
 
       // Failed to bind the child document, destroy it.
       childDoc->Shutdown();
     }
   }
   mHangingChildDocuments.Clear();
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -463,22 +463,23 @@ nsAccDocManager::CreateDocOrRootAccessib
   if (isRootDoc) {
     nsAccessible* appAcc = nsAccessNode::GetApplicationAccessible();
     if (!appAcc->AppendChild(docAcc)) {
       docAcc->Shutdown();
       return nsnull;
     }
 
     // Fire reorder event to notify new accessible document has been attached to
-    // the tree.
+    // the tree. The reorder event is delivered after the document tree is
+    // constructed because event processing and tree construction are done by
+    // the same document.
     nsRefPtr<AccEvent> reorderEvent =
       new AccEvent(nsIAccessibleEvent::EVENT_REORDER, appAcc, eAutoDetect,
                    AccEvent::eCoalesceFromSameSubtree);
-    if (reorderEvent)
-      docAcc->FireDelayedAccessibleEvent(reorderEvent);
+    docAcc->FireDelayedAccessibleEvent(reorderEvent);
 
   } else {
     parentDocAcc->BindChildDocument(docAcc);
   }
 
   NS_LOG_ACCDOCCREATE("document creation finished", aDocument)
 
   AddListeners(aDocument, isRootDoc);
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -71,17 +71,16 @@
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 nsIStringBundle *nsAccessNode::gStringBundle = 0;
-nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
 nsINode *nsAccessNode::gLastFocusedNode = nsnull;
 
 PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
 
 nsApplicationAccessible *nsAccessNode::gApplicationAccessible = nsnull;
 
 /*
  * Class nsAccessNode
@@ -205,18 +204,16 @@ nsAccessNode::GetApplicationAccessible()
 void nsAccessNode::InitXPAccessibility()
 {
   nsCOMPtr<nsIStringBundleService> stringBundleService =
     mozilla::services::GetStringBundleService();
   if (stringBundleService) {
     // Static variables are released in ShutdownAllXPAccessibility();
     stringBundleService->CreateBundle(ACCESSIBLE_BUNDLE_URL, 
                                       &gStringBundle);
-    stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL, 
-                                      &gKeyStringBundle);
   }
 
   nsAccessibilityAtoms::AddRefAtoms();
 
   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (prefBranch) {
     prefBranch->GetBoolPref("browser.formfill.enable", &gIsFormFillEnabled);
   }
@@ -241,17 +238,16 @@ void nsAccessNode::NotifyA11yInitOrShutd
 
 void nsAccessNode::ShutdownXPAccessibility()
 {
   // Called by nsAccessibilityService::Shutdown()
   // which happens when xpcom is shutting down
   // at exit of program
 
   NS_IF_RELEASE(gStringBundle);
-  NS_IF_RELEASE(gKeyStringBundle);
   NS_IF_RELEASE(gLastFocusedNode);
 
   // Release gApplicationAccessible after everything else is shutdown
   // so we don't accidently create it again while tearing down root accessibles
   nsApplicationAccessibleWrap::Unload();
   if (gApplicationAccessible) {
     gApplicationAccessible->Shutdown();
     NS_RELEASE(gApplicationAccessible);
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -210,17 +210,16 @@ protected:
 
     /**
      * Notify global nsIObserver's that a11y is getting init'd or shutdown
      */
     static void NotifyA11yInitOrShutdown(PRBool aIsInit);
 
     // Static data, we do our own refcounting for our static data
     static nsIStringBundle *gStringBundle;
-    static nsIStringBundle *gKeyStringBundle;
 
     static PRBool gIsFormFillEnabled;
 
 private:
   static nsApplicationAccessible *gApplicationAccessible;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessNode,
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -100,16 +100,17 @@
 #include "nsEventStates.h"
 
 #ifdef NS_DEBUG
 #include "nsIDOMCharacterData.h"
 #endif
 
 #include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible. nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible)
@@ -324,73 +325,31 @@ nsAccessible::Description(nsString& aDes
             // has no name or the tooltip is the same as the name
             aDescription.Truncate();
         }
       }
     }
     aDescription.CompressWhitespace();
 }
 
-// mask values for ui.key.chromeAccess and ui.key.contentAccess
-#define NS_MODIFIER_SHIFT    1
-#define NS_MODIFIER_CONTROL  2
-#define NS_MODIFIER_ALT      4
-#define NS_MODIFIER_META     8
-
-// returns the accesskey modifier mask used in the given node's context
-// (i.e. chrome or content), or 0 if an error occurs
-static PRInt32
-GetAccessModifierMask(nsIContent* aContent)
-{
-  // use ui.key.generalAccessKey (unless it is -1)
-  switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
-    case -1:                             break;
-    case nsIDOMKeyEvent::DOM_VK_SHIFT:   return NS_MODIFIER_SHIFT;
-    case nsIDOMKeyEvent::DOM_VK_CONTROL: return NS_MODIFIER_CONTROL;
-    case nsIDOMKeyEvent::DOM_VK_ALT:     return NS_MODIFIER_ALT;
-    case nsIDOMKeyEvent::DOM_VK_META:    return NS_MODIFIER_META;
-    default:                             return 0;
-  }
-
-  // get the docShell to this DOMNode, return 0 on failure
-  nsCOMPtr<nsIDocument> document = aContent->GetCurrentDoc();
-  if (!document)
-    return 0;
-  nsCOMPtr<nsISupports> container = document->GetContainer();
-  if (!container)
-    return 0;
-  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
-  if (!treeItem)
-    return 0;
-
-  // determine the access modifier used in this context
-  nsresult rv = NS_ERROR_FAILURE;
-  PRInt32 itemType, accessModifierMask = 0;
-  treeItem->GetItemType(&itemType);
-  switch (itemType) {
-    case nsIDocShellTreeItem::typeChrome:
-      rv = Preferences::GetInt("ui.key.chromeAccess", &accessModifierMask);
-      break;
-
-    case nsIDocShellTreeItem::typeContent:
-      rv = Preferences::GetInt("ui.key.contentAccess", &accessModifierMask);
-      break;
-  }
-
-  return NS_SUCCEEDED(rv) ? accessModifierMask : 0;
-}
-
 NS_IMETHODIMP
 nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
 {
   aAccessKey.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
+  AccessKey().ToString(aAccessKey);
+  return NS_OK;
+}
+
+KeyBinding
+nsAccessible::AccessKey() const
+{
   PRUint32 key = nsCoreUtils::GetAccessKeyFor(mContent);
   if (!key && mContent->IsElement()) {
     nsAccessible* label = nsnull;
 
     // Copy access key from label node.
     if (mContent->IsHTML()) {
       // Unless it is labeled via an ancestor <label>, in which case that would
       // be redundant.
@@ -403,42 +362,64 @@ nsAccessible::GetKeyboardShortcut(nsAStr
       label = iter.Next();
     }
 
     if (label)
       key = nsCoreUtils::GetAccessKeyFor(label->GetContent());
   }
 
   if (!key)
-    return NS_OK;
-
-  nsAutoString accesskey(key);
-
-  // Append the modifiers in reverse order, result: Control+Alt+Shift+Meta+<key>
-  nsAutoString propertyKey;
-  PRInt32 modifierMask = GetAccessModifierMask(mContent);
-  if (modifierMask & NS_MODIFIER_META) {
-    propertyKey.AssignLiteral("VK_META");
-    nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
+    return KeyBinding();
+
+  // Get modifier mask. Use ui.key.generalAccessKey (unless it is -1).
+  switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
+  case -1:
+    break;
+  case nsIDOMKeyEvent::DOM_VK_SHIFT:
+    return KeyBinding(key, KeyBinding::kShift);
+  case nsIDOMKeyEvent::DOM_VK_CONTROL:
+    return KeyBinding(key, KeyBinding::kControl);
+  case nsIDOMKeyEvent::DOM_VK_ALT:
+    return KeyBinding(key, KeyBinding::kAlt);
+  case nsIDOMKeyEvent::DOM_VK_META:
+    return KeyBinding(key, KeyBinding::kMeta);
+  default:
+    return KeyBinding();
   }
-  if (modifierMask & NS_MODIFIER_SHIFT) {
-    propertyKey.AssignLiteral("VK_SHIFT");
-    nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
-  }
-  if (modifierMask & NS_MODIFIER_ALT) {
-    propertyKey.AssignLiteral("VK_ALT");
-    nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
+
+  // Determine the access modifier used in this context.
+  nsIDocument* document = mContent->GetCurrentDoc();
+  if (!document)
+    return KeyBinding();
+  nsCOMPtr<nsISupports> container = document->GetContainer();
+  if (!container)
+    return KeyBinding();
+  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
+  if (!treeItem)
+    return KeyBinding();
+
+  nsresult rv = NS_ERROR_FAILURE;
+  PRInt32 itemType = 0, modifierMask = 0;
+  treeItem->GetItemType(&itemType);
+  switch (itemType) {
+    case nsIDocShellTreeItem::typeChrome:
+      rv = Preferences::GetInt("ui.key.chromeAccess", &modifierMask);
+      break;
+    case nsIDocShellTreeItem::typeContent:
+      rv = Preferences::GetInt("ui.key.contentAccess", &modifierMask);
+      break;
   }
-  if (modifierMask & NS_MODIFIER_CONTROL) {
-    propertyKey.AssignLiteral("VK_CONTROL");
-    nsAccessible::GetFullKeyName(propertyKey, accesskey, accesskey);
-  }
-
-  aAccessKey = accesskey;
-  return NS_OK;
+
+  return NS_SUCCEEDED(rv) ? KeyBinding(key, modifierMask) : KeyBinding();
+}
+
+KeyBinding
+nsAccessible::KeyboardShortcut() const
+{
+  return KeyBinding();
 }
 
 NS_IMETHODIMP
 nsAccessible::GetParent(nsIAccessible **aParent)
 {
   NS_ENSURE_ARG_POINTER(aParent);
 
   NS_IF_ADDREF(*aParent = GetParent());
@@ -599,32 +580,16 @@ nsresult nsAccessible::GetTranslatedStri
   if (!gStringBundle || 
     NS_FAILED(gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue)))) 
     return NS_ERROR_FAILURE;
 
   aStringOut.Assign(xsValue);
   return NS_OK;
 }
 
-nsresult nsAccessible::GetFullKeyName(const nsAString& aModifierName, const nsAString& aKeyName, nsAString& aStringOut)
-{
-  nsXPIDLString modifierName, separator;
-
-  if (!gKeyStringBundle ||
-      NS_FAILED(gKeyStringBundle->GetStringFromName(PromiseFlatString(aModifierName).get(), 
-                                                    getter_Copies(modifierName))) ||
-      NS_FAILED(gKeyStringBundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(), 
-                                                    getter_Copies(separator)))) {
-    return NS_ERROR_FAILURE;
-  }
-
-  aStringOut = modifierName + separator + aKeyName; 
-  return NS_OK;
-}
-
 PRBool
 nsAccessible::IsVisible(PRBool* aIsOffscreen)
 {
   // We need to know if at least a kMinPixels around the object is visible,
   // otherwise it will be marked states::OFFSCREEN. The states::INVISIBLE flag
   // is for elements which are programmatically hidden.
 
   *aIsOffscreen = PR_TRUE;
@@ -1783,16 +1748,20 @@ NS_IMETHODIMP nsAccessible::SetName(cons
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetDefaultKeyBinding(nsAString& aKeyBinding)
 {
   aKeyBinding.Truncate();
+  if (IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  KeyboardShortcut().ToString(aKeyBinding);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessible::GetKeyBindings(PRUint8 aActionIndex,
                              nsIDOMDOMStringList **aKeyBindings)
 {
   // Currently we support only unique key binding on element for default action.
@@ -3354,8 +3323,84 @@ nsAccessible::GetLevelInternal()
       }
     } else {
       ++ level; // level is 1-index based
     }
   }
 
   return level;
 }
+
+
+////////////////////////////////////////////////////////////////////////////////
+// KeyBinding class
+
+void
+KeyBinding::ToPlatformFormat(nsAString& aValue) const
+{
+  nsCOMPtr<nsIStringBundle> keyStringBundle;
+  nsCOMPtr<nsIStringBundleService> stringBundleService =
+      mozilla::services::GetStringBundleService();
+  if (stringBundleService)
+    stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL,
+                                      getter_AddRefs(keyStringBundle));
+
+  if (!keyStringBundle)
+    return;
+
+  nsAutoString separator;
+  keyStringBundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(),
+                                     getter_Copies(separator));
+
+  nsAutoString modifierName;
+  if (mModifierMask & kControl) {
+    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(),
+                                       getter_Copies(modifierName));
+
+    aValue.Append(modifierName);
+    aValue.Append(separator);
+  }
+
+  if (mModifierMask & kAlt) {
+    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(),
+                                       getter_Copies(modifierName));
+
+    aValue.Append(modifierName);
+    aValue.Append(separator);
+  }
+
+  if (mModifierMask & kShift) {
+    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(),
+                                       getter_Copies(modifierName));
+
+    aValue.Append(modifierName);
+    aValue.Append(separator);
+  }
+
+  if (mModifierMask & kMeta) {
+    keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(),
+                                       getter_Copies(modifierName));
+
+    aValue.Append(modifierName);
+    aValue.Append(separator);
+  }
+
+  aValue.Append(mKey);
+}
+
+void
+KeyBinding::ToAtkFormat(nsAString& aValue) const
+{
+  nsAutoString modifierName;
+  if (mModifierMask & kControl)
+    aValue.Append(NS_LITERAL_STRING("<Control>"));
+
+  if (mModifierMask & kAlt)
+    aValue.Append(NS_LITERAL_STRING("<Alt>"));
+
+  if (mModifierMask & kShift)
+    aValue.Append(NS_LITERAL_STRING("<Shift>"));
+
+  if (mModifierMask & kMeta)
+      aValue.Append(NS_LITERAL_STRING("<Meta>"));
+
+  aValue.Append(mKey);
+}
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -52,16 +52,17 @@
 #include "nsARIAMap.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 
 class AccEvent;
 class AccGroupInfo;
 class EmbeddedObjCollector;
+class KeyBinding;
 class nsAccessible;
 class nsHyperTextAccessible;
 class nsHTMLLIAccessible;
 struct nsRoleMapEntry;
 class nsTextAccessible;
 
 struct nsRect;
 class nsIContent;
@@ -397,16 +398,30 @@ public:
 
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
   nsRootAccessible* AsRoot();
 
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
   nsTextAccessible* AsTextLeaf();
 
   //////////////////////////////////////////////////////////////////////////////
+  // ActionAccessible
+
+  /**
+   * Return access key, such as Alt+D.
+   */
+  virtual KeyBinding AccessKey() const;
+
+  /**
+   * Return global keyboard shortcut for default action, such as Ctrl+O for
+   * Open file menuitem.
+   */
+  virtual KeyBinding KeyboardShortcut() const;
+
+  //////////////////////////////////////////////////////////////////////////////
   // HyperLinkAccessible
 
   /**
    * Return true if the accessible is hyper link accessible.
    */
   virtual bool IsLink();
 
   /**
@@ -687,9 +702,66 @@ protected:
   friend class AccGroupInfo;
 
   nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible,
                               NS_ACCESSIBLE_IMPL_IID)
 
+
+/**
+ * Represent key binding associated with accessible (such as access key and
+ * global keyboard shortcuts).
+ */
+class KeyBinding
+{
+public:
+  /**
+   * Modifier mask values.
+   */
+  static const PRUint32 kShift = 1;
+  static const PRUint32 kControl = 2;
+  static const PRUint32 kAlt = 4;
+  static const PRUint32 kMeta = 8;
+
+  KeyBinding() : mKey(0), mModifierMask(0) {}
+  KeyBinding(PRUint32 aKey, PRUint32 aModifierMask) :
+    mKey(aKey), mModifierMask(aModifierMask) {};
+
+  inline bool IsEmpty() const { return !mKey; }
+  inline PRUint32 Key() const { return mKey; }
+  inline PRUint32 ModifierMask() const { return mModifierMask; }
+
+  enum Format {
+    ePlatformFormat,
+    eAtkFormat
+  };
+
+  /**
+   * Return formatted string for this key binding depending on the given format.
+   */
+  inline void ToString(nsAString& aValue,
+                       Format aFormat = ePlatformFormat) const
+  {
+    aValue.Truncate();
+    AppendToString(aValue, aFormat);
+  }
+  inline void AppendToString(nsAString& aValue,
+                             Format aFormat = ePlatformFormat) const
+  {
+    if (mKey) {
+      if (aFormat == ePlatformFormat)
+        ToPlatformFormat(aValue);
+      else
+        ToAtkFormat(aValue);
+    }
+  }
+
+private:
+  void ToPlatformFormat(nsAString& aValue) const;
+  void ToAtkFormat(nsAString& aValue) const;
+
+  PRUint32 mKey;
+  PRUint32 mModifierMask;
+};
+
 #endif
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -128,23 +128,16 @@ nsApplicationAccessible::GetValue(nsAStr
 }
 
 void
 nsApplicationAccessible::Description(nsString &aDescription)
 {
   aDescription.Truncate();
 }
 
-NS_IMETHODIMP
-nsApplicationAccessible::GetKeyboardShortcut(nsAString &aKeyboardShortcut)
-{
-  aKeyboardShortcut.Truncate();
-  return NS_OK;
-}
-
 PRUint64
 nsApplicationAccessible::State()
 {
   return IsDefunct() ? states::DEFUNCT : 0;
 }
 
 NS_IMETHODIMP
 nsApplicationAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
@@ -379,16 +372,22 @@ nsApplicationAccessible::NativeState()
 
 void
 nsApplicationAccessible::InvalidateChildren()
 {
   // Do nothing because application children are kept updated by AppendChild()
   // and RemoveChild() method calls.
 }
 
+KeyBinding
+nsApplicationAccessible::AccessKey() const
+{
+  return KeyBinding();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessible protected methods
 
 void
 nsApplicationAccessible::CacheChildren()
 {
   // CacheChildren is called only once for application accessible when its
   // children are requested because empty InvalidateChldren() prevents its
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -86,17 +86,16 @@ public:
   NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
 
   // nsIAccessible
   NS_IMETHOD GetParent(nsIAccessible **aParent);
   NS_IMETHOD GetNextSibling(nsIAccessible **aNextSibling);
   NS_IMETHOD GetPreviousSibling(nsIAccessible **aPreviousSibling);
   NS_IMETHOD GetName(nsAString &aName);
   NS_IMETHOD GetValue(nsAString &aValue);
-  NS_IMETHOD GetKeyboardShortcut(nsAString &aKeyboardShortcut);
   NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
   NS_IMETHOD GroupPosition(PRInt32 *aGroupLevel, PRInt32 *aSimilarItemsInGroup,
                            PRInt32 *aPositionInGroup);
   NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
                                nsIAccessibleRelation **aRelation);
   NS_IMETHOD GetRelationsCount(PRUint32 *aRelationsCount);
   NS_IMETHOD GetRelation(PRUint32 aIndex, nsIAccessibleRelation **aRelation);
   NS_IMETHOD GetRelations(nsIArray **aRelations);
@@ -125,16 +124,19 @@ public:
   virtual PRUint32 NativeRole();
   virtual PRUint64 State();
   virtual PRUint64 NativeState();
   virtual nsAccessible* ChildAtPoint(PRInt32 aX, PRInt32 aY,
                                      EWhichChildAtPoint aWhichChild);
 
   virtual void InvalidateChildren();
 
+  // ActionAccessible
+  virtual KeyBinding AccessKey() const;
+
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
   virtual nsAccessible* GetSiblingAtOffset(PRInt32 aOffset,
                                            nsresult *aError = nsnull) const;
 
 private:
--- a/accessible/src/base/nsBaseWidgetAccessible.cpp
+++ b/accessible/src/base/nsBaseWidgetAccessible.cpp
@@ -170,23 +170,21 @@ nsLinkableAccessible::DoAction(PRUint8 a
 {
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   return mActionAcc ? mActionAcc->DoAction(aIndex) :
     nsAccessibleWrap::DoAction(aIndex);
 }
 
-NS_IMETHODIMP
-nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
+KeyBinding
+nsLinkableAccessible::AccessKey() const
 {
-  aKeyboardShortcut.Truncate();
-
-  return mActionAcc ? mActionAcc->GetKeyboardShortcut(aKeyboardShortcut) :
-    nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
+  return mActionAcc ?
+    mActionAcc->AccessKey() : nsAccessible::AccessKey();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsLinkableAccessible. nsAccessNode
 
 void
 nsLinkableAccessible::Shutdown()
 {
--- a/accessible/src/base/nsBaseWidgetAccessible.h
+++ b/accessible/src/base/nsBaseWidgetAccessible.h
@@ -87,24 +87,26 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetValue(nsAString& _retval);
   NS_IMETHOD TakeFocus();
-  NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
 
   // nsAccessNode
   virtual void Shutdown();
 
   // nsAccessible
   virtual PRUint64 NativeState();
 
+  // ActionAccessible
+  virtual KeyBinding AccessKey() const;
+
   // HyperLinkAccessible
   virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
 
 protected:
   // nsAccessible
   virtual void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent);
 
   /**
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -61,16 +61,17 @@
 #include "nsPIDOMWindow.h"
 #include "nsGUIEvent.h"
 #include "nsIView.h"
 #include "nsLayoutUtils.h"
 
 #include "nsContentCID.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
+#include "mozilla/dom/Element.h"
 
 static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsCoreUtils
 ////////////////////////////////////////////////////////////////////////////////
 
 PRBool
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1489,16 +1489,27 @@ nsDocAccessible::NotifyOfInitialUpdate()
   // miss the notification (since content tree change notifications are ignored
   // prior to initial update). Make sure the content element is valid.
   nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocument);
   if (contentElm && mContent != contentElm)
     mContent = contentElm;
 
   // Build initial tree.
   CacheChildrenInSubtree(this);
+
+  // Fire reorder event after the document tree is constructed. Note, since
+  // this reorder event is processed by parent document then events targeted to
+  // this document may be fired prior to this reorder event. If this is
+  // a problem then consider to keep event processing per tab document.
+  if (!IsRoot()) {
+    nsRefPtr<AccEvent> reorderEvent =
+      new AccEvent(nsIAccessibleEvent::EVENT_REORDER, GetParent(),
+                   eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
+    ParentDocument()->FireDelayedAccessibleEvent(reorderEvent);
+  }
 }
 
 void
 nsDocAccessible::AddDependentIDsFor(nsAccessible* aRelProvider,
                                     nsIAtom* aRelAttr)
 {
   for (PRUint32 idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp
+++ b/accessible/src/html/nsHTMLLinkAccessible.cpp
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHTMLLinkAccessible.h"
 
 #include "States.h"
 #include "nsCoreUtils.h"
 
 #include "nsEventStates.h"
+#include "mozilla/dom/Element.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLLinkAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLLinkAccessible::
   nsHTMLLinkAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
--- a/accessible/src/msaa/CAccessibleAction.cpp
+++ b/accessible/src/msaa/CAccessibleAction.cpp
@@ -37,21 +37,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "CAccessibleAction.h"
 
 #include "AccessibleAction_i.c"
 
-#include "nsIAccessible.h"
-#include "nsAccessNodeWrap.h"
-#include "nsCOMPtr.h"
-#include "nsString.h"
-#include "nsIDOMDOMStringList.h"
+#include "nsAccessible.h"
 
 // IUnknown
 
 STDMETHODIMP
 CAccessibleAction::QueryInterface(REFIID iid, void** ppv)
 {
   *ppv = NULL;
 
@@ -132,64 +128,54 @@ CAccessibleAction::get_description(long 
 }
 
 STDMETHODIMP
 CAccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
                                   BSTR **aKeyBinding,
                                   long *aNumBinding)
 {
 __try {
+  if (!aKeyBinding)
+    return E_INVALIDARG;
   *aKeyBinding = NULL;
+
+  if (!aNumBinding)
+    return E_INVALIDARG;
   *aNumBinding = 0;
 
-  nsCOMPtr<nsIAccessible> acc(do_QueryObject(this));
-  if (!acc)
+  if (aActionIndex != 0 || aNumMaxBinding < 1)
+    return E_INVALIDARG;
+
+  nsRefPtr<nsAccessible> acc(do_QueryObject(this));
+  if (!acc || acc->IsDefunct())
     return E_FAIL;
 
-  nsCOMPtr<nsIDOMDOMStringList> keys;
-  PRUint8 index = static_cast<PRUint8>(aActionIndex);
-  nsresult rv = acc->GetKeyBindings(index, getter_AddRefs(keys));
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
-
-  PRUint32 length = 0;
-  keys->GetLength(&length);
-  if (length == 0)
+  // Expose keyboard shortcut if it's not exposed via MSAA keyboard shortcut.
+  KeyBinding keyBinding = acc->AccessKey();
+  if (keyBinding.IsEmpty())
     return S_FALSE;
 
-  PRUint32 maxBinding = static_cast<PRUint32>(aNumMaxBinding);
-  PRUint32 numBinding = length > maxBinding ? maxBinding : length;
-  *aNumBinding = numBinding;
+  keyBinding = acc->KeyboardShortcut();
+  if (keyBinding.IsEmpty())
+    return S_FALSE;
 
-  *aKeyBinding = static_cast<BSTR*>(nsMemory::Alloc((numBinding) * sizeof(BSTR*)));
+  nsAutoString keyStr;
+  keyBinding.ToString(keyStr);
+
+  *aKeyBinding = static_cast<BSTR*>(::CoTaskMemAlloc(sizeof(BSTR*)));
   if (!*aKeyBinding)
     return E_OUTOFMEMORY;
 
-  PRBool outOfMemory = PR_FALSE;
-  PRUint32 i = 0;
-  for (; i < numBinding; i++) {
-    nsAutoString key;
-    keys->Item(i, key);
-    *(aKeyBinding[i]) = ::SysAllocStringLen(key.get(), key.Length());
-
-    if (!*(aKeyBinding[i])) {
-      outOfMemory = PR_TRUE;
-      break;
-    }
+  *(aKeyBinding[0]) = ::SysAllocStringLen(keyStr.get(), keyStr.Length());
+  if (!*(aKeyBinding[0])) {
+    ::CoTaskMemFree(*aKeyBinding);
+    return E_OUTOFMEMORY;
   }
 
-  if (outOfMemory) {
-    for (PRUint32 j = 0; j < i; j++)
-      ::SysFreeString(*(aKeyBinding[j]));
-
-    nsMemory::Free(*aKeyBinding);
-    *aKeyBinding = NULL;
-
-    return E_OUTOFMEMORY;
-  }
+  *aNumBinding = 1;
   return S_OK;
 
 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
 STDMETHODIMP
 CAccessibleAction::get_name(long aActionIndex, BSTR *aName)
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -481,26 +481,28 @@ STDMETHODIMP nsAccessibleWrap::get_accHe
 
 STDMETHODIMP nsAccessibleWrap::get_accKeyboardShortcut(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
 {
 __try {
   if (!pszKeyboardShortcut)
     return E_INVALIDARG;
+  *pszKeyboardShortcut = NULL;
 
-  *pszKeyboardShortcut = NULL;
-  nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
-  if (!xpAccessible || xpAccessible->IsDefunct())
+  nsAccessible* acc = GetXPAccessibleFor(varChild);
+  if (!acc || acc->IsDefunct())
     return E_FAIL;
 
+  KeyBinding keyBinding = acc->AccessKey();
+  if (keyBinding.IsEmpty())
+    keyBinding = acc->KeyboardShortcut();
+
   nsAutoString shortcut;
-  nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+  keyBinding.ToString(shortcut);
 
   *pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
                                              shortcut.Length());
   return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return E_FAIL;
 }
 
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -53,16 +53,17 @@
 #include "nsIServiceManager.h"
 #include "nsIPresShell.h"
 #include "nsIContent.h"
 #include "nsGUIEvent.h"
 #include "nsILookAndFeel.h"
 #include "nsWidgetsCID.h"
 
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULSelectableAccessible
@@ -382,82 +383,125 @@ nsXULMenuitemAccessible::GetNameInternal
 
 void
 nsXULMenuitemAccessible::Description(nsString& aDescription)
 {
   mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::description,
                     aDescription);
 }
 
-//return menu accesskey: N or Alt+F
-NS_IMETHODIMP
-nsXULMenuitemAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
+KeyBinding
+nsXULMenuitemAccessible::AccessKey() const
 {
-  aAccessKey.Truncate();
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
+  // Return menu accesskey: N or Alt+F.
   static PRInt32 gMenuAccesskeyModifier = -1;  // magic value of -1 indicates unitialized state
 
   // We do not use nsCoreUtils::GetAccesskeyFor() because accesskeys for
   // menu are't registered by nsEventStateManager.
   nsAutoString accesskey;
   mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::accesskey,
                     accesskey);
   if (accesskey.IsEmpty())
-    return NS_OK;
+    return KeyBinding();
+
+  PRUint32 modifierKey = 0;
 
   nsAccessible* parentAcc = GetParent();
   if (parentAcc) {
     if (parentAcc->NativeRole() == nsIAccessibleRole::ROLE_MENUBAR) {
       // If top level menu item, add Alt+ or whatever modifier text to string
       // No need to cache pref service, this happens rarely
       if (gMenuAccesskeyModifier == -1) {
         // Need to initialize cached global accesskey pref
         gMenuAccesskeyModifier = Preferences::GetInt("ui.key.menuAccessKey", 0);
       }
 
-      nsAutoString propertyKey;
       switch (gMenuAccesskeyModifier) {
         case nsIDOMKeyEvent::DOM_VK_CONTROL:
-          propertyKey.AssignLiteral("VK_CONTROL");
+          modifierKey = KeyBinding::kControl;
           break;
         case nsIDOMKeyEvent::DOM_VK_ALT:
-          propertyKey.AssignLiteral("VK_ALT");
+          modifierKey = KeyBinding::kAlt;
           break;
         case nsIDOMKeyEvent::DOM_VK_META:
-          propertyKey.AssignLiteral("VK_META");
+          modifierKey = KeyBinding::kMeta;
           break;
       }
-
-      if (!propertyKey.IsEmpty())
-        nsAccessible::GetFullKeyName(propertyKey, accesskey, aAccessKey);
     }
   }
 
-  if (aAccessKey.IsEmpty())
-    aAccessKey = accesskey;
-
-  return NS_OK;
+  return KeyBinding(accesskey[0], modifierKey);
 }
 
-//return menu shortcut: Ctrl+F or Ctrl+Shift+L
-NS_IMETHODIMP
-nsXULMenuitemAccessible::GetDefaultKeyBinding(nsAString& aKeyBinding)
+KeyBinding
+nsXULMenuitemAccessible::KeyboardShortcut() const
 {
-  aKeyBinding.Truncate();
+  nsAutoString keyElmId;
+  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyElmId);
+  if (keyElmId.IsEmpty())
+    return KeyBinding();
+
+  nsIDocument* document = mContent->GetOwnerDoc();
+  if (!document)
+    return KeyBinding();
+
+  nsIContent* keyElm = document->GetElementById(keyElmId);
+  if (!keyElm)
+    return KeyBinding();
+
+  PRUint32 key = 0;
+
+  nsAutoString keyStr;
+  keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::key, keyStr);
+  if (keyStr.IsEmpty()) {
+    nsAutoString keyCodeStr;
+    keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, keyCodeStr);
+    PRUint32 errorCode;
+    key = keyStr.ToInteger(&errorCode, kAutoDetect);
+  } else {
+    key = keyStr[0];
+  }
+
+  nsAutoString modifiersStr;
+  keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr);
 
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
+  PRUint32 modifierMask = 0;
+  if (modifiersStr.Find("shift") != -1)
+    modifierMask != KeyBinding::kShift;
+  if (modifiersStr.Find("alt") != -1)
+    modifierMask |= KeyBinding::kAlt;
+  if (modifiersStr.Find("meta") != -1)
+    modifierMask |= KeyBinding::kMeta;
+  if (modifiersStr.Find("control") != -1)
+    modifierMask |= KeyBinding::kControl;
+  if (modifiersStr.Find("accel") != -1) {
+    // Get the accelerator key value from prefs, overriding the default.
+    switch (Preferences::GetInt("ui.key.accelKey", 0)) {
+      case nsIDOMKeyEvent::DOM_VK_META:
+        modifierMask |= KeyBinding::kMeta;
+        break;
 
-  nsAutoString accelText;
-  mContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::acceltext,
-                    aKeyBinding);
+      case nsIDOMKeyEvent::DOM_VK_ALT:
+        modifierMask |= KeyBinding::kAlt;
+        break;
+
+      case nsIDOMKeyEvent::DOM_VK_CONTROL:
+        modifierMask |= KeyBinding::kControl;
+        break;
 
-  return NS_OK;
+      default:
+#ifdef XP_MACOSX
+        modifierMask |= KeyBinding::kMeta;
+#else
+        modifierMask |= KeyBinding::kControl;
+#endif
+    }
+  }
+
+  return KeyBinding(key, modifierMask);
 }
 
 PRUint32
 nsXULMenuitemAccessible::NativeRole()
 {
   nsCOMPtr<nsIDOMXULContainerElement> xulContainer(do_QueryInterface(mContent));
   if (xulContainer)
     return nsIAccessibleRole::ROLE_PARENT_MENUITEM;
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -77,32 +77,34 @@ protected:
 class nsXULMenuitemAccessible : public nsAccessibleWrap
 {
 public:
   enum { eAction_Click = 0 };
 
   nsXULMenuitemAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsIAccessible
-  NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
-  NS_IMETHOD GetDefaultKeyBinding(nsAString& aKeyBinding);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
 
   // nsAccessible
   virtual void Description(nsString& aDescription);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual PRInt32 GetLevelInternal();
   virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                           PRInt32 *aSetSize);
 
   virtual PRBool GetAllowsAnonChildAccessibles();
+
+  // ActionAccessible
+  virtual KeyBinding AccessKey() const;
+  virtual KeyBinding KeyboardShortcut() const;
 };
 
 /**
  * Used for XUL menuseparator element.
  */
 class nsXULMenuSeparatorAccessible : public nsXULMenuitemAccessible
 {
 public:
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -92,17 +92,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug420863.html \
 		test_childAtPoint.html \
 		test_childAtPoint.xul \
 		test_descr.html \
 		test_elm_landmarks.html \
 		test_elm_listbox.xul \
 		test_elm_nsApplicationAcc.html \
 		test_elm_plugin.html \
-		test_keys.html \
  		test_nsIAccessible_selects.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleImage.html \
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
 		test_takeFocus.html \
 		test_text_caret.html \
--- a/accessible/tests/mochitest/actions/Makefile.in
+++ b/accessible/tests/mochitest/actions/Makefile.in
@@ -46,16 +46,18 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_anchors.html \
 		test_aria.html \
 		test_general.html \
 		test_general.xul \
 		test_inputs.html \
+		test_keys_menu.xul \
+		test_keys.html \
 		test_link.html \
 		test_media.html \
 		test_tree.xul \
 		test_treegrid.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
rename from accessible/tests/mochitest/test_keys.html
rename to accessible/tests/mochitest/actions/test_keys.html
--- a/accessible/tests/mochitest/test_keys.html
+++ b/accessible/tests/mochitest/actions/test_keys.html
@@ -7,33 +7,34 @@
         href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 
   <script type="application/javascript"
-          src="common.js"></script>
+          src="../common.js"></script>
 
   <script type="application/javascript">
     function testKeyboardShortcut(aAccOrElmOrID, aKey)
     {
       var acc = getAccessible(aAccOrElmOrID);
       if (!acc)
         return;
 
       is(acc.keyboardShortcut, aKey,
          "Wrong keyboard shortcut on " + prettyName(aAccOrElmOrID));
     }
 
     function doTest()
     {
       testKeyboardShortcut("input1", "");
       testKeyboardShortcut("input2", MAC ? "⌃b" : "Alt+Shift+b");
+      testKeyboardShortcut("link", MAC ? "⌃l" : "Alt+Shift+l");
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
@@ -51,10 +52,11 @@
   <pre id="test">
   </pre>
 
   <label accesskey="a">
     <input id="input1"/>
   </label>
   <label accesskey="b" for="input2">
   <input id="input2"/>
+  <a id="link" accesskey="l">link</a>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/actions/test_keys_menu.xul
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL access keys and shortcut keys tests">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    function openMenu(aMenuID, aMenuitemID)
+    {
+      this.menuNode = getNode(aMenuID),
+      this.menuitemNode = getNode(aMenuitemID),
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, this.menuNode)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        // Show menu.
+        this.menuNode.open = true;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        var menu = getAccessible(aMenuID);
+        is(menu.keyboardShortcut, (MAC ? "u" : "Alt+u"),
+           "Wrong accesskey on " + prettyName(this.menuitemNode));
+
+        var menuitem = getAccessible(aMenuitemID);
+        is(menuitem.keyboardShortcut, "p",
+           "Wrong accesskey on " + prettyName(this.menuitemNode));
+        is(menuitem.defaultKeyBinding, (MAC ? "⌃l" : "Ctrl+l"),
+           "Wrong keyboard shortcut on " + prettyName(this.menuitemNode));
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "menuitem accesskey and shortcut test " +
+          prettyName(this.menuItemNode);
+      }
+    }
+
+    var gQueue = null;
+    function doTest()
+    {
+      gQueue = new eventQueue();
+      gQueue.push(new openMenu("menu", "menuitem"));
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=672092"
+         title="Reorganize access key and keyboard shortcut handling code">
+        Mozilla Bug 672092
+      </a><br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <keyset>
+        <key key="l" modifiers="control" id="key1"/>
+      </keyset>
+
+      <menubar>
+        <menu label="menu" id="menu" accesskey="u">
+          <menupopup>
+            <menuitem accesskey="p" key="key1" label="item1" id="menuitem"/>
+          </menupopup>
+        </menu>
+      </menubar>
+
+      <vbox id="debug"/>
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -154,21 +154,33 @@ const DO_NOT_FINISH_TEST = 1;
  *     // (used in the case when invoker expects single event).
  *     DOMNode getter: function() {},
  *
  *     // Array of checker objects defining expected events on invoker's action.
  *     //
  *     // Checker object interface:
  *     //
  *     // var checker = {
- *     //   type getter: function() {}, // DOM or a11y event type
- *     //   target getter: function() {}, // DOM node or accessible
- *     //   phase getter: function() {}, // DOM event phase (false - bubbling)
+ *     //   * DOM or a11y event type. *
+ *     //   type getter: function() {},
+ *     //
+ *     //   * DOM node or accessible. *
+ *     //   target getter: function() {},
+ *     //
+ *     //   * DOM event phase (false - bubbling). *
+ *     //   phase getter: function() {},
+ *     //
+ *     //   * Callback, called when event is handled
  *     //   check: function(aEvent) {},
- *     //   getID: function() {}
+ *     //
+ *     //   * Checker ID *
+ *     //   getID: function() {},
+ *     //
+ *     //   * Event that don't have predefined order relative other events. *
+ *     //   async getter: function() {}
  *     // };
  *     eventSeq getter() {},
  *
  *     // Array of checker objects defining unexpected events on invoker's
  *     // action.
  *     unexpectedEventSeq getter() {},
  *
  *     // The ID of invoker.
@@ -322,76 +334,110 @@ function eventQueue(aEventType)
       // invoker in the queue.
       this.processNextInvoker();
       return;
     }
 
     if ("debugCheck" in invoker)
       invoker.debugCheck(aEvent);
 
-    // Search through handled expected events if one of them was handled again.
+    // Search through handled expected events to report error if one of them is
+    // handled for a second time.
     var idx = 0;
     for (; idx < this.mEventSeq.length; idx++) {
-      if (!this.isEventUnexpected(idx) && (invoker.wasCaught[idx] == true) &&
+      if (this.isEventExpected(idx) && (invoker.wasCaught[idx] == true) &&
           this.isAlreadyCaught(idx, aEvent)) {
 
         var msg = "Doubled event { event type: " +
           this.getEventTypeAsString(idx) + ", target: " +
           prettyName(this.getEventTarget(idx)) + "} in test with ID = '" +
           this.getEventID(idx) + "'.";
         ok(false, msg);
       }
     }
 
-    // Search through unexpected events to ensure no one of them was handled.
+    // Search through unexpected events, any matches result in error report
+    // after this invoker processing.
     for (idx = 0; idx < this.mEventSeq.length; idx++) {
       if (this.isEventUnexpected(idx) && this.compareEvents(idx, aEvent))
         invoker.wasCaught[idx] = true;
     }
 
-    // We've handled all expected events, next invoker processing is pending.
-    if (this.mEventSeqIdx == this.mEventSeq.length)
+    // Nothing left, proceed next invoker in timeout. Otherwise check if
+    // handled event is matched.
+    var idxObj = {};
+    if (!this.prepareForExpectedEvent(invoker, idxObj))
       return;
 
-    // Compute next expected event index.
-    for (idx = this.mEventSeqIdx + 1;
-         idx < this.mEventSeq.length && this.mEventSeq[idx].unexpected;
-         idx++);
-
-    // No expected events were registered, proceed to next invoker to ensure
-    // unexpected events for current invoker won't be handled.
-    if (idx == this.mEventSeq.length) {
-      this.mEventSeqIdx = idx;
-      this.processNextInvokerInTimeout();
-      return;
+    // Check if handled event matches expected sync event.
+    var matched = false;
+    idx = idxObj.value;
+    if (idx < this.mEventSeq.length) {
+      matched = this.compareEvents(idx, aEvent);
+      if (matched)
+        this.mEventSeqIdx = idx;
     }
 
-    // Check if handled event matches expected event.
-    var matched = this.compareEvents(idx, aEvent);
+    // Check if handled event matches any expected async events.
+    if (!matched) {
+      for (idx = 0; idx < this.mEventSeq.length; idx++) {
+        if (this.mEventSeq[idx].async) {
+          matched = this.compareEvents(idx, aEvent);
+          if (matched)
+            break;
+        }
+      }
+    }
     this.dumpEventToDOM(aEvent, idx, matched);
 
     if (matched) {
       this.checkEvent(idx, aEvent);
       invoker.wasCaught[idx] = true;
-      this.mEventSeqIdx = idx;
 
-      // Get next expected event index.
-      while (++idx < this.mEventSeq.length && this.mEventSeq[idx].unexpected);
-
-      // If the last expected event was processed, proceed next invoker in
-      // timeout to ensure unexpected events for current invoker won't be
-      // handled.
-      if (idx == this.mEventSeq.length) {
-        this.mEventSeqIdx = idx;
-        this.processNextInvokerInTimeout();
-      }
+      this.prepareForExpectedEvent(invoker);
     }
   }
 
   // Helpers
+  this.prepareForExpectedEvent =
+    function eventQueue_prepareForExpectedEvent(aInvoker, aIdxObj)
+  {
+    // Nothing left, wait for next invoker.
+    if (this.mEventSeqFinished)
+      return false;
+
+    // Compute next expected sync event index.
+    for (var idx = this.mEventSeqIdx + 1;
+         idx < this.mEventSeq.length &&
+         (this.mEventSeq[idx].unexpected || this.mEventSeq[idx].async);
+         idx++);
+
+    // If no expected events were left, proceed to next invoker in timeout
+    // to make sure unexpected events for current invoker aren't be handled.
+    if (idx == this.mEventSeq.length) {
+      var allHandled = true;
+      for (var jdx = 0; jdx < this.mEventSeq.length; jdx++) {
+        if (this.isEventExpected(jdx) && !aInvoker.wasCaught[jdx])
+          allHandled = false;
+      }
+
+      if (allHandled) {
+        this.mEventSeqIdx = this.mEventSeq.length;
+        this.mEventFinished = true;
+        this.processNextInvokerInTimeout();
+        return false;
+      }
+    }
+
+    if (aIdxObj)
+      aIdxObj.value = idx;
+
+    return true;
+  }
+
   this.getInvoker = function eventQueue_getInvoker()
   {
     return this.mInvokers[this.mIndex];
   }
 
   this.getNextInvoker = function eventQueue_getNextInvoker()
   {
     return this.mInvokers[++this.mIndex];
@@ -400,28 +446,34 @@ function eventQueue(aEventType)
   this.setEventHandler = function eventQueue_setEventHandler(aInvoker)
   {
     // Create unique event sequence concatenating expected and unexpected
     // events.
     this.mEventSeq = ("eventSeq" in aInvoker) ?
       aInvoker.eventSeq :
       [ new invokerChecker(this.mDefEventType, aInvoker.DOMNode) ];
 
-    for (var idx = 0; idx < this.mEventSeq.length; idx++)
+    for (var idx = 0; idx < this.mEventSeq.length; idx++) {
       this.mEventSeq[idx].unexpected = false;
+      if (!("async" in this.mEventSeq[idx]))
+        this.mEventSeq[idx].async = false;
+    }
 
     var unexpectedSeq = aInvoker.unexpectedEventSeq;
     if (unexpectedSeq) {
-      for (var idx = 0; idx < unexpectedSeq.length; idx++)
+      for (var idx = 0; idx < unexpectedSeq.length; idx++) {
         unexpectedSeq[idx].unexpected = true;
+        unexpectedSeq[idx].async = false;
+      }
 
       this.mEventSeq = this.mEventSeq.concat(unexpectedSeq);
     }
 
     this.mEventSeqIdx = -1;
+    this.mEventSeqFinished = false;
 
     // Register event listeners
     if (this.mEventSeq) {
       aInvoker.wasCaught = new Array(this.mEventSeq.length);
 
       for (var idx = 0; idx < this.mEventSeq.length; idx++) {
         var eventType = this.getEventType(idx);
 
@@ -512,16 +564,20 @@ function eventQueue(aEventType)
     var invoker = this.getInvoker();
     return invoker.getID();
   }
 
   this.isEventUnexpected = function eventQueue_isEventUnexpected(aIdx)
   {
     return this.mEventSeq[aIdx].unexpected;
   }
+  this.isEventExpected = function eventQueue_isEventExpected(aIdx)
+  {
+    return !this.mEventSeq[aIdx].unexpected;
+  }
 
   this.compareEvents = function eventQueue_compareEvents(aIdx, aEvent)
   {
     var eventType1 = this.getEventType(aIdx);
 
     var eventType2 = (aEvent instanceof nsIDOMEvent) ?
       aEvent.type : aEvent.eventType;
 
@@ -593,42 +649,40 @@ function eventQueue(aEventType)
     // Dump DOM event information. Skip a11y event since it is dumped by
     // gA11yEventObserver.
     if (aOrigEvent instanceof nsIDOMEvent) {
       var info = "Event type: " + aOrigEvent.type;
       info += ". Target: " + prettyName(aOrigEvent.originalTarget);
       gLogger.logToDOM(info);
     }
 
-    var currType = this.getEventTypeAsString(aExpectedEventIdx);
-    var currTarget = this.getEventTarget(aExpectedEventIdx);
+    if (!aMatch)
+      return;
 
     var msg = "EQ: ";
-    var emphText = "";
-    if (aMatch) {
-      emphText = "matched ";
+    var emphText = "matched ";
 
-      var consoleMsg = "*****\nEQ matched: " + currType + "\n*****";
-      gLogger.logToConsole(consoleMsg);
+    var currType = this.getEventTypeAsString(aExpectedEventIdx);
+    var currTarget = this.getEventTarget(aExpectedEventIdx);
+    var consoleMsg = "*****\nEQ matched: " + currType + "\n*****";
+    gLogger.logToConsole(consoleMsg);
 
-    } else {
-      msg += "expected";
-    }
     msg += " event, type: " + currType + ", target: " + prettyName(currTarget);
 
     gLogger.logToDOM(msg, true, emphText);
   }
 
   this.mDefEventType = aEventType;
 
   this.mInvokers = new Array();
   this.mIndex = -1;
 
   this.mEventSeq = null;
   this.mEventSeqIdx = -1;
+  this.mEventSeqFinished = false;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Action sequence
 
 /**
  * Deal with action sequence. Used when you need to execute couple of actions
@@ -891,19 +945,20 @@ function synthSelectAll(aNodeOrID, aChec
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Event queue checkers
 
 /**
  * Common invoker checker (see eventSeq of eventQueue).
  */
-function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
+function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg, aIsAsync)
 {
   this.type = aEventType;
+  this.async = aIsAsync;
 
   this.__defineGetter__("target", invokerChecker_targetGetter);
   this.__defineSetter__("target", invokerChecker_targetSetter);
 
   // implementation details
   function invokerChecker_targetGetter()
   {
     if (typeof this.mTarget == "function")
@@ -928,16 +983,25 @@ function invokerChecker(aEventType, aTar
     return prettyName(this.mTarget);
   }
 
   this.mTarget = aTargetOrFunc;
   this.mTargetFuncArg = aTargetFuncArg;
 }
 
 /**
+ * Common invoker checker for async events.
+ */
+function asyncInvokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
+{
+  this.__proto__ = new invokerChecker(aEventType, aTargetOrFunc,
+                                      aTargetFuncArg, true);
+}
+
+/**
  * Text inserted/removed events checker.
  */
 function textChangeChecker(aID, aStart, aEnd, aTextOrFunc, aIsInserted)
 {
   this.target = getNode(aID);
   this.type = aIsInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
 
   this.check = function textChangeChecker_check(aEvent)
--- a/accessible/tests/mochitest/events/docload_wnd.xul
+++ b/accessible/tests/mochitest/events/docload_wnd.xul
@@ -31,28 +31,31 @@
     function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
                         aAbsentExtraState)
     {
       gOpenerWnd.testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
                             aAbsentExtraState);
     }
 
     var invokerChecker = gOpenerWnd.invokerChecker;
+    var asyncInvokerChecker = gOpenerWnd.asyncInvokerChecker;
 
     const STATE_BUSY = gOpenerWnd.STATE_BUSY;
     const EVENT_DOCUMENT_LOAD_COMPLETE =
       gOpenerWnd.EVENT_DOCUMENT_LOAD_COMPLETE;
     const EVENT_DOCUMENT_RELOAD = gOpenerWnd.EVENT_DOCUMENT_RELOAD;
     const EVENT_DOCUMENT_LOAD_STOPPED =
       gOpenerWnd.EVENT_DOCUMENT_LOAD_STOPPED;
     const EVENT_REORDER = gOpenerWnd.EVENT_REORDER;
     const EVENT_STATE_CHANGE = gOpenerWnd.EVENT_STATE_CHANGE;
     const nsIAccessibleStateChangeEvent =
       gOpenerWnd.nsIAccessibleStateChangeEvent;
 
+    //gOpenerWnd.gA11yEventDumpToConsole = true; // debug
+
     ////////////////////////////////////////////////////////////////////////////
     // Hacks to make xul:tabbrowser work.
 
     var handleDroppedLink = null; // needed for tabbrowser usage
 
     Components.utils.import("resource://gre/modules/Services.jsm");
     var XULBrowserWindow = {
       isBusy: false,
@@ -127,17 +130,17 @@
       this.invoke = function loadURIInvoker_invoke()
       {
         gTabBrowser.loadURI(aURI);
       }
 
       this.eventSeq = [
         // We don't expect state change event for busy true since things happen
         // quickly and it's coalesced.
-        new invokerChecker(EVENT_REORDER, getContainer),
+        new asyncInvokerChecker(EVENT_REORDER, getContainer),
         new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
         new stateBusyChecker(false)
       ];
 
       this.getID = function loadURIInvoker_getID()
       {
         return "load uri " + aURI;
       }
@@ -150,17 +153,17 @@
     {
       this.invoke = function clickReloadBtnInvoker_invoke()
       {
         synthesizeMouse(document.getElementById("reloadbtn"), 5, 5, {});
       }
 
       this.eventSeq = [
         new documentReloadChecker(true),
-        new invokerChecker(EVENT_REORDER, getContainer),
+        new asyncInvokerChecker(EVENT_REORDER, getContainer),
         new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
         new stateBusyChecker(false)
       ];
 
       this.getID = function reloadInvoker_getID()
       {
         return "click reload page button";
       }
@@ -173,17 +176,17 @@
     {
       this.invoke = function reloadInvoker_invoke()
       {
         gTabBrowser.reload();
       }
 
       this.eventSeq = [
         new documentReloadChecker(false),
-        new invokerChecker(EVENT_REORDER, getContainer),
+        new asyncInvokerChecker(EVENT_REORDER, getContainer),
         new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
         new stateBusyChecker(false)
       ];
 
       this.getID = function reloadInvoker_getID()
       {
         return "reload page";
       }
@@ -197,17 +200,17 @@
       this.invoke = function loadErrorPageInvoker_invoke()
       {
         gTabBrowser.loadURI(aURL);
       }
 
       this.eventSeq = [
         // We don't expect state change for busy true, load stopped events since
         // things happen quickly and it's coalesced.
-        new invokerChecker(EVENT_REORDER, getContainer),
+        new asyncInvokerChecker(EVENT_REORDER, getContainer),
         new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, getDocument),
         new stateBusyChecker(false)
       ];
 
       this.getID = function loadErrorPageInvoker_getID()
       {
         return "load error page: '" + aURLDescr + "'";
       }
--- a/accessible/tests/mochitest/treeupdate/test_doc.html
+++ b/accessible/tests/mochitest/treeupdate/test_doc.html
@@ -352,16 +352,46 @@
       }
 
       this.getID = function insertBodyToIFrameDoc_getID()
       {
         return "insert body element";
       }
     }
 
+    function changeSrc(aID)
+    {
+      this.containerNode = getNode(aID);
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.containerNode)
+      ];
+
+      this.invoke = function changeSrc_invoke()
+      {
+        this.containerNode.src = "data:text/html,<html><input></html>";
+      }
+
+      this.finalCheck = function changeSrc_finalCheck()
+      {
+        var tree =
+          { INTERNAL_FRAME: [
+            { DOCUMENT: [
+              { ENTRY: [ ] }
+            ] };
+          ] };
+        testAccessibleTree(this.containerNode, tree);
+      }
+
+      this.getID() = function changeSrc_getID()
+      {
+        return "change src on iframe";
+      }
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     //gA11yEventDumpID = "eventdump"; // debug stuff
 
     var gQueue = null;
 
     function doTest()
@@ -373,32 +403,36 @@
       gQueue.push(new replaceIFrameBody("iframe"));
       gQueue.push(new openIFrameDoc("iframe"));
       gQueue.push(new closeIFrameDoc("iframe"));
       gQueue.push(new removeHTMLFromIFrameDoc("iframe"));
       gQueue.push(new insertHTMLToIFrameDoc("iframe"));
       gQueue.push(new removeBodyFromIFrameDoc("iframe"));
       gQueue.push(new insertElmUnderDocElmWhileBodyMissed("iframe"));
       gQueue.push(new insertBodyToIFrameDoc("iframe"));
+      gQueue.push(new changeSrc("iframe"));
 
       gQueue.invoke(); // SimpleTest.finish() will be called in the end
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank"
      title="Update accessible tree when root element is changed"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=606082">Mozilla Bug 606082</a>
   <a target="_blank"
      title="Elements inserted outside the body aren't accessible"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=608887">Mozilla Bug 608887</a>
+  <a target="_blank"
+     title="Reorder event for document must be fired after document initial tree creation"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=669263">Mozilla Bug 669263</a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <iframe id="iframe"></iframe>
 
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6792,19 +6792,19 @@ var gPluginHandler = {
   managePlugins: function (aEvent) {
     BrowserOpenAddonsMgr("addons://list/plugin");
   },
 
   // Callback for user clicking "submit a report" link
   submitReport : function(pluginDumpID, browserDumpID) {
     // The crash reporter wants a DOM element it can append an IFRAME to,
     // which it uses to submit a form. Let's just give it gBrowser.
-    this.CrashSubmit.submit(pluginDumpID, gBrowser, null, null);
+    this.CrashSubmit.submit(pluginDumpID);
     if (browserDumpID)
-      this.CrashSubmit.submit(browserDumpID, gBrowser, null, null);
+      this.CrashSubmit.submit(browserDumpID);
   },
 
   // Callback for user clicking a "reload page" link
   reloadPage: function (browser) {
     browser.reload();
   },
 
   // Callback for user clicking the help icon
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -37,17 +37,17 @@
 # ***** 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() {
+__defineGetter__("webNavigation", function () {
   return docShell.QueryInterface(Ci.nsIWebNavigation);
 });
 
-addMessageListener("WebNavigation:LoadURI", function(message) {
+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/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1367,25 +1367,29 @@
             // activeness in the tab switcher.
             b.docShellIsActive = false;
 
             // Check if we're opening a tab related to the current tab and
             // move it to after the current tab.
             // aReferrerURI is null or undefined if the tab is opened from
             // an external application or bookmark, i.e. somewhere other
             // than the current tab.
-            if ((aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) &&
-                Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) {
+            if (aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) {
               let newTabPos = (this._lastRelatedTab ||
                                this.selectedTab)._tPos + 1;
+
               if (this._lastRelatedTab)
                 this._lastRelatedTab.owner = null;
               else
                 t.owner = this.selectedTab;
-              this.moveTabTo(t, newTabPos);
+
+              if (!this.selectedTab.pinned &&
+                  Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent"))
+                this.moveTabTo(t, newTabPos);
+
               this._lastRelatedTab = t;
             }
 
             return t;
           ]]>
         </body>
       </method>
 
--- 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;
@@ -117,25 +119,16 @@ function GroupItem(listOfEls, options) {
 
   this.bounds = $container.bounds();
 
   this.isDragging = false;
   $container
     .css({zIndex: -100})
     .appendTo("body");
 
-  // ___ New Tab Button
-  this.$ntb = iQ("<div>")
-    .addClass('newTabButton')
-    .click(function() {
-      self.newTab();
-    })
-    .attr('title', tabviewString('groupItem.newTabButton'))
-    .appendTo($container);
-
   // ___ Resizer
   this.$resizer = iQ("<div>")
     .addClass('resizer')
     .appendTo($container)
     .hide();
 
   // ___ Titlebar
   var html =
@@ -813,25 +806,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", self._onChildClose.bind(self));
+        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 });
       });
@@ -1004,17 +997,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", this._onChildClose.bind(this));
+        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);
 
@@ -1105,17 +1098,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;
@@ -1653,19 +1646,55 @@ GroupItem.prototype = Utils.extend(new I
     }
   },
 
   // ----------
   // Function: _addHandlers
   // Helper routine for the constructor; adds various event handlers to the container.
   _addHandlers: function GroupItem__addHandlers(container) {
     let self = this;
+    let lastMouseDownTarget;
 
-    var dropIndex = false;
-    var dropSpaceTimer = null;
+    container.mousedown(function(e) {
+      let target = e.target;
+      // only set the last mouse down target if it is a left click, not on the
+      // close button, not on the new tab button, not on the title bar and its
+      // element
+      if (Utils.isLeftClick(e) &&
+          self.$closeButton[0] != target &&
+          self.$titlebar[0] != target &&
+          !self.$titlebar.contains(target) &&
+          !self.$appTabTray.contains(target)) {
+        lastMouseDownTarget = target;
+      } else {
+        lastMouseDownTarget = null;
+      }
+    });
+    container.mouseup(function(e) {
+      let same = (e.target == lastMouseDownTarget);
+      lastMouseDownTarget = null;
+
+      if (same && !self.isDragging) {
+        if (gBrowser.selectedTab.pinned &&
+            UI.getActiveTab() != self.getActiveTab() &&
+            self.getChildren().length > 0) {
+          UI.setActive(self, { dontSetActiveTabInGroup: true });
+          UI.goToTab(gBrowser.selectedTab);
+        } else {
+          let tabItem = self.getTopChild();
+          if (tabItem)
+            tabItem.zoomIn();
+          else
+            self.newTab();
+        }
+      }
+    });
+
+    let dropIndex = false;
+    let dropSpaceTimer = null;
 
     // When the _dropSpaceActive flag is turned on on a group, and a tab is
     // dragged on top, a space will open up.
     this._dropSpaceActive = false;
 
     this.dropOptions.over = function GroupItem_dropOptions_over(event) {
       iQ(this.container).addClass("acceptsDrop");
     };
--- 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
@@ -139,21 +139,16 @@ body {
 
 .activeVisibleTrench {
   z-index: -102;
 }
 
 /* Other
 ----------------------------------*/
 
-.newTabButton {
-  position: absolute !important;
-  z-index: 99999;
-}
-
 .titlebar {
   position: absolute;
 }
 
 .title-shield {
   position: absolute;
   left: 0;
   top: 0;
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -395,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");
@@ -434,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
@@ -465,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
@@ -490,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;
@@ -511,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();
     }
 
--- 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_locationBarExternalLoad.js
+++ b/browser/base/content/test/browser_locationBarExternalLoad.js
@@ -41,16 +41,20 @@ function testURL(url, loadFunc, endFunc)
   registerCleanupFunction(function () {
     gBrowser.removeTab(tab);
   });
   addPageShowListener(function () {
     let pagePrincipal = gBrowser.contentPrincipal;
     loadFunc(url);
 
     addPageShowListener(function () {
+      let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
+      is(fm.focusedElement, null, "should be no focused element");
+      is(fm.focusedWindow, gBrowser.contentWindow, "content window should be focused");
+
       ok(!gBrowser.contentPrincipal.equals(pagePrincipal),
          "load of " + url + " by " + loadFunc.name + " should produce a page with a different principal");
       endFunc();
     });
   });
 }
 
 function addPageShowListener(func) {
--- a/browser/base/content/test/browser_relatedTabs.js
+++ b/browser/base/content/test/browser_relatedTabs.js
@@ -73,10 +73,19 @@ function test() {
   testPosition(2, 5, "tab with referrer opened immediately to the right");
   testPosition(3, 1, "next tab with referrer opened further to the right");
   testPosition(4, 4, "tab selection changed, tab opens immediately to the right");
   testPosition(5, 6, "blank tab with referrer opens to the right of 3rd original tab where removed tab was");
   testPosition(6, 2, "tab has moved, new tab opens immediately to the right");
   testPosition(7, 8, "blank tab without referrer opens at the end");
   testPosition(8, 9, "tab without referrer opens at the end");
 
+  gBrowser.selectedTab = tabs[0];
+  gBrowser.pinTab(gBrowser.selectedTab);
+  addTab("http://mochi.test:8888/#8", gBrowser.currentURI);
+  testPosition(9, 10, "tab with referrer should open at the end when the selected tab is pinned");
+  gBrowser.selectedTab = tabs[9];
+  gBrowser.removeTab(tabs.pop());
+  is(gBrowser.selectedTab, tabs[0],
+     "opening a tab from a pinned tab, selecting it and closing it should go back to the pinned tab");
+
   tabs.forEach(gBrowser.removeTab, gBrowser);
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_save_video.js
@@ -0,0 +1,90 @@
+/* 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() {
+  waitForExplicitFinish();
+
+  gBrowser.loadURI("http://mochi.test:8888/browser/browser/base/content/test/bug564387.html");
+
+  registerCleanupFunction(function () {
+    gBrowser.addTab();
+    gBrowser.removeCurrentTab();
+  });
+
+  gBrowser.addEventListener("pageshow", function pageShown(event) {
+    if (event.target.location == "about:blank")
+      return;
+    gBrowser.removeEventListener("pageshow", pageShown);
+
+    executeSoon(function () {
+      document.addEventListener("popupshown", contextMenuOpened);
+
+      var video1 = gBrowser.contentDocument.getElementById("video1");
+      EventUtils.synthesizeMouseAtCenter(video1,
+                                         { type: "contextmenu", button: 2 },
+                                         gBrowser.contentWindow);
+    });
+  });
+
+  function contextMenuOpened(event) {
+    event.currentTarget.removeEventListener("popupshown", contextMenuOpened);
+
+    // Create the folder the video will be saved into.
+    var destDir = createTemporarySaveDirectory();
+
+    mockFilePickerSettings.destDir = destDir;
+    mockFilePickerSettings.filterIndex = 1; // kSaveAsType_URL
+    mockFilePickerRegisterer.register();
+
+    mockTransferCallback = onTransferComplete;
+    mockTransferRegisterer.register();
+
+    registerCleanupFunction(function () {
+      mockTransferRegisterer.unregister();
+      mockFilePickerRegisterer.unregister();
+      destDir.remove(true);
+    });
+
+    // Select "Save Video As" option from context menu
+    var saveVideoCommand = document.getElementById("context-savevideo");
+    saveVideoCommand.doCommand();
+
+    event.target.hidePopup();
+  }
+
+  function onTransferComplete(downloadSuccess) {
+    ok(downloadSuccess, "Video file should have been downloaded successfully");
+
+    // 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");
+
+    finish();
+  }
+}
+
+Cc["@mozilla.org/moz/jssubscript-loader;1"]
+  .getService(Ci.mozIJSSubScriptLoader)
+  .loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockTransfer.js",
+                 this);
+
+Cc["@mozilla.org/moz/jssubscript-loader;1"]
+  .getService(Ci.mozIJSSubScriptLoader)
+  .loadSubScript("chrome://mochitests/content/browser/toolkit/content/tests/browser/common/mockFilePicker.js",
+                 this);
+
+function createTemporarySaveDirectory() {
+  var saveDir = Cc["@mozilla.org/file/directory_service;1"]
+                  .getService(Ci.nsIProperties)
+                  .get("TmpD", Ci.nsIFile);
+  saveDir.append("testsavedir");
+  if (!saveDir.exists())
+    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+  return saveDir;
+}
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
@@ -144,16 +144,18 @@ 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_click_group.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 \
@@ -161,15 +163,14 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_search.js \
                  browser_tabview_snapping.js \
                  browser_tabview_startup_transitions.js \
                  browser_tabview_undo_group.js \
                  dummy_page.html \
                  head.js \
                  search1.html \
                  search2.html \
-                 test_bug599626.html \
                  test_bug600645.html \
                  test_bug644097.html \
                  $(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/base/content/test/tabview/browser_tabview_bug588265.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug588265.js
@@ -1,98 +1,76 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+let contentWindow;
+let groupItemTwoId;
+
 function test() {
   waitForExplicitFinish();
-
-  window.addEventListener("tabviewshown", setup, false);
-  TabView.toggle();
+  
+  registerCleanupFunction(function() {
+    while (gBrowser.tabs[1])
+      gBrowser.removeTab(gBrowser.tabs[1]);
+    hideTabView(function() {});
+  });
+  gBrowser.loadOneTab("about:blank", { inBackground: true });
+  showTabView(setup);
 }
 
 function setup() {
-  window.removeEventListener("tabviewshown", setup, false);
+  registerCleanupFunction(function() {
+    let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId);
+    if (groupItem)
+      closeGroupItem(groupItem, function() {}); 
+  });
 
-  let contentWindow = document.getElementById("tab-view").contentWindow;
+  let contentWindow = TabView.getContentWindow();
   is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group");
 
   let groupItemOne = contentWindow.GroupItems.groupItems[0];
-  // add a blank tab to group one.
-  createNewTabItemInGroupItem(groupItemOne, contentWindow, function() { 
-    is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items");
-
-    // create group two with a blank tab.
-    let groupItemTwo = createEmptyGroupItem(contentWindow, 250, 250, 40);
-    createNewTabItemInGroupItem(groupItemTwo, contentWindow, function() {
-      // start the first test.
-      testGroups(groupItemOne, groupItemTwo, contentWindow);
-    });
-  });
-}
+  is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items");
 
-function createNewTabItemInGroupItem(groupItem, contentWindow, callback) {
-  // click on the + button to create a blank tab in group item
-  let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
-  ok(newTabButton[0], "New tab button exists");
-
-  let onTabViewHidden = function() {
-    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-
-    ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
-    TabView.toggle();
-  };
-  let onTabViewShown = function() {
-    window.removeEventListener("tabviewshown", onTabViewShown, false);
-
-    ok(TabView.isVisible(), "Tab View is visible");
-    callback();
-  };
-  window.addEventListener("tabviewhidden", onTabViewHidden, false);
-  window.addEventListener("tabviewshown", onTabViewShown, false);
-  EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
+  let groupItemTwo = createGroupItemWithBlankTabs(window, 250, 250, 40, 1);
+  groupItemTwoId = groupItemTwo.id;
+  testGroups(groupItemOne, groupItemTwo, contentWindow);
 }
 
 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);
+    whenTabViewIsHidden(function() {
       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");
-
+      closeGroupItem(groupItemTwo, function() {
         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();
       });
-      gBrowser.removeTab(groupItemTwo.getChild(0).tab);
-      groupItemTwo.close();
-    }
-    window.addEventListener("tabviewhidden", onTabViewHidden, false);
+    });
     EventUtils.synthesizeKey("t", { accelKey: true });
   });
   // close a tab item in group one
   tabItem.close();
 }
--- a/browser/base/content/test/tabview/browser_tabview_bug590606.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug590606.js
@@ -1,51 +1,53 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 let originalTab;
 let newTabOne;
+let groupItemTwoId;
 
 function test() {
   waitForExplicitFinish();
 
   originalTab = gBrowser.visibleTabs[0];
   // add a tab to the existing group.
   newTabOne = gBrowser.addTab();
 
-  let onTabviewShown = function() {
-    window.removeEventListener("tabviewshown", onTabviewShown, false);
+  registerCleanupFunction(function() {
+    while (gBrowser.tabs[1])
+      gBrowser.removeTab(gBrowser.tabs[1]);
+    hideTabView(function() {});
+  });
 
-    let contentWindow = document.getElementById("tab-view").contentWindow;
+  showTabView(function() {
+    let contentWindow = TabView.getContentWindow();
+
+    registerCleanupFunction(function() {
+      let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId);
+      if (groupItem)
+        closeGroupItem(groupItem, function() {});
+    });
 
     is(contentWindow.GroupItems.groupItems.length, 1, 
        "There is one group item on startup");
     let groupItemOne = contentWindow.GroupItems.groupItems[0];
     is(groupItemOne.getChildren().length, 2, 
        "There should be two tab items in that group.");
     is(gBrowser.selectedTab, groupItemOne.getChild(0).tab,
        "The currently selected tab should be the first tab in the groupItemOne");
 
     // create another group with a tab.
-    let groupItemTwo = createEmptyGroupItem(contentWindow, 300, 300, 200);
-
-    let onTabViewHidden = function() {
-      window.removeEventListener("tabviewhidden", onTabViewHidden, false);
+    let groupItemTwo = createGroupItemWithBlankTabs(window, 300, 300, 200, 1);
+    groupItemTwoId = groupItemTwoId;
+    hideTabView(function() {
       // start the test
       testGroupSwitch(contentWindow, groupItemOne, groupItemTwo);
-    };
-    window.addEventListener("tabviewhidden", onTabViewHidden, false);
-
-    // click on the + button
-    let newTabButton = groupItemTwo.container.getElementsByClassName("newTabButton");
-    ok(newTabButton[0], "New tab button exists");
-    EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
-  };
-  window.addEventListener("tabviewshown", onTabviewShown, false);
-  TabView.toggle();
+    });
+  });
 }
 
 function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) {
   is(gBrowser.selectedTab, groupItemTwo.getChild(0).tab,
      "The currently selected tab should be the only tab in the groupItemTwo");
 
   // switch to groupItemOne
   let tabItem = contentWindow.GroupItems.getNextGroupItemTab(false);
--- 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_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_bug595560.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595560.js
@@ -18,80 +18,54 @@ function test() {
     ok(win.TabView.isVisible(), "Tab View is visible");
     afterAllTabItemsUpdated(testOne, win);
   };
 
   newWindowWithTabView(onShow, onLoad);
 }
 
 function testOne() {
-  whenSearchEnabledAndDisabled(testTwo);
+  hideSearchWhenSearchEnabled(testTwo);
   // press cmd/ctrl F
   EventUtils.synthesizeKey("f", {accelKey: true}, cw);
 }
 
 function testTwo() {
-  whenSearchEnabledAndDisabled(testThree);
+  hideSearchWhenSearchEnabled(testThree);
   // press /
   EventUtils.synthesizeKey("VK_SLASH", {}, cw);
 }
 
 function testThree() {
-  let onTabViewShown = function () {
-    is(cw.UI.getActiveTab(), groupItem.getChild(0), 
-       "The active tab is newly created tab item");
+  ok(win.TabView.isVisible(), "Tab View is visible");
+  // create another group with a tab.
+  let groupItem = createGroupItemWithBlankTabs(win, 300, 300, 200, 1);
+  is(cw.UI.getActiveTab(), groupItem.getChild(0), 
+     "The active tab is newly created tab item");
 
-    let onSearchEnabled = function () {
-      let doc = cw.document;
-      let searchBox = cw.iQ("#searchbox");
-      let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0];
-      ok(hasFocus, "The search box has focus");
-
-      let tab = win.gBrowser.tabs[1];
-      searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML);
-
-      cw.performSearch();
+  whenSearchIsEnabled(function () {
+    let doc = cw.document;
+    let searchBox = cw.iQ("#searchbox");
+    let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0];
+    ok(hasFocus, "The search box has focus");
 
-      whenTabViewIsHidden(function () {
-        is(tab, win.gBrowser.selectedTab, "The search result tab is shown");
-        waitForFocus(finish);
-      }, win);
+    let tab = win.gBrowser.tabs[1];
+    searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML);
 
-      // use the tabview menu (the same as pressing cmd/ctrl + e)
-      win.document.getElementById("menu_tabview").doCommand();
-    };
+    cw.performSearch();
 
-    whenSearchEnabled(onSearchEnabled);
-    EventUtils.synthesizeKey("VK_SLASH", {}, cw);
-  };
+    whenTabViewIsHidden(function () {
+      is(tab, win.gBrowser.selectedTab, "The search result tab is shown");
+      finish()
+    }, win);
 
-  whenTabViewIsHidden(function () {
-    showTabView(onTabViewShown, win);
+    // use the tabview menu (the same as pressing cmd/ctrl + e)
+    win.document.getElementById("menu_tabview").doCommand();
   }, win);
-
-  // click on the + button
-  let groupItem = createEmptyGroupItem(cw, 300, 300, 200);
-  let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
-  ok(newTabButton[0], "New tab button exists");
-
-  EventUtils.sendMouseEvent({type: "click"}, newTabButton[0], cw);
+  EventUtils.synthesizeKey("VK_SLASH", {}, cw);
 }
 
-function whenSearchEnabledAndDisabled(callback) {
-  whenSearchEnabled(function () {
-    whenSearchDisabled(callback);
-    cw.hideSearch();
-  });
+function hideSearchWhenSearchEnabled(callback) {
+  whenSearchIsEnabled(function() {
+    hideSearch(callback, win);
+  }, win);
 }
 
-function whenSearchEnabled(callback) {
-  cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() {
-    cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false);
-    callback();
-  }, false);
-}
-
-function whenSearchDisabled(callback) {
-  cw.addEventListener("tabviewsearchdisabled", function onSearchDisabled() {
-    cw.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false);
-    callback();
-  }, false);
-}
--- a/browser/base/content/test/tabview/browser_tabview_bug595930.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug595930.js
@@ -21,18 +21,18 @@ 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);
@@ -40,21 +40,16 @@ function onTabViewWindowLoaded() {
     // 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);
     });
   });
 
-  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_bug599626.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug599626.js
@@ -1,161 +1,87 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let handleDialog;
-let timer; // keep in outer scope so it's not GC'd before firing
+const TEST_URL = 'data:text/html,<script>window.onbeforeunload=' +
+                 'function(e){e.returnValue="?"}</script>';
 
 function test() {
   waitForExplicitFinish();
-
-  window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
-  TabView.toggle();
+  showTabView(onTabViewShown);
 }
 
-function onTabViewWindowLoaded() {
-  window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
-
-  let contentWindow = document.getElementById("tab-view").contentWindow;
+function onTabViewShown() {
+  let contentWindow = TabView.getContentWindow();
   let groupItemOne = contentWindow.GroupItems.getActiveGroupItem();
-
-  // Create a group and make it active
-  let box = new contentWindow.Rect(10, 10, 300, 300);
-  let groupItemTwo = new contentWindow.GroupItem([], { bounds: box });
-  contentWindow.UI.setActive(groupItemTwo);
+  let groupItemTwo = createGroupItemWithTabs(window, 300, 300, 10, [TEST_URL]);
 
-  let testTab = 
-    gBrowser.addTab(
-      "http://mochi.test:8888/browser/browser/base/content/test/tabview/test_bug599626.html");
-  let browser = gBrowser.getBrowserForTab(testTab);
-  let onLoad = function() {
-    browser.removeEventListener("load", onLoad, true);
-
+  afterAllTabsLoaded(function () {
     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");
+  whenDialogOpened(function (dialog) {
+    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);
-
+      showTabView(function () {
         // start the next test
         testLeavePage(contentWindow, groupItemOne, groupItemTwo);
-      };
-      window.addEventListener("tabviewshown", onTabViewShown, false);
-      TabView.toggle();
+      });
     });
+
     // stay on page
-    doc.documentElement.getButton("cancel").click();
+    dialog.cancelDialog();
   });
+
+  closeGroupItem(groupItemTwo);
 }
 
 function testLeavePage(contentWindow, groupItemOne, groupItemTwo) {
-  setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) {
+  whenDialogOpened(function (dialog) {
     // 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);
-        finish();
-      };
-      window.addEventListener("tabviewhidden", endGame, false);
+      hideTabView(finish);
     });
 
     // Leave page
-    doc.documentElement.getButton("accept").click();
+    dialog.acceptDialog();
   });
-}
-
-function setupAndRun(contentWindow, groupItemOne, groupItemTwo, callback) {
-  let closeButton = groupItemTwo.container.getElementsByClassName("close");
-  ok(closeButton[0], "Group close button exists");
-  // click the close button
-  EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
 
-  let onTabViewHidden = function() {
-    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-
-    handleDialog = function(doc) {
-      callback(doc);
-    };
-    startCallbackTimer();
-  };
-  window.addEventListener("tabviewhidden", onTabViewHidden, false);
-
-  let tabItem = groupItemOne.getChild(0);
-  tabItem.zoomIn();
+  closeGroupItem(groupItemTwo);
 }
 
-// Copied from http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/tests/mochitest/prompt_common.js
-let observer = {
-  QueryInterface : function (iid) {
-    const interfaces = [Ci.nsIObserver, Ci.nsISupports, Ci.nsISupportsWeakReference];
-
-    if (!interfaces.some( function(v) { return iid.equals(v) } ))
-      throw Components.results.NS_ERROR_NO_INTERFACE;
-    return this;
-  },
+// ----------
+function whenDialogOpened(callback) {
+  let listener = {
+    onCloseWindow: function () {},
+    onWindowTitleChange: function () {},
 
-  observe : function (subject, topic, data) {
-    let doc = getDialogDoc();
-    if (doc)
-      handleDialog(doc);
-    else
-      startCallbackTimer(); // try again in a bit
-  }
-};
-
-function startCallbackTimer() {
-   // Delay before the callback twiddles the prompt.
-   const dialogDelay = 10;
-
-   // Use a timer to invoke a callback to twiddle the authentication dialog
-   timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-   timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT);
-}
+    onOpenWindow: function (xulWin) {
+      let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
+                   .getInterface(Ci.nsIDOMWindow);
 
-function getDialogDoc() {
-  // Find the <browser> which contains notifyWindow, by looking
-  // through all the open windows and all the <browsers> in each.
-  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
-            getService(Ci.nsIWindowMediator);
-  let enumerator = wm.getXULWindowEnumerator(null);
+      whenWindowLoaded(domWin, function () {
+        let dialog = domWin.document.querySelector("dialog");
+        if (dialog) {
+          Services.wm.removeListener(listener);
+          callback(dialog);
+        }
+      });
+    }
+  };
 
-   while (enumerator.hasMoreElements()) {
-     let win = enumerator.getNext();
-     let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell;
- 
-     let containedDocShells = windowDocShell.getDocShellEnumerator(
-                                Ci.nsIDocShellTreeItem.typeChrome,
-                                Ci.nsIDocShell.ENUMERATE_FORWARDS);
-     while (containedDocShells.hasMoreElements()) {
-       // Get the corresponding document for this docshell
-       let childDocShell = containedDocShells.getNext();
-       // We don't want it if it's not done loading.
-       if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE)
-         continue;
-       let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell).
-                      contentViewer.DOMDocument;
-
-       if (childDoc.location.href == "chrome://global/content/commonDialog.xul")
-         return childDoc;
-     }
-   }
- 
-  return null;
+  Services.wm.addListener(listener);
 }
--- 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';
--- 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_bug630157.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug630157.js
@@ -60,21 +60,16 @@ function test() {
     let container = groupItem.container;
     simulateDoubleClick(container, 1);
     assertNumberOfTabs(1);
 
     // simulate double click with right mouse button
     simulateDoubleClick(container, 2);
     assertNumberOfTabs(1);
 
-    // simulate double click with left mouse button
-    let container = groupItem.container;
-    simulateDoubleClick(container);
-    assertNumberOfTabs(1);
-
     groupItem.close();
     hideTabView(finishTest);
   }
 
   waitForExplicitFinish();
   registerCleanupFunction(function () TabView.hide());
 
   showTabView(function () {
--- 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_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);
+}
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_click_group.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+let contentWindow;
+let groupItem;
+let groupItemId;
+
+function test() {
+  waitForExplicitFinish();
+
+  registerCleanupFunction(function() {
+    contentWindow.gPrefBranch.clearUserPref("animate_zoom");
+    let createdGroupItem = contentWindow.GroupItems.groupItem(groupItemId)
+    if (createdGroupItem)
+      closeGroupItem(createdGroupItem, function() {});
+    hideTabView(function() {});
+  });
+
+  showTabView(function() {
+    contentWindow = TabView.getContentWindow();
+    groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
+    groupItemId = groupItem.id;
+    testMouseClickOnEmptyGroupItem();
+  });
+}
+
+function testMouseClickOnEmptyGroupItem() {
+  whenTabViewIsHidden(function() {
+    is(groupItem.getChildren().length, 1, "The group item contains one tab item now");
+    showTabView(testDraggingWithinGroupItem);
+  });
+  is(groupItem.getChildren().length, 0, "The group item doesn't contain any tab items");
+  EventUtils.sendMouseEvent({ type: "mousedown" }, groupItem.container, contentWindow);
+  EventUtils.sendMouseEvent({ type: "mouseup" }, groupItem.container, contentWindow);
+}
+
+function testDraggingWithinGroupItem() {
+  let target = groupItem.container;
+  contentWindow.gPrefBranch.setBoolPref("animate_zoom", false);
+
+  // stimulate drag and drop
+  EventUtils.sendMouseEvent( {type: "mousedown" }, target, contentWindow);
+  EventUtils.synthesizeMouse(target, 10, 10, { type: "mousemove" }, contentWindow);
+  ok(groupItem.isDragging, "The group item is being dragged")
+
+  EventUtils.sendMouseEvent({ type: "mouseup" }, target, contentWindow);
+  ok(!groupItem.isDragging, "The dragging is competely");
+
+  executeSoon(function() {
+    ok(TabView.isVisible(), "The tab view is still visible after dragging");
+    contentWindow.gPrefBranch.clearUserPref("animate_zoom");
+
+    testMouseClickOnGroupItem();
+  });
+}
+
+function testMouseClickOnGroupItem() {
+  whenTabViewIsHidden(function() {
+    is(groupItem.getChildren().length, 1, "The group item still contains one tab item");
+
+    closeGroupItem(groupItem, function() {
+      hideTabView(finish);
+    });
+  });
+  EventUtils.sendMouseEvent({ type: "mousedown" }, groupItem.container, contentWindow);
+  EventUtils.sendMouseEvent({ type: "mouseup" }, groupItem.container, contentWindow);
+}
+
--- 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
@@ -1,26 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
 
-  window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
-  TabView.toggle();
+  showTabView(onTabViewWindowLoaded);
 }
 
 let originalGroupItem = null;
 let originalTab = null;
 
 function onTabViewWindowLoaded() {
-  window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
   ok(TabView.isVisible(), "Tab View is visible");
 
-  let contentWindow = document.getElementById("tab-view").contentWindow;
+  let contentWindow = TabView.getContentWindow();
 
   is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item on startup");
   originalGroupItem = contentWindow.GroupItems.groupItems[0];
   is(originalGroupItem.getChildren().length, 1, "There should be one Tab Item in that group.");
   contentWindow.UI.setActive(originalGroupItem);
 
   [originalTab] = gBrowser.visibleTabs;
 
@@ -32,18 +30,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);
   });
 
@@ -53,77 +51,61 @@ function testEmptyGroupItem(contentWindo
   // click the close button
   EventUtils.synthesizeMouse(closeButton[0], 1, 1, {}, contentWindow);
 }
 
 function testGroupItemWithTabItem(contentWindow) {
   let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
   let tabItemCount = 0;
 
-  let onTabViewHidden = function() {
-    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-
-    is(groupItem.getChildren().length, ++tabItemCount,
-       "The number of children in new tab group is increased by 1");
-
-    ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
-
-    TabView.toggle();
-  };
   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
       // and go into that tab.
       is(gBrowser.tabs.length, 1, "There is only one tab left");
-            
-      let endGame = function() {
-        window.removeEventListener("tabviewhidden", endGame, false);
-        ok(!TabView.isVisible(), "Tab View is hidden");
-        finish();
-      };
-      window.addEventListener("tabviewhidden", endGame, false);
 
       // after the last selected tabitem is closed, there would be not active
       // tabitem on the UI so we set the active tabitem before toggling the 
       // visibility of tabview
       let tabItems = contentWindow.TabItems.getItems();
       ok(tabItems[0], "A tab item exists");
       contentWindow.UI.setActive(tabItems[0]);
 
-      TabView.toggle();
+      hideTabView(function() {
+        ok(!TabView.isVisible(), "Tab View is hidden");
+
+        closeGroupItem(groupItem, finish);
+      });
     });
 
     // remove the tab item.  The code detects mousedown and mouseup so we stimulate here
     let closeButton = tabItem.container.getElementsByClassName("close");
     ok(closeButton, "Tab item close button exists");
 
     EventUtils.sendMouseEvent({ type: "mousedown" }, closeButton[0], contentWindow);
     EventUtils.sendMouseEvent({ type: "mouseup" }, closeButton[0], contentWindow);
+  };
 
-    TabView.toggle();
-  };
-  window.addEventListener("tabviewhidden", onTabViewHidden, false);
-  window.addEventListener("tabviewshown", onTabViewShown, false);
-  
-  // click on the + button
-  let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
-  ok(newTabButton[0], "New tab button exists");
+  whenTabViewIsHidden(function() {
+    is(groupItem.getChildren().length, ++tabItemCount,
+       "The number of children in new tab group is increased by 1");
 
-  EventUtils.synthesizeMouse(newTabButton[0], 1, 1, {}, contentWindow);
+    ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
+    showTabView(onTabViewShown);
+  });
+  groupItem.newTab();
 }
--- 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_startup_transitions.js
+++ b/browser/base/content/test/tabview/browser_tabview_startup_transitions.js
@@ -26,29 +26,34 @@ function test() {
   let onLoad = function() {
     win.removeEventListener("load", onLoad, false);
 
     // a few shared references
     let tabViewWindow = null;
     let transitioned = 0;
 
     let initCallback = function() {
-      tabViewWindow = win.TabView._window;
+      tabViewWindow = win.TabView.getContentWindow();
       function onTransitionEnd(event) {
         transitioned++;
         info(transitioned);
       }
       tabViewWindow.document.addEventListener("transitionend", onTransitionEnd, false);
 
-      showTabView(function() {
+      // don't use showTabView() here because we only want to check whether 
+      // zoom out animation happens. Other animations would happen before
+      // the callback as waitForFocus() was added to showTabView() in head.js
+      let onTabViewShown = function() {
+        tabViewWindow.removeEventListener("tabviewshown", onTabViewShown, false);
+        tabViewWindow.document.removeEventListener("transitionend", onTransitionEnd, false);
+
         ok(!transitioned, "There should be no transitions");
 
-        tabViewWindow.document.removeEventListener(
-          "transitionend", onTransitionEnd, false);
-
         finish();
-      }, win);
+      };
+      tabViewWindow.addEventListener("tabviewshown", onTabViewShown, false);
+      win.TabView.toggle();
     };
 
     win.TabView._initFrame(initCallback);
   }
   win.addEventListener("load", onLoad, false);
 }
--- a/browser/base/content/test/tabview/browser_tabview_undo_group.js
+++ b/browser/base/content/test/tabview/browser_tabview_undo_group.js
@@ -1,76 +1,64 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   waitForExplicitFinish();
 
-  window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
-  TabView.toggle();
+  registerCleanupFunction(function() {
+    while (gBrowser.tabs[1])
+      gBrowser.removeTab(gBrowser.tabs[1]);
+    hideTabView(function() {});
+  });
+  showTabView(onTabViewWindowLoaded);
 }
 
 function onTabViewWindowLoaded() {
-  window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
   ok(TabView.isVisible(), "Tab View is visible");
 
-  let contentWindow = document.getElementById("tab-view").contentWindow;
+  let contentWindow = TabView.getContentWindow();
+
+  registerCleanupFunction(function() {
+    let groupItem = contentWindow.GroupItems.groupItem(groupItemId);
+    if (groupItem)
+      closeGroupItem(groupItem, function() {});
+  });
 
   // create a group item
-  let box = new contentWindow.Rect(20, 400, 300, 300);
-  let groupItem = new contentWindow.GroupItem([], { bounds: box });
-
-  // create a tab item in the new group
-  let onTabViewHidden = function() {
-    window.removeEventListener("tabviewhidden", onTabViewHidden, false);
-
-    ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab");
-    // show tab view
-    TabView.toggle();
-  };
-  let onTabViewShown = function() {
-    window.removeEventListener("tabviewshown", onTabViewShown, false);
-
-    is(groupItem.getChildren().length, 1, "The new group has a tab item");
-    // start the tests
-    waitForFocus(function() {
-      testUndoGroup(contentWindow, groupItem);
-    }, contentWindow);
-  };
-  window.addEventListener("tabviewhidden", onTabViewHidden, false);
-  window.addEventListener("tabviewshown", onTabViewShown, false);
-
-  // click on the + button
-  let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
-  ok(newTabButton[0], "New tab button exists");
-
-  EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
+  let groupItem = createGroupItemWithBlankTabs(window, 300, 300, 400, 1);
+  groupItemId = groupItem.id;
+  is(groupItem.getChildren().length, 1, "The new group has a tab item");
+  // start the tests
+  waitForFocus(function() {
+    testUndoGroup(contentWindow, groupItem);
+  }, 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 +70,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,35 +90,31 @@ 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();
-    };
-    window.addEventListener("tabviewhidden", endGame, false);
-
     // after the last selected tabitem is closed, there would be not active
     // tabitem on the UI so we set the active tabitem before toggling the 
     // visibility of tabview
     let tabItems = contentWindow.TabItems.getItems();
     ok(tabItems[0], "A tab item exists");
     contentWindow.UI.setActive(tabItems[0]);
 
-    TabView.toggle();
+    hideTabView(function() {
+      ok(!TabView.isVisible(), "Tab View is hidden");
+      finish();
+    });
   });
 
   let closeButton = groupItem.container.getElementsByClassName("close");
   ok(closeButton[0], "Group item close button exists");
   EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow);
 }
--- a/browser/base/content/test/tabview/head.js
+++ b/browser/base/content/test/tabview/head.js
@@ -27,38 +27,41 @@ function createGroupItemWithTabs(win, wi
   // add blank items
   contentWindow.UI.setActive(groupItem);
   let t = 0;
   urls.forEach( function(url) {
     let newItem = win.gBrowser.loadOneTab(url)._tabViewTabItem;
     ok(newItem.container, "Created element "+t+":"+newItem.container);
     ++t;
   });
+  // to set one of tabItem to be active since we load tabs into a group 
+  // in a non-standard flow.
+  contentWindow.UI.setActive(groupItem);
   return groupItem;
 }
 
 // ----------
 function createGroupItemWithBlankTabs(win, width, height, padding, numNewTabs, animate) {
   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();
 }
 
 // ----------
@@ -128,21 +131,23 @@ function afterAllTabsLoaded(callback, wi
     executeSoon(callback);
 }
 
 // ----------
 function showTabView(callback, win) {
   win = win || window;
 
   if (win.TabView.isVisible()) {
-    callback();
+    waitForFocus(callback, win);
     return;
   }
 
-  whenTabViewIsShown(callback, win);
+  whenTabViewIsShown(function() {
+    waitForFocus(callback, win);
+  }, win);
   win.TabView.show();
 }
 
 // ----------
 function hideTabView(callback, win) {
   win = win || window;
 
   if (!win.TabView.isVisible()) {
@@ -217,62 +222,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() {
@@ -337,13 +342,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();
   });
 }
deleted file mode 100644
--- a/browser/base/content/test/tabview/test_bug599626.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<html>
-  <script>
-  window.onbeforeunload = function(event){
-    event.returnValue = 'Confirmation? ';
-  }
-  </script>
-  <body>
-    Test page
-  </body>
-</html>
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -322,47 +322,44 @@
             // inheriting the currently loaded document's principal, unless this
             // URL is marked as safe to inherit (e.g. came from a bookmark
             // keyword).
             if (!mayInheritPrincipal)
               flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
             gBrowser.loadURIWithFlags(url, flags, null, null, postData);
           }
 
+          // Focus the content area before triggering loads, since if the load
+          // occurs in a new tab, we want focus to be restored to the content
+          // area when the current tab is re-selected.
+          gBrowser.selectedBrowser.focus();
+
           if (aTriggeringEvent instanceof MouseEvent) {
             // We have a mouse event (from the go button), so use the standard
             // UI link behaviors
             let where = whereToOpenLink(aTriggeringEvent, false, false);
             if (where == "current") {
               loadCurrent();
             } else {
               this.handleRevert();
-              content.focus();
               openUILinkIn(url, where,
                            { allowThirdPartyFixup: true, postData: postData });
             }
-            return;
-          }
-
-          if (aTriggeringEvent &&
-              aTriggeringEvent.altKey &&
-              !isTabEmpty(gBrowser.selectedTab)) {
+          } else if (aTriggeringEvent && aTriggeringEvent.altKey &&
+                     !isTabEmpty(gBrowser.selectedTab)) {
             this.handleRevert();
-            content.focus();
             gBrowser.loadOneTab(url, {
                                 postData: postData,
                                 inBackground: false,
                                 allowThirdPartyFixup: true});
             aTriggeringEvent.preventDefault();
             aTriggeringEvent.stopPropagation();
           } else {
             loadCurrent();
           }
-
-          gBrowser.selectedBrowser.focus();
         ]]></body>
       </method>
 
       <method name="_canonizeURL">
         <parameter name="aTriggeringEvent"/>
         <body><![CDATA[
           var url = this.value;
           if (!url)
--- 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/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -111,28 +111,17 @@ MOZ_PKG_MAC_BACKGROUND=branding/backgrou
 MOZ_PKG_MAC_ICON=branding/disk.icns
 MOZ_PKG_MAC_EXTRA=--symlink "/Applications:/ "
 endif
 
 ifndef LIBXUL_SDK
 INSTALL_SDK = 1
 endif
 
-ifneq (1_,$(if $(CROSS_COMPILE),1,0)_$(UNIVERSAL_BINARY))
-ifdef RUN_TEST_PROGRAM
-_ABS_RUN_TEST_PROGRAM = $(call core_abspath,$(RUN_TEST_PROGRAM))
-endif
-
-GENERATE_CACHE = \
-  $(_ABS_RUN_TEST_PROGRAM) $(LIBXUL_DIST)/bin/xpcshell$(BIN_SUFFIX) -g "$$PWD" -a "$$PWD" -f $(topsrcdir)/browser/installer/precompile_cache.js -e 'populate_startupcache("omni.jar", "startupCache.zip");' && \
-  rm -rf jsloader && \
-  $(UNZIP) startupCache.zip && \
-  rm startupCache.zip && \
-  $(ZIP) -r9m omni.jar jsloader
-endif
+GENERATE_CACHE = 1
 
 include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
 
 ifeq (bundle, $(MOZ_FS_LAYOUT))
 BINPATH = $(_BINPATH)
 DEFINES += -DAPPNAME=$(_APPNAME)
 else
 # Every other platform just winds up in dist/bin
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -987,17 +987,16 @@ xpicleanup@BIN_SUFFIX@
   modules/services-sync/type_records/bookmark.js
   modules/services-sync/type_records/clients.js
   modules/services-sync/type_records/forms.js
   modules/services-sync/type_records/history.js
   modules/services-sync/type_records/passwords.js
   modules/services-sync/type_records/prefs.js
   modules/services-sync/type_records/tabs.js
   modules/services-sync/util.js
-  modules/SpatialNavigation.js
   modules/stylePanel.jsm
   modules/tabview/AllTabs.jsm
   modules/tabview/groups.jsm
   modules/tabview/utils.jsm
   modules/utils.js
   modules/WindowDraggingUtils.jsm
   #ifdef XP_WIN
     modules/WindowsJumpLists.jsm
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -13,17 +13,17 @@
 
 <!ENTITY browsing.label                  "Browsing">
 
 <!ENTITY useAutoScroll.label             "Use autoscrolling">
 <!ENTITY useAutoScroll.accesskey         "a">
 <!ENTITY useSmoothScrolling.label        "Use smooth scrolling">
 <!ENTITY useSmoothScrolling.accesskey    "m">
 <!ENTITY allowHWAccel.label              "Use hardware acceleration when available">
-<!ENTITY allowHWAccel.accesskey          "h">
+<!ENTITY allowHWAccel.accesskey          "r">
 <!ENTITY checkSpelling.label             "Check my spelling as I type">
 <!ENTITY checkSpelling.accesskey         "t">
 
 <!ENTITY systemDefaults.label            "System Defaults">
 <!ENTITY alwaysCheckDefault.label        "Always check to see if &brandShortName; is the default browser on startup"><!--XXX-->
 <!ENTITY alwaysCheckDefault.accesskey    "w">
 <!ENTITY checkNow.label                  "Check Now">
 <!ENTITY checkNow.accesskey              "N">
--- a/browser/locales/en-US/chrome/browser/tabview.properties
+++ b/browser/locales/en-US/chrome/browser/tabview.properties
@@ -1,5 +1,4 @@
-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/themes/gnomestripe/browser/jar.mn
+++ b/browser/themes/gnomestripe/browser/jar.mn
@@ -74,17 +74,16 @@ browser.jar:
   skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css)
   skin/classic/browser/tabbrowser/alltabs.png          (tabbrowser/alltabs.png)
   skin/classic/browser/tabbrowser/connecting.png      (tabbrowser/connecting.png)
   skin/classic/browser/tabbrowser/loading.png         (tabbrowser/loading.png)
   skin/classic/browser/tabbrowser/tab.png             (tabbrowser/tab.png)
   skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabview/edit-light.png         (tabview/edit-light.png)
-  skin/classic/browser/tabview/new-tab.png            (tabview/new-tab.png)
   skin/classic/browser/tabview/search.png             (tabview/search.png)  
   skin/classic/browser/tabview/stack-expander.png     (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png            (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css            (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-16-throbber.png
   skin/classic/browser/sync-16.png
   skin/classic/browser/sync-24-throbber.png
deleted file mode 100644
index b7150d63e751e68ca032bf4873ea65c27dfe75b7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/gnomestripe/browser/tabview/tabview.css
+++ b/browser/themes/gnomestripe/browser/tabview/tabview.css
@@ -185,17 +185,17 @@ html[dir=rtl] .stack-trayed .tab-title {
 .front .focus {
   box-shadow: none !important;
 }
 
 /* Tab GroupItem
 ----------------------------------*/
 
 .groupItem {
-  cursor: move;
+  cursor: pointer;
   border: 1px solid rgba(230,230,230,1);
   background-color: window;
   background-image: -moz-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.1));
   border-radius: 0.4em;
   box-shadow:
     inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
     rgba(0,0,0,0.2) 1px 1px 3px;
 }
@@ -380,35 +380,16 @@ html[dir=rtl] .guideTrench {
 .visibleTrench.guide, 
 .activeVisibleTrench.guide {
   background-color: blue;
 }
 
 /* Other
 ----------------------------------*/
 
-.newTabButton {
-  width: 16px;
-  height: 15px;
-  bottom: 10px;
-  left: 10px;
-  cursor: pointer;
-  opacity: .3;
-  background-image: url(chrome://browser/skin/tabview/new-tab.png);
-}
-
-html[dir=rtl] .newTabButton {
-  left: auto;
-  right: 10px;
-}
-
-.newTabButton:hover {
-  opacity: 1;
-}
-
 .active {
   box-shadow: 5px 5px 3px rgba(0,0,0,.5);
 }
 
 html[dir=rtl] .active {
   box-shadow: -5px 5px 3px rgba(0,0,0,.5);
 }
 
@@ -416,16 +397,17 @@ html[dir=rtl] .active {
   box-shadow: 2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
 html[dir=rtl] .acceptsDrop {
   box-shadow: -2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
 .titlebar {
+  cursor: move;
   font-size: 12px;
   height: 18px;
 }
 
 input.name {
   background: transparent;
   border: 1px solid transparent;
   color: GrayText;
--- a/browser/themes/pinstripe/browser/jar.mn
+++ b/browser/themes/pinstripe/browser/jar.mn
@@ -112,17 +112,16 @@ browser.jar:
   skin/classic/browser/tabbrowser/tabbar-top-bg-inactive.png             (tabbrowser/tabbar-top-bg-inactive.png)
   skin/classic/browser/tabbrowser/tab-top-normal-active.png              (tabbrowser/tab-top-normal-active.png)
   skin/classic/browser/tabbrowser/tab-top-hover-active.png               (tabbrowser/tab-top-hover-active.png)
   skin/classic/browser/tabbrowser/tab-top-selected-active.png            (tabbrowser/tab-top-selected-active.png)
   skin/classic/browser/tabbrowser/tab-overflow-border.png                (tabbrowser/tab-overflow-border.png)
   skin/classic/browser/tabbrowser/tabDragIndicator.png                   (tabbrowser/tabDragIndicator.png)
   skin/classic/browser/tabview/close.png                    (tabview/close.png)
   skin/classic/browser/tabview/edit-light.png               (tabview/edit-light.png)
-  skin/classic/browser/tabview/new-tab.png                  (tabview/new-tab.png)
   skin/classic/browser/tabview/search.png                   (tabview/search.png)
   skin/classic/browser/tabview/stack-expander.png           (tabview/stack-expander.png)
   skin/classic/browser/tabview/tabview.png                  (tabview/tabview.png)
   skin/classic/browser/tabview/tabview.css                  (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/sync-throbber.png
   skin/classic/browser/sync-16.png
   skin/classic/browser/sync-32.png
deleted file mode 100644
index b7150d63e751e68ca032bf4873ea65c27dfe75b7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/pinstripe/browser/tabview/tabview.css
+++ b/browser/themes/pinstripe/browser/tabview/tabview.css
@@ -186,17 +186,17 @@ html[dir=rtl] .stack-trayed .tab-title {
   box-shadow: none !important;
   border: none !important;
 }
 
 /* Tab GroupItem
 ----------------------------------*/
 
 .groupItem {
-  cursor: move;
+  cursor: pointer;
   background-color: rgb(240,240,240);
   border-radius: 0.4em;
   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
   border: 1px solid rgba(255, 255, 255, 0.5);
 }
 
 .groupItem.activeGroupItem {
   box-shadow:
@@ -371,35 +371,16 @@ html[dir=rtl] .guideTrench {
 .visibleTrench.guide, 
 .activeVisibleTrench.guide {
   background-color: blue;
 }
 
 /* Other
 ----------------------------------*/
 
-.newTabButton {
-  width: 16px;
-  height: 15px;
-  bottom: 10px;
-  left: 10px;
-  cursor: pointer;
-  opacity: .3;
-  background-image: url(chrome://browser/skin/tabview/new-tab.png);
-}
-
-html[dir=rtl] .newTabButton {
-  left: auto;
-  right: 10px;
-}
-
-.newTabButton:hover {
-  opacity: 1;
-}
-
 .active {
   box-shadow: 5px 5px 3px rgba(0,0,0,.5);
 }
 
 html[dir=rtl] .active {
   box-shadow: -5px 5px 3px rgba(0,0,0,.5);
 }
 
@@ -407,16 +388,17 @@ html[dir=rtl] .active {
   box-shadow: 2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
 html[dir=rtl] .acceptsDrop {
   box-shadow: -2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
 .titlebar {
+  cursor: move;
   font-size: 12px;
   height: 18px;
 }
 
 input.name {
   background: transparent;
   border: 1px solid transparent;
   color: #999;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5c5881d51490c78ca606db20ca0a4adc51e1e602
GIT binary patch
literal 5117
zc$@+K69VjsP)<h;3K|Lk000e1NJLTq00CA2001Tk1^@s6pZc@*0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU_pGibPRCwC#T?=ql#TEV&hzJ-SrYejA
zQig}ArNyApMhzql1VTU_i2{X$Bp?J3T1o~gP#vZy)f9Otzl=1MmQD~vAV3i#MC47N
zKoJTAk!K{l!>d3@_xp1;EbHF;@BRNoUVCQF<mTSHdw0*C^X)lj_ufCiW$2!!($Z4D
z$_E4l_*I`=-q5|RKX(fSXk2g1IFj*qjK5-h&EYeuFb-q<bH;g$3osrI%HPlUas}L@
zLyf4fs~8{Dxc^DUZRvO=<Nr8(-g8vGk#zoBs&9kl7&c)X#rO%vHR${~#@iX^GCrn|
zImV?8;};m$r*j(_Kcn$X)VG@CR3e;j$oSWcpJp6rQT7`3YY{WbGZu!0_H^{pmh05s
zMT}1h=O1F+S+gH1;&m2D=R-(ddGx$eLH<8s{36NYq@vDn8t29q&&y_f-pBT096K@o
z75%@KagH=Dx)dVm^T|69SkZ@<EXIEw<4ufrdy!8&!U5RQQO5hpw)c|W`3<^J4H`7a
z%E`&uId<&WFWLY78CP{U=*fcy4O+Hz>C$gnwru$i>a>nDVO(h;AtAHymyA}X=8V(n
zo>azlZ0bY1V;H~A*iD?t`1b?^&4Yr1K3uqPAq1GBA)AOAHEPUUy?XUNFphCfvv0hP
zKkVGO^Ju9=+qZ8&!mf?dr~`fK9U2<?cgXk5nKKu79VbqlD9+B#{&&54_5RB4=}u!I
zQjcD}dM(<wZ{PR43}jNOK`4W=s6(nV74j=7DY<S{_R5tjS7*+g2{3ut#wb(JcDpv<
z8M9{1f|2x;$|ldAJ$p;3kA$+QL(!(BtgNhj*aJImCY=9Svu4d^;~K`oqCcZBrmE*n
zpFVv(yZ$QUT0YuoM09lYmh|-WE8w<m+vd}R?F%3cgiJ}U1L>SsVD*P9fx2NVRI-MC
zlip6Ev3kU!jz1kfeE8J4bLTE?-n{v{88c>Vh>MGx&(6O|j>CO^gK9xRK@o2lfoqh5
zdRq1C*Kf(yt5-|7v1@`WuBCC~BCs1I&G?}J!ra{4J-COAwVy?O0M1cwyz$0L5y(!R
zI&~g`Yu~>8Ja&D;iWMvVd-3AM|FPpKUfLE5*@$)Fn2at?6I^Qo^sEe=fZvX)GafK{
z^ypl)*{UA&v48*mOKEZv!Syd95IX@@5Xzzsu|1gJ0C=Q?ZWRw1GUQ)SSSYuJVcl1|
zcI}Vsz?swe^XCzzOqR;O&-Kj?l+g|xW75Z8=p_TFPf!+hNOcB6*DxtSN7(;^NtWPY
zt5&Vr>qT#ra^(O3!zIT+mmZ?~A=6KW4I6fW0l^h8j&Y8zrP96Hpvv3k1Y9eTk_6pJ
z(kuh89J67=h65^_!Z<<y=FFM1m7JkSg}u719EyyLj4z-I6cttR8&pB?Ty4NhMO^`S
zVjY^``XIb8#j^)f*y{mRD70uSFi6F05(b0cvSrIbJ7eR0^<p3hZxhgd%xH2QM~@yo
zO?^wS356>HSW$QKd+)ushTjj5H8C-9A!LAh`}Xa-c-^{n-}37K5?1CFLFR7NGv#xI
zg@tFq8f|<W&n5XyMH>~~NiFG~2b{`9B#W_fm-<Nx*$2T0VUV~^UQaxj12ZNtih#6%
z73Vp)YD}a*@XF`UpI<t3=+LVhH*UPd>%=k6;hK&2{R1yg1XT%KyWK)ybvtl0ICdpZ
zoH%i{mApkKWY3;Gg@`tU^arOQz?RFGFJDpBbNu-6bEE@^;H&uss=IdWIz}P)PaO!R
zE);Ujnl%Lu!4>BQb8l1x4|e`F8B_(YHboICXTU2JJ-AOl{dC8K2@}2oSj*m?4X|Q%
z>eHo5mj$w?Cwp?Z2lslJ(fk3{CXtbmbGc_We*Adk{RTrW2M-=RiT+Y5VI((Pcz2B(
zH~yR8foK6M02-{(#x#rpm!C!0SKem|fqN?YR?8u<PL<?b8Ndp989Ku!8|XFcfloS!
z94O_Y4Xls>>I5si`&5gG$K#b37Z;Z>P%kMeD!L}ui*vY!dlcTcNKNTE$Q_SUv|$`w
zOOw(cw=1wV4hsvLV->NW4tSiRQv@%RJWvrJu~spJ@igERoD$JV;gp$~`8A?OOuRmU
zDv+H(RTTPIO4uv&p5nbef@^aXfC5}q=g6Ct^RST+B)<=Bpqyh0x$>iB@U{R}2rd;N
zwbd*p67He!JJm+${s3zlCI#Ln_WuaRwRwF)A3`8QjGqv4cGm?~C>`aM-V}4OQX4UO
z^@V=OV5b1q@-|W!KaIe(3gy&OdAdLs1j%!lL6KAl?*k?St8|1F^9jU4_87-;a4>in
z&m#t$BM_?U)MNEA_v)#SIS7bEN}{8qPe(;Xm2>CLoloPM7d-+{4qd){`7X3w)eg$_
zkE8U*YqtPgodRnLCU;&20E_gc6cxllSNS*!j!BGAPb^Y{jNc|Ki^f_EoEg~;;2o3R
zS~^j!RG?}_FjfLrnbKvjvLXRo+gY?JR0XaUpxQ)H{&k)Q#j_}<@(W%s6h<SwM9$__
z2v8^QC#EJy=&xEN$^8M=chDc)hrA&B|CeHYQXistxC&X&;+-Y1!sCV_!UGe+q_#N5
zIb7o&JGHS7lo$C&(aW_0FXXvJStAEed1=c9E9#HiN?y`JmRo3B6_va#CeJETSrxsA
zd_0~9qwU_k`)7!N!o$P=Y2jpe1y&z(uby%MMT$bwNzXXH&Z9Joz5pO!<N9ys<@0M^
zz%|Li1eT<kQ*|qV)muGpBOS-fko@3Lrqkjgmt`czQH;hVEPD&}fFWbp53MKkQl%j2
zdV*DI^S7#muMZ(pxzXzoLRVI1yp6Ce!Ih^5EI_pi%JHxOMoWVcXb08`qk9>NZePPn
zltmp>7xHrNaOKbdR?g#THL^V4$7f^;^#VoUfX7VX4LrDqdA^!28rcCWCQO=uVyJuo
zF^*$!jeEfC{}1`1j<528^0Im++AUb|F|m`Eu#hE#V*oc;30U1U&WSQ$*#Il#oW}J5
z21%1of|mtLN5HC)drccLV#Epo=;UWV9T5?c4SBNT4;1AGh)#vd%NM<OejkDB0Nwui
z;4t`G&rJ)L6lK>Y-R&l%!7z?fc^VM<%l@Bk*A7ge!-o%F4v>b<i)%J;G-%=aVNp>y
zUAc7W($yb3iNYEMgSb!$RR`6oRjVo^Pah8-K8(c$7%{w!Np0G+nH&%h@S)5MI51#e
z3-zpG;pQ}c-NF7m&;2OtD%;-(dVx(k1KC&%03SPcEZJro%K*-7@<|swq5w9qo<0Qz
z2I9CXd0Q6?3kwT&@7`Tlty;Apx7*!{(j7re1|Gw^&d6K4n>KCw$jX%~0iXb!i-ICw
z#5r8UJ$&+F${R#&@QLcwse`?OwW?RI9*F*k*O)$D5yyn}Zx#NpU%!6V4-l`ctP0#}
zFhFf1%9}mwKK#!N3*O!H4i|PWWM*dWI(_=|g%&MZ)EhZ+WOFj!z=~2_v@Izq=_$J%
zA@T9?k5ha0xo+O03|*+Vb?er1Ec!goj=xuwFIcl?%~AQ}#~*);b3?&&d=sr-zaCNQ
ze%I|w*O+a4_Sxg_$&)96EwFnyZ=W-Mmh#rs*+gCgcH$8jBWe6LEn2i_=l=csPn0hf
z)va4|(xgf4a&mG8v%0r+?AS54sHmveliy->O_(sDrQrPB>>0uv5f^&w2+3SlX1Hp_
z5{pB+`ynak`D`Vn0;chtDD5g3pfEoCA57bqv~xZ_&ZsXTf9P#Hki74cJc(GLo<Cz{
z64$X4z*V+?7W6#EaNfLm+wct9Miz$<UN;pW<(;BP;lNQiC*A*%?n0B71*i{H^(Z{c
zBr8u}h%{uc(=z3vh)%3L)?ku<I>rwk3KmHaCJLcoI^7fOug9vPM{Z&4V+1|MiwL8T
z-{&E*MR`nw19)17*GKCD9*-5r;x*h$_EYsXP6dn>bH%jnkISbw<*l*4(qG(Bg9w`<
zNlpzZXa6R22Pr*qk(;)i_7m3v5Dik4s9aMCgJH@k0jzu?oRm5?obr`2Jw~gDZZYKL
z;iCdn+g9S@)kr>32&>|4gy-RJ1Gw=NHazLY^Ke^*?3xDQd0_%ds}nwBQXu0=lJbS+
zlNT*8jB(v~dkXSTfl@({AVZ#TpE6|%-aP4|1FU3Z9Z;SWrUN&&9}8HWqylV!)t^*=
zXU{Tp1I7hCLs_gtz)rwOW#JsI;U3bXSV^ZdRNMXh1=a%x4xFH|f%lq%T(A5bo6x%)
zTrt_I+J|$v<^@!5r^TxnF^3QNP+AKqxG5MXq;Zf&5uF=KaSW8~v=c2}fm0z{zTFO3
zLR&j0VEiSUX>GZP<po@ya3Gk6eFW8t+HUm>R*l64H+UMf6$yeIj>WUNbLVc$%F5cD
zkdOcnYf*{7$_Fh8UZ@?oLJ6=qLff`vuy2I1;NCd$$7Em#MeurM1FZgI@Odr`IU+Lp
zU>#tETp%lq6&N`?oRjYNfUeyO3Yt0gw>3c1?IW=2E?%jCwG}2~Y|p`@gg5M9khEY3
zS+~aohI7zIOk}v1Ch%5b&J*CO^5FadR=z5Ye(@;9VNMf38A%b(7)ATW(6z{00II$K
zYc+8f4A0@y9`0!>J%!9@@lmw<POwkDhnphCBzUU49Br@bAx3eup7I;J1}ec7Kqn!)
zH%gRWFVp~4Puc>?SphEy0K^7}TQC4dn27<>d3kwzj~qF2dfT>bhnFl_@=Z)k%qL#<
z=~e`=mV+z2QPuV>C;){qy(~Ov$gPjKl?-x4NQ%W203v2(9u7iz$n)*ytuNx%G_h?s
zmbc7NAA91tcoy0X51K+HWhjVieCG-N(&W*lf;`_THoF1>giurVRIPRe{0=ri3q>QL
zgS67zPe_sU!;S<*5V#-rq705JBDLfVSm8a{?W@)VB;{+Mw32=&y&&LO@dtK@o}}vK
z08X@rI9bA?x5SrX_*;hJOCppC9RXXDwx^Bu*1(&<6~;-({gea2GzUQN4rziaH-a?G
z!n&`t(smowJN`%y41~v_@(_!Qi!UL`Pi}m8C8q-973Mww7IDB~C|*ES^fvm#kiEUq
zN_#z%rTQ{)&DU32g*T0O*fbH(f#T5wrvz49!#&g{zT4q`-Pc$(b_IA=hQ)lLE~AX}
zN~<SFkMV$<*#vxuB7@q396fu5VN~#p&@YssJ-U?ztncgO=`CK*RgveFRuNnYRPV%B
zT7ezy5S;-xxSUkLN~w-NGJaIvwj}~9>H53aImMj|0^3RAI*zpK#yhwo#37F-+2!p0
zSQv6IgiZiH3PrtvDkpR{jkYn^eS~GOaF3M|VC6X(;Vj&B2o(7j06i3lQXDZFeM_=P
zq9-{_(%&Q>7%md%SdgLxr&lyrnbF=}n4uwGEKWfQP!B)=33{84uyg~Eh~ADau%ZkB
zm*~x8SZ#J!5zX!yLirRvk@`ZyKGx(4*dE7sYj|G7fN?@+Xls>fq4hcF5bnX`K+#p2
z#`tB}y=qN{pP^bH*6E|v7j1BL0;;#+M_9_!Wyp;}|0&{_s&YW2?U0<}xot?g-kraq
zFGNV?AJ~E2!NG880$eaH_`vl=j??L9vjQo(-pXbDSv9-arzUO3D)r+Y-i`*ez2-66
zc7Yjv7q#oS%h~4)D~bXsx&A!Kc8#m-vv1cO$ml^=+1nva=@|Vw#TW*TQ0JUW{n@~-
zuCmX~)ueN}pACep@p-xht{b0Uv->ojisVltK1z!|{(SE5GxFp+`B_g6ZBuGYaz&JO
zfb?XOLY4uPM{Pr808F{mM>~3&WY)yudI8C3lXU(O%|42K(FIrjk)<zPcjjjURXcv3
zpmBk&SJRM@Xd5m;*MrGPf!qPC*p~U7p!a9U-j<lJ4Bz8aYCcqK$mmbSBf1fcAwz}?
zu>Od^$~w)%RBXAx=5p*2+jg%3tFOvqCLKe@HYypwZdV(#Nh$+W6S44wg%xZspv|@|
zy(ORhO=#aOe5=OpR<y-wn+)AOz<M{^ScQ75<f(R#jEqcJym)bZaBwhwQ_8h=?b`hj
z5fS*-=487W!x)YsLx%2U3bX*#t_(nXEL^xSj)N+wQKLq6UBVY!3>h+H$dDIc4JdOz
zUt*w|$UN0Je6@vND=sd++`D)0FI;86&S}VyAw!0|r2+_4yM~8{CoEgGEFPc95<xXS
zK7MgtULIcgoX^T!H>m(ah71|90agOlE@5F|i7QsD=q!V3*REZ2a&vP}S=52w+Qug4
zd;_e83>h+X16bQJP)%OGe0h9GNXP?DD#*{zKiIl;Yy8I1y9QVd88T$(MvnD`1q&9m
zcM7VY(9qC&F7<o-h71`pbWa0o`A?V_GGxe*p^5?4)jfOmTygg7*^5pq*s)^=e&O(d
z5v3tRh76Sv&#{)j5P-d_;x;S%Xj)86%%c4K{9=nb@UsS3yxPi7m>jDiLx%2oVD%hW
zylo|cE4~%Fpj1Fkv)#&&Awz~NfK>-vJ9Ox<c*BMb_z8{A4X_$AWXO;PuzCa6Lx&EX
zYS^&h`}hS|1FVJ&88W1%Km{n`t*ZHW%L;E>;ROK!Sn-AI6Gm)?3>h-yz+;s>*B;T)
z(Fxhv*|B@~?mZD38~f$ivu7vcCyR{7YRHfwLk@ve09VH!x;DUS$dDleto~GBfYp#8
fLxygm{|hhx$eiUvzT;wE00000NkvXXu0mjf!t|93
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -133,16 +133,23 @@
   #nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child:not(:-moz-lwtheme) {
     background-color: transparent !important;
     color: black;
     text-shadow: 0 0 .5em white, 0 0 .5em white, 0 1px 0 rgba(255,255,255,.4);
     border-left-style: none !important;
     border-right-style: none !important;
   }
 
+  #toolbar-menubar :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme),
+  #TabsToolbar[tabsontop=true] :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme),
+  #navigator-toolbox[tabsontop=false] > #nav-bar :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme),
+  #nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme) {
+    list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
+  }
+
   /* Vertical toolbar border */
   #main-window[sizemode=normal] #navigator-toolbox::after,
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > toolbar:not(#toolbar-menubar):not(#TabsToolbar),
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=false] > toolbar:not(#toolbar-menubar):not(#nav-bar) {
     border-left: 1px solid @toolbarShadowColor@;
     border-right: 1px solid @toolbarShadowColor@;
     background-clip: padding-box;
   }
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -52,16 +52,17 @@
 %filter substitution
 %define toolbarHighlight rgba(255,255,255,.5)
 %define selectedTabHighlight rgba(255,255,255,.7)
 %define toolbarShadowColor rgba(10%,10%,10%,.4)
 %define toolbarShadowOnTab -moz-linear-gradient(bottom, rgba(10%,10%,10%,.4) 1px, transparent 1px)
 %define bgTabTexture -moz-linear-gradient(transparent, hsla(0,0%,45%,.1) 1px, hsla(0,0%,32%,.2) 80%, hsla(0,0%,0%,.2))
 %define bgTabTextureHover -moz-linear-gradient(hsla(0,0%,100%,.3) 1px, hsla(0,0%,75%,.2) 80%, hsla(0,0%,60%,.2))
 %define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32);
+%define navbarLargeIcons #navigator-toolbox[iconsize=large][mode=icons] > #nav-bar
 
 #menubar-items {
   -moz-box-orient: vertical; /* for flex hack */
 }
 
 #main-menubar {
   -moz-box-flex: 1; /* make menu items expand to fill toolbar height */
 }
@@ -577,147 +578,143 @@ menuitem.bookmark-item {
 }
 
 /* ::::: primary toolbar buttons ::::: */
 
 .toolbarbutton-1 {
   list-style-image: url("chrome://browser/skin/Toolbar.png");
 }
 
+.toolbarbutton-1:-moz-lwtheme-brighttext {
+  list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
+}
+
 .toolbarbutton-1:not([type="menu-button"]) {
   -moz-box-orient: vertical;
 }
 
 .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
 .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon {
   opacity: .4;
 }
 
 #nav-bar {
   /* force iconsize="small" on this toolbar */
   counter-reset: smallicons;
 }
 
-#navigator-toolbox[iconsize=small] > #nav-bar {
-  padding-top: 1px;
-  padding-bottom: 1px;
-}
-
-#navigator-toolbox[iconsize=large][mode=icons] > #nav-bar {
+@navbarLargeIcons@ {
   -moz-padding-start: 0;
   -moz-padding-end: 2px;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
-#nav-bar .toolbarbutton-1 {
+@navbarLargeIcons@ :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon {
+  list-style-image: url("chrome://browser/skin/Toolbar.png") !important;
+}
+
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button,
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
+@navbarLargeIcons@ .toolbarbutton-1 {
   -moz-appearance: none;
   padding: 1px 5px;
   background: rgba(151,152,153,.05)
               -moz-linear-gradient(rgba(251,252,253,.95), rgba(246,247,248,.47) 49%, 
                                    rgba(231,232,233,.45) 51%, rgba(225,226,229,.3));
   background-clip: padding-box;
   border-radius: 3.5px;
   border: 1px solid;
   border-color: rgba(0,0,0,.12) rgba(0,0,0,.19) rgba(0,0,0,.38);
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 2px rgba(255,255,255,.1) inset;
   color: black;
   text-shadow: 0 0 2px white;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker,
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button,
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   padding-left: 3px;
   padding-right: 3px;
 }
 
-#nav-bar .toolbarbutton-1[type="menu-button"] {
+@navbarLargeIcons@ .toolbarbutton-1[type="menu-button"] {
   -moz-appearance: none;
   padding: 0;
   background: none !important;
   border: none !important;
   box-shadow: none !important;
 }
 
-#nav-bar .toolbarbutton-1 {
+@navbarLargeIcons@ .toolbarbutton-1 {
   margin: 1px 3px;
 }
 
-#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 {
-  margin-left: 2px;
-  margin-right: 2px;
-}
-
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker {
   -moz-border-start-style: none;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr),
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr),
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl),
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl),
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) {
   border-top-left-radius: 0;
   border-bottom-left-radius: 0;
 }
 
-#nav-bar .toolbarbutton-1[disabled="true"] {
+@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] {
   opacity: .4;
 }
 
-#nav-bar .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
-#nav-bar .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon {
+@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
+@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon {
   opacity: 1;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
-#nav-bar .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
-#nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover,
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
+@navbarLargeIcons@ .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
+@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover,
+@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon {
   background-color: hsla(190,60%,70%,.5);
   border-color: hsla(190,50%,65%,.8) hsla(190,50%,50%,.8) hsla(190,50%,40%,.8);
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 1.5px rgba(255,255,255,.1) inset,
               0 0 3.5px hsl(190,90%,80%);
   -moz-transition: background-color .4s ease-in,
                    border-color .3s ease-in,
                    box-shadow .3s ease-in;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
-#nav-bar .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
-#nav-bar .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker,
-#nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active,
-#nav-bar .toolbarbutton-1:not([type="menu-button"])[checked="true"],
-#nav-bar .toolbarbutton-1[open="true"] {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
+@navbarLargeIcons@ .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
+@navbarLargeIcons@ .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker,
+@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active,
+@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"])[checked="true"],
+@navbarLargeIcons@ .toolbarbutton-1[open="true"] {
   background-color: transparent;
   border-color: rgba(0,0,0,.65) rgba(0,0,0,.55) rgba(0,0,0,.5);
   box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
               0 0 2px rgba(0,0,0,.4) inset,
               0 1px 0 rgba(255,255,255,.4);
   text-shadow: none;
 }
 
-#nav-bar .toolbarbutton-1[checked="true"]:not(:active):hover {
+@navbarLargeIcons@ .toolbarbutton-1[checked="true"]:not(:active):hover {
   background-color: rgba(90%,90%,90%,.4);
   -moz-transition: background-color .4s;
 }
 
 .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
 .toolbarbutton-1 > .toolbarbutton-icon {
   -moz-margin-end: 0;
 }
 
-#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
-#nav-bar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon {
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
+@navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon {
   margin: 1px;
 }
 
 toolbar[mode="full"] .toolbarbutton-1,
 toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button {
   min-width: 57px;
 }
 
@@ -759,114 +756,108 @@ toolbar[mode="full"] .toolbarbutton-1 > 
 #back-button {
   -moz-image-region: rect(0, 18px, 18px, 0);
 }
 
 #forward-button {
   -moz-image-region: rect(0, 36px, 18px, 18px);
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
-  -moz-image-region: rect(18px, 20px, 38px, 0);
-}
-
 #back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon,
 #forward-button:-moz-locale-dir(rtl),
 #forward-button:-moz-locale-dir(rtl) > .toolbarbutton-text {
   -moz-transform: scaleX(-1);
 }
 
-#nav-bar #back-button {
-  -moz-margin-end: 0 !important;
-}
-
-#nav-bar #forward-button {
+@navbarLargeIcons@ #forward-button {
   border-left-style: none;
   -moz-margin-start: 0 !important;
 }
 
-#nav-bar #back-button:-moz-locale-dir(ltr) {
+@navbarLargeIcons@ #back-button:-moz-locale-dir(ltr) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
-#nav-bar #back-button:-moz-locale-dir(rtl),
-#nav-bar #forward-button {
+@navbarLargeIcons@ #back-button:-moz-locale-dir(rtl),
+@navbarLargeIcons@ #forward-button {
   border-top-left-radius: 0;
   border-bottom-left-radius: 0;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button {
+@navbarLargeIcons@ #back-button {
+  -moz-image-region: rect(18px, 20px, 38px, 0);
+  -moz-margin-end: 0 !important;
   margin: -5px 0;
   padding-top: 0;
   padding-bottom: 0;
   -moz-padding-start: 5px;
   -moz-padding-end: 0;
   position: relative;
   z-index: 1;
   border-radius: 0 10000px 10000px 0;
   background: transparent;
   border: none;
   box-shadow: none;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-locale-dir(rtl) {
+@navbarLargeIcons@ #back-button:-moz-locale-dir(rtl) {
   border-radius: 10000px 0 0 10000px;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button > .toolbarbutton-icon {
+@navbarLargeIcons@ #back-button > .toolbarbutton-icon {
   border-radius: 10000px;
   padding: 5px;
   border: none;
   background-image: -moz-linear-gradient(rgba(251,252,253,.97), rgba(246,247,248,.5) 49%, 
                                          rgba(231,232,233,.45) 51%, rgba(225,226,229,.2));
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 2px rgba(255,255,255,.1) inset,
               0 0 0 1px rgba(0,0,0,.15),
               0 1px 0 rgba(0,0,0,.4),
               0 1px 1px rgba(0,0,0,.3);
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
+@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
   box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
               0 0 0 2px rgba(255,255,255,.1) inset,
               0 0 0 1px hsla(190,50%,40%,.3),
               0 1px 0 rgba(0,0,0,.4),
               0 1px 1px rgba(0,0,0,.3),
               0 0 5px 1px hsl(190,90%,80%);
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button[open="true"] > .toolbarbutton-icon {
+@navbarLargeIcons@ #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
+@navbarLargeIcons@ #back-button[open="true"] > .toolbarbutton-icon {
   box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset,
               0 0 2px rgba(0,0,0,.4) inset,
               0 0 0 1px rgba(0,0,0,.65),
               0 2px 0 rgba(255,255,255,.4);
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar[currentset*="unified-back-forward-button"],
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar:not([currentset]) {
+@navbarLargeIcons@[currentset*="unified-back-forward-button"],
+@navbarLargeIcons@:not([currentset]) {
   padding-top: 3px;
   padding-bottom: 5px;
 }
 
 #navigator-toolbox[iconsize="large"][mode="icons"][tabsontop="true"] > #nav-bar[currentset*="unified-back-forward-button"],
 #navigator-toolbox[iconsize="large"][mode="icons"][tabsontop="true"] > #nav-bar:not([currentset]) {
   padding-top: 5px;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button {
+@navbarLargeIcons@ #forward-button {
   /*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
   mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask);
   -moz-margin-start: -6px !important;
   padding-left: 7px;
   padding-right: 3px;
 }
 
-#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:not([disabled="true"]):not(:active):hover {
+@navbarLargeIcons@ #forward-button:not([disabled="true"]):not(:active):hover {
   /*mask: url(keyhole-forward-mask.svg#mask-hover);*/
   mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask-hover);
   /* Don't animate the box shadow, as the blur and spread radii affect the mask. */
   -moz-transition: background-color .4s ease-in;
 }
 
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
@@ -890,16 +881,19 @@ toolbar[mode="full"] .toolbarbutton-1 > 
   -moz-image-region: rect(0, 72px, 18px, 54px);
 }
 
 /* home button */
 
 #home-button.bookmark-item {
   list-style-image: url("chrome://browser/skin/Toolbar.png");
 }
+#home-button.bookmark-item:-moz-lwtheme-brighttext {
+  list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
+}
 #home-button {
   -moz-image-region: rect(0, 90px, 18px, 72px);
 }
 
 /* tabview button */
 
 #tabview-button,
 #menu_tabview {
@@ -964,16 +958,20 @@ toolbar[mode="full"] .toolbarbutton-1 > 
 #bookmarks-menu-button {
   -moz-image-region: rect(0, 144px, 18px, 126px);
 }
 
 #bookmarks-menu-button.bookmark-item {
   list-style-image: url("chrome://browser/skin/Toolbar.png");
 }
 
+#bookmarks-menu-button.bookmark-item:-moz-lwtheme-brighttext {
+  list-style-image: url("chrome://browser/skin/Toolbar-inverted.png");
+}
+
 #bookmarks-menu-button.toolbarbutton-1 {
   -moz-box-orient: horizontal;
 }
 
 /* print button */
 
 #print-button {
   -moz-image-region: rect(0, 162px, 18px, 144px);
--- a/browser/themes/winstripe/browser/jar.mn
+++ b/browser/themes/winstripe/browser/jar.mn
@@ -30,16 +30,17 @@ browser.jar:
         skin/classic/browser/page-livemarks.png                      (feeds/feedIcon16.png)
         skin/classic/browser/livemark-item.png                       (livemark-item.png)
         skin/classic/browser/livemark-folder.png                     (livemark-folder.png)
         skin/classic/browser/Privacy-16.png
         skin/classic/browser/Privacy-48.png
         skin/classic/browser/reload-stop-go.png
         skin/classic/browser/Secure24.png                            (Secure24.png)
         skin/classic/browser/Toolbar.png                             (Toolbar.png)
+        skin/classic/browser/Toolbar-inverted.png
         skin/classic/browser/Go-arrow.png                            (Go-arrow.png)
 *       skin/classic/browser/searchbar.css                           (searchbar.css)
         skin/classic/browser/section_collapsed.png
         skin/classic/browser/section_collapsed-rtl.png
         skin/classic/browser/section_expanded.png
         skin/classic/browser/setDesktopBackground.css
         skin/classic/browser/menu-back.png                           (menu-back.png)
         skin/classic/browser/menu-forward.png                        (menu-forward.png)
@@ -91,17 +92,16 @@ browser.jar:
         skin/classic/browser/tabbrowser/loading.png                  (tabbrowser/loading.png)
         skin/classic/browser/tabbrowser/tab.png                      (tabbrowser/tab.png)
         skin/classic/browser/tabbrowser/tab-arrow-left.png           (tabbrowser/tab-arrow-left.png)
         skin/classic/browser/tabbrowser/tab-overflow-border.png      (tabbrowser/tab-overflow-border.png)
         skin/classic/browser/tabbrowser/tabDragIndicator.png         (tabbrowser/tabDragIndicator.png)
         skin/classic/browser/tabview/close.png                      (tabview/close.png)
         skin/classic/browser/tabview/edit-light.png                 (tabview/edit-light.png)
         skin/classic/browser/tabview/grain.png                      (tabview/grain.png)
-        skin/classic/browser/tabview/new-tab.png                    (tabview/new-tab.png)
         skin/classic/browser/tabview/search.png                     (tabview/search.png)
         skin/classic/browser/tabview/stack-expander.png             (tabview/stack-expander.png)
         skin/classic/browser/tabview/tabview.png                    (tabview/tabview.png)
         skin/classic/browser/tabview/tabview.css                    (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/sync-throbber.png
         skin/classic/browser/sync-16.png
         skin/classic/browser/sync-32.png
@@ -144,16 +144,17 @@ browser.jar:
         skin/classic/aero/browser/page-livemarks.png                 (feeds/feedIcon16-aero.png)
         skin/classic/aero/browser/livemark-item.png                  (livemark-item-aero.png)
         skin/classic/aero/browser/livemark-folder.png                (livemark-folder-aero.png)
         skin/classic/aero/browser/Privacy-16.png                     (Privacy-16-aero.png)
         skin/classic/aero/browser/Privacy-48.png                     (Privacy-48-aero.png)
         skin/classic/aero/browser/reload-stop-go.png
         skin/classic/aero/browser/Secure24.png                       (Secure24-aero.png)
         skin/classic/aero/browser/Toolbar.png
+        skin/classic/aero/browser/Toolbar-inverted.png
         skin/classic/aero/browser/Go-arrow.png                       (Go-arrow-aero.png)
 *       skin/classic/aero/browser/searchbar.css                      (searchbar.css)
         skin/classic/aero/browser/section_collapsed.png
         skin/classic/aero/browser/section_collapsed-rtl.png
         skin/classic/aero/browser/section_expanded.png
         skin/classic/aero/browser/setDesktopBackground.css
         skin/classic/aero/browser/menu-back.png                      (menu-back-aero.png)
         skin/classic/aero/browser/menu-forward.png                   (menu-forward-aero.png)
@@ -206,17 +207,16 @@ browser.jar:
         skin/classic/aero/browser/tabbrowser/loading.png             (tabbrowser/loading.png)
         skin/classic/aero/browser/tabbrowser/tab.png                 (tabbrowser/tab.png)
         skin/classic/aero/browser/tabbrowser/tab-arrow-left.png      (tabbrowser/tab-arrow-left.png)
         skin/classic/aero/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png)
         skin/classic/aero/browser/tabbrowser/tabDragIndicator.png    (tabbrowser/tabDragIndicator.png)
         skin/classic/aero/browser/tabview/close.png                  (tabview/close.png)
         skin/classic/aero/browser/tabview/edit-light.png             (tabview/edit-light.png)
         skin/classic/aero/browser/tabview/grain.png                  (tabview/grain.png)
-        skin/classic/aero/browser/tabview/new-tab.png                (tabview/new-tab.png)
         skin/classic/aero/browser/tabview/search.png                 (tabview/search.png)
         skin/classic/aero/browser/tabview/stack-expander.png         (tabview/stack-expander.png)
         skin/classic/aero/browser/tabview/tabview.png                (tabview/tabview.png)
         skin/classic/aero/browser/tabview/tabview.css                (tabview/tabview.css)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/sync-throbber.png
         skin/classic/aero/browser/sync-16.png
         skin/classic/aero/browser/sync-32.png
deleted file mode 100644
index b7150d63e751e68ca032bf4873ea65c27dfe75b7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/winstripe/browser/tabview/tabview.css
+++ b/browser/themes/winstripe/browser/tabview/tabview.css
@@ -199,17 +199,17 @@ html[dir=rtl] .tab.focus {
 .front.focus {
   box-shadow: none !important;
 }
 
 /* Tab GroupItem
 ----------------------------------*/
 
 .groupItem {
-  cursor: move;
+  cursor: pointer;
   background-color: #E0EAF5;
   border-radius: 0.4em;
   box-shadow:
     0 1px 0 #FFFFFF inset,
     0 -1px 1px rgba(255, 255, 255, 0.8) inset,
     1px 0 1px rgba(255, 255, 255, 0.8) inset,
     -1px 0 1px rgba(255, 255, 255, 0.8) inset,
     0 1px 3px rgba(4, 38, 60, 0.6);
@@ -393,35 +393,16 @@ html[dir=rtl] .guideTrench {
 .visibleTrench.guide, 
 .activeVisibleTrench.guide {
   background-color: blue;
 }
 
 /* Other
 ----------------------------------*/
 
-.newTabButton {
-  width: 16px;
-  height: 15px;
-  bottom: 10px;
-  left: 10px;
-  cursor: pointer;
-  opacity: .3;
-  background-image: url(chrome://browser/skin/tabview/new-tab.png);
-}
-
-html[dir=rtl] .newTabButton {
-  left: auto;
-  right: 10px;
-}
-
-.newTabButton:hover {
-  opacity: 1;
-}
-
 .active {
   box-shadow: 5px 5px 3px rgba(0,0,0,.5);
 }
 
 html[dir=rtl] .active {
   box-shadow: -5px 5px 3px rgba(0,0,0,.5);
 }
 
@@ -429,16 +410,17 @@ html[dir=rtl] .active {
   box-shadow: 2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
 html[dir=rtl] .acceptsDrop {
   box-shadow: -2px 2px 7px -1px rgba(0,0,0,.6);
 }
 
 .titlebar {
+  cursor: move;
   font-size: 12px;
   height: 18px;
 }
 
 input.name {
   background: transparent;
   border: 1px solid transparent;
   color: #999;
--- a/build/autoconf/config.sub
+++ b/build/autoconf/config.sub
@@ -1428,17 +1428,17 @@ case $os in
 		;;
 	-zvmoe)
 		os=-zvmoe
 		;;
 	-dicos*)
 		os=-dicos
 		;;
         -android*)
-	        os=android
+	        os=-android
                 ;;
 	-none)
 		;;
 	*)
 		# Get rid of the `-' at the beginning of $os.
 		os=`echo $os | sed 's/[^-]*-//'`
 		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
 		exit 1
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -1,87 +1,136 @@
 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)
+      if (not self.dirExists(remoteDir)):
+        self.mkDirs(remoteDir+"/x")
+      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 +156,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 +209,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 +347,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 +376,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 +486,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/pgo/profileserver.py
+++ b/build/pgo/profileserver.py
@@ -59,53 +59,35 @@ os.chdir(SCRIPT_DIR)
 
 class EasyServer(SocketServer.TCPServer):
   allow_reuse_address = True
 
 if __name__ == '__main__':
   from optparse import OptionParser
   automation = Automation()
 
-  parser = OptionParser(usage='OBJDIR=path/to/objdir python %prog [NUM_RUNS]')
+  parser = OptionParser()
   addCommonOptions(parser)
 
   options, args = parser.parse_args()
 
-  if not os.getenv('OBJDIR'):
-      parser.error('Please specify the OBJDIR environment variable.')
-
-  if not args:
-      num_runs = 1
-  else:
-      try:
-          num_runs = int(args[0])
-      except:
-          parser.error('NUM_RUNS argument must be an integer.')
-      if num_runs < 1:
-          parser.error('NUM_RUNS must be greater than zero.')
-
   debuggerInfo = getDebuggerInfo(".", options.debugger, options.debuggerArgs,
           options.debuggerInteractive)
 
   httpd = EasyServer(("", PORT), SimpleHTTPServer.SimpleHTTPRequestHandler)
   t = threading.Thread(target=httpd.serve_forever)
   t.setDaemon(True) # don't hang on exit
   t.start()
   
   automation.setServerInfo("localhost", PORT)
+  automation.initializeProfile(PROFILE_DIRECTORY)
   browserEnv = automation.environment()
   browserEnv["XPCOM_DEBUG_BREAK"] = "warn"
   browserEnv["MOZ_JAR_LOG_DIR"] = MOZ_JAR_LOG_DIR
 
   url = "http://localhost:%d/index.html" % PORT
   appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP)
-
-  for i in range(0, num_runs):
-      if num_runs != 1:
-          print "Starting profiling run %d of %d" % (i + 1, num_runs)
-      automation.initializeProfile(PROFILE_DIRECTORY)
-      status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
-                                 debuggerInfo=debuggerInfo,
-                                 # the profiling HTML doesn't output anything,
-                                 # so let's just run this without a timeout
-                                 timeout = None)
-      if status != 0:
-          sys.exit(status)
+  status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {},
+                             debuggerInfo=debuggerInfo,
+                             # the profiling HTML doesn't output anything,
+                             # so let's just run this without a timeout
+                             timeout = None)
+  sys.exit(status)
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -86,17 +86,16 @@
 #include "nsIContent.h"
 #include "nsAutoPtr.h"
 #include "nsDOMJSUtils.h"
 #include "nsAboutProtocolUtils.h"
 #include "nsIClassInfo.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
-#include "nsPrintfCString.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -81,16 +81,18 @@ nsSystemPrincipal::Release()
   return count;
 }
 
 
 ///////////////////////////////////////
 // Methods implementing nsIPrincipal //
 ///////////////////////////////////////
 
+#define SYSTEM_PRINCIPAL_SPEC "[System Principal]"
+
 NS_IMETHODIMP
 nsSystemPrincipal::GetPreferences(char** aPrefName, char** aID,
                                   char** aSubjectName,
                                   char** aGrantedList, char** aDeniedList,
                                   PRBool* aIsTrusted)
 {
     // The system principal should never be streamed out
     *aPrefName = nsnull;
@@ -190,17 +192,17 @@ nsSystemPrincipal::GetURI(nsIURI** aURI)
 {
     *aURI = nsnull;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsSystemPrincipal::GetOrigin(char** aOrigin)
 {
-    *aOrigin = ToNewCString(NS_LITERAL_CSTRING("[System Principal]"));
+    *aOrigin = ToNewCString(NS_LITERAL_CSTRING(SYSTEM_PRINCIPAL_SPEC));
     return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 NS_IMETHODIMP 
 nsSystemPrincipal::GetFingerprint(nsACString& aID)
 {
     return NS_ERROR_NOT_AVAILABLE;
 }
@@ -303,21 +305,16 @@ nsSystemPrincipal::Write(nsIObjectOutput
 /////////////////////////////////////////////
 // Constructor, Destructor, initialization //
 /////////////////////////////////////////////
 
 nsSystemPrincipal::nsSystemPrincipal()
 {
 }
 
-// Don't rename the system principal!
-// The JS engine (NewCompartment) relies on this name. 
-// XXX: bug 669123 will fix this hack.
-#define SYSTEM_PRINCIPAL_SPEC "[System Principal]"
-
 nsresult
 nsSystemPrincipal::Init(JSPrincipals **jsprin)
 {
     // Use an nsCString so we only do the allocation once here and then
     // share with nsJSPrincipals
     nsCString str(SYSTEM_PRINCIPAL_SPEC);
     if (!str.EqualsLiteral(SYSTEM_PRINCIPAL_SPEC)) {
         NS_WARNING("Out of memory initializing system principal");
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -204,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
 
--- a/configure.in
+++ b/configure.in
@@ -982,17 +982,20 @@ fi
 
 if test -z "$COMPILE_ENVIRONMENT"; then
     NSINSTALL_BIN='$(PYTHON) $(topsrcdir)/config/nsinstall.py'
 fi
 AC_SUBST(NSINSTALL_BIN)
 
 MOZ_PATH_PROG(DOXYGEN, doxygen, :)
 MOZ_PATH_PROG(AUTOCONF, autoconf, :)
-MOZ_PATH_PROG(UNZIP, unzip, :)
+MOZ_PATH_PROGS(UNZIP, unzip)
+if test -z "$UNZIP" -o "$UNZIP" = ":"; then
+    AC_MSG_ERROR([unzip not found in \$PATH])
+fi
 MOZ_PATH_PROGS(ZIP, zip)
 if test -z "$ZIP" -o "$ZIP" = ":"; then
     AC_MSG_ERROR([zip not found in \$PATH])
 fi
 MOZ_PATH_PROG(SYSTEM_MAKEDEPEND, makedepend)
 MOZ_PATH_PROG(XARGS, xargs)
 if test -z "$XARGS" -o "$XARGS" = ":"; then
     AC_MSG_ERROR([xargs not found in \$PATH .])
@@ -4812,17 +4815,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
@@ -7465,22 +7467,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}])
     ;;
@@ -7736,29 +7746,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= )
@@ -8966,17 +8963,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
@@ -9009,16 +9005,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/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -74,23 +74,23 @@ static fp_except_t oldmask = fpsetmask(~
 #include "nsIScriptGlobalObject.h"
 #include "nsIDOMEvent.h"
 #include "nsTArray.h"
 #include "nsTextFragment.h"
 #include "nsReadableUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "nsINode.h"
 #include "nsHashtable.h"
+#include "nsIDOMNode.h"
 
 struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
 
 class nsIDOMScriptObjectFactory;
 class nsIXPConnect;
 class nsIContent;
-class nsIDOMNode;
 class nsIDOMKeyEvent;
 class nsIDocument;
 class nsIDocumentObserver;
 class nsIDocShell;
 class nsINameSpaceManager;
 class nsIScriptSecurityManager;
 class nsIJSContextStack;
 class nsIThreadJSContextStack;
@@ -117,17 +117,16 @@ class nsIScriptContext;
 class nsIRunnable;
 class nsIInterfaceRequestor;
 template<class E> class nsCOMArray;
 template<class K, class V> class nsRefPtrHashtable;
 struct JSRuntime;
 class nsIUGenCategory;
 class nsIWidget;
 class nsIDragSession;
-class nsPIDOMWindow;
 class nsIPresShell;
 class nsIXPConnectJSObjectHolder;
 #ifdef MOZ_XTF
 class nsIXTFService;
 #endif
 #ifdef IBMBIDI
 class nsIBidiKeyboard;
 #endif
--- a/content/base/src/ThirdPartyUtil.cpp
+++ b/content/base/src/ThirdPartyUtil.cpp
@@ -281,32 +281,38 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIC
   // be set on the channel.
   nsCOMPtr<nsIDOMWindow> ourWin, parentWin;
   ctx->GetAssociatedWindow(getter_AddRefs(ourWin));
   if (!ourWin) return NS_ERROR_INVALID_ARG;
 
   ourWin->GetParent(getter_AddRefs(parentWin));
   NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG);
 
-  if (SameCOMIdentity(ourWin, parentWin)) {
-    // Check whether this is the document channel for this window (representing
-    // a load of a new page). This covers the case of a freshly kicked-off load
-    // (e.g. the user typing something in the location bar, or clicking on a
-    // bookmark), where the window's URI hasn't yet been set, and will be bogus.
-    // This is a bit of a nasty hack, but we will hopefully flag these channels
-    // better later.
-    nsLoadFlags flags;
-    rv = aChannel->GetLoadFlags(&flags);
-    NS_ENSURE_SUCCESS(rv, rv);
+  // Check whether this is the document channel for this window (representing a
+  // load of a new page). In that situation we want to avoid comparing
+  // channelURI to ourWin, since what's in ourWin right now will be replaced as
+  // the channel loads.  This covers the case of a freshly kicked-off load
+  // (e.g. the user typing something in the location bar, or clicking on a
+  // bookmark), where the window's URI hasn't yet been set, and will be bogus.
+  // It also covers situations where a subframe is navigated to someting that
+  // is same-origin with all its ancestors.  This is a bit of a nasty hack, but
+  // we will hopefully flag these channels better later.
+  nsLoadFlags flags;
+  rv = aChannel->GetLoadFlags(&flags);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-    if (flags & nsIChannel::LOAD_DOCUMENT_URI) {
+  if (flags & nsIChannel::LOAD_DOCUMENT_URI) {
+    if (SameCOMIdentity(ourWin, parentWin)) {
       // We only need to compare aURI to the channel URI -- the window's will be
       // bogus. We already know the answer.
       *aResult = false;
       return NS_OK;
     }
+
+    // Make sure to still compare to ourWin's ancestors
+    ourWin = parentWin;
   }
 
   // Check the window hierarchy. This covers most cases for an ordinary page
   // load from the location bar.
   return IsThirdPartyWindow(ourWin, channelURI, aResult);
 }
 
--- a/content/base/src/contentSecurityPolicy.js
+++ b/content/base/src/contentSecurityPolicy.js
@@ -63,17 +63,16 @@ function ContentSecurityPolicy() {
   this._isInitialized = false;
   this._reportOnlyMode = false;
   this._policy = CSPRep.fromString("default-src *");
 
   // default options "wide open" since this policy will be intersected soon
   this._policy._allowInlineScripts = true;
   this._policy._allowEval = true;
 
-  this._requestHeaders = []; 
   this._request = "";
   this._docRequest = null;
   CSPdebug("CSP POLICY INITED TO 'default-src *'");
 }
 
 /*
  * Set up mappings from nsIContentPolicy content types to CSP directives.
  */
@@ -206,23 +205,16 @@ ContentSecurityPolicy.prototype = {
     // We will only be able to provide the HTTP version information if aChannel
     // implements nsIHttpChannelInternal
     if (internalChannel) {
       var reqMaj = {};
       var reqMin = {};
       var reqVersion = internalChannel.getRequestVersion(reqMaj, reqMin);
       this._request += " HTTP/" + reqMaj.value + "." + reqMin.value;
     }
-
-    // grab the request headers
-    var self = this;
-    aChannel.visitRequestHeaders({
-      visitHeader: function(aHeader, aValue) {
-        self._requestHeaders.push(aHeader + ": " + aValue);
-      }});
   },
 
 /* ........ Methods .............. */
 
   /**
    * Given a new policy, intersects the currently enforced policy with the new
    * one and stores the result.  The effect is a "tightening" or refinement of
    * an old policy.  This is called any time a new policy is encountered and
@@ -265,31 +257,23 @@ ContentSecurityPolicy.prototype = {
   function(blockedUri, violatedDirective, aSourceFile, aScriptSample, aLineNum) {
     var uriString = this._policy.getReportURIs();
     var uris = uriString.split(/\s+/);
     if (uris.length > 0) {
       // Generate report to send composed of
       // {
       //   csp-report: {
       //     request: "GET /index.html HTTP/1.1",
-      //     request-headers: "Host: example.com
-      //                       User-Agent: ...
-      //                       ...",
       //     blocked-uri: "...",
       //     violated-directive: "..."
       //   }
       // }
-      var strHeaders = "";
-      for (let i in this._requestHeaders) {
-        strHeaders += this._requestHeaders[i] + "\n";
-      }
       var report = {
         'csp-report': {
           'request': this._request,
-          'request-headers': strHeaders,
           'blocked-uri': (blockedUri instanceof Ci.nsIURI ?
                           blockedUri.asciiSpec : blockedUri),
           'violated-directive': violatedDirective
         }
       }
       // extra report fields for script errors (if available)
       if (aSourceFile)
         report["csp-report"]["source-file"] = aSourceFile;
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -51,17 +51,17 @@
 #include "nsIDOMNodeList.h"
 #include "nsINodeList.h"
 #include "nsStubMutationObserver.h"
 #include "nsIAtom.h"
 #include "nsINameSpaceManager.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "nsCRT.h"
-#include "mozilla/dom/Element.h"
+#include "nsHashKeys.h"
 
 // Magic namespace id that means "match all namespaces".  This is
 // negative so it won't collide with actual namespace constants.
 #define kNameSpaceID_Wildcard PR_INT32_MIN
 
 // This is a callback function type that can be used to implement an
 // arbitrary matching algorithm.  aContent is the content that may
 // match the list, while aNamespaceID, aAtom, and aData are whatever
@@ -69,16 +69,21 @@
 typedef PRBool (*nsContentListMatchFunc)(nsIContent* aContent,
                                          PRInt32 aNamespaceID,
                                          nsIAtom* aAtom,
                                          void* aData);
 
 typedef void (*nsContentListDestroyFunc)(void* aData);
 
 class nsIDocument;
+namespace mozilla {
+namespace dom {
+class Element;
+}
+}
 
 
 class nsBaseContentList : public nsINodeList
 {
 public:
   virtual ~nsBaseContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -74,16 +74,18 @@
 #include "nsIFrame.h"
 
 // image copy stuff
 #include "nsIImageLoadingContent.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsContentUtils.h"
 #include "nsContentCID.h"
 
+#include "mozilla/dom/Element.h"
+
 nsresult NS_NewDomSelection(nsISelection **aDomSelection);
 
 static NS_DEFINE_CID(kCClipboardCID,           NS_CLIPBOARD_CID);
 static NS_DEFINE_CID(kCTransferableCID,        NS_TRANSFERABLE_CID);
 static NS_DEFINE_CID(kHTMLConverterCID,        NS_HTMLFORMATCONVERTER_CID);
 
 // private clipboard data flavors for html copy, used by editor when pasting
 #define kHTMLContext   "text/_moz_htmlcontext"
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1686,17 +1686,16 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentXBL)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMEventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
-    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer_MOZILLA_2_0_BRANCH)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDocument)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
                                  new nsNode3Tearoff(this))
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -485,17 +485,17 @@ protected:
 // nsIDOMXMLDocument's. nsDocument's QI should *not* claim to support
 // nsIDOMXMLDocument unless someone writes a real implementation of
 // the interface.
 class nsDocument : public nsIDocument,
                    public nsIDOMXMLDocument, // inherits nsIDOMDocument
                    public nsIDOMDocumentXBL,
                    public nsSupportsWeakReference,
                    public nsIScriptObjectPrincipal,
-                   public nsIRadioGroupContainer_MOZILLA_2_0_BRANCH,
+                   public nsIRadioGroupContainer,
                    public nsIApplicationCacheContainer,
                    public nsStubMutationObserver,
                    public nsIDOMDocumentTouch
 {
 public:
   typedef mozilla::dom::Element Element;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -77,16 +77,17 @@
 #include "nsISelectionPrivate.h"
 #include "nsITransferable.h" // for kUnicodeMime
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "nsTArray.h"
 #include "nsIFrame.h"
 #include "nsStringBuffer.h"
+#include "mozilla/dom/Element.h"
 
 nsresult NS_NewDomSelection(nsISelection **aDomSelection);
 
 enum nsRangeIterationDirection {
   kDirectionOut = -1,
   kDirectionIn = 1
 };
 
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -114,16 +114,17 @@
 #include "TabParent.h"
 #include "mozilla/layout/RenderFrameParent.h"
 
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
+using namespace mozilla::layout;
 typedef FrameMetrics::ViewID ViewID;
 
 #include "jsapi.h"
 
 class nsAsyncDocShellDestroyer : public nsRunnable
 {
 public:
   nsAsyncDocShellDestroyer(nsIDocShell* aDocShell)
@@ -165,32 +166,35 @@ nsContentView::Update(const ViewConfig& 
 {
   if (aConfig == mConfig) {
     return NS_OK;
   }
   mConfig = aConfig;
 
   // View changed.  Try to locate our subdoc frame and invalidate
   // it if found.
-  if (!mOwnerContent) {
+  if (!mFrameLoader) {
     if (IsRoot()) {
       // Oops, don't have a frame right now.  That's OK; the view
       // config persists and will apply to the next frame we get, if we
       // ever get one.
       return NS_OK;
     } else {
       // This view is no longer valid.
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
-  nsIFrame* frame = mOwnerContent->GetPrimaryFrame();
+  if (RenderFrameParent* rfp = mFrameLoader->GetCurrentRemoteFrame()) {
+    rfp->ContentViewScaleChanged(this);
+  }
 
   // XXX could be clever here and compute a smaller invalidation
   // rect
+  nsIFrame* frame = mFrameLoader->GetPrimaryFrameOfOwningContent();
   InvalidateFrame(frame);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentView::ScrollTo(float aXpx, float aYpx)
 {
   ViewConfig config(mConfig);
@@ -909,17 +913,19 @@ nsFrameLoader::ShowRemoteFrame(const nsI
   // cross-process layers; need to figure out what behavior we really
   // want here.  For now, hack.
   if (!mRemoteBrowserShown) {
     mRemoteBrowser->Show(size);
     mRemoteBrowserShown = PR_TRUE;
 
     EnsureMessageManager();
   } else {
-    mRemoteBrowser->Move(size);
+    nsRect dimensions;
+    NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
+    mRemoteBrowser->UpdateDimensions(dimensions, size);
   }
 
   return true;
 }
 
 void
 nsFrameLoader::Hide()
 {
@@ -1595,23 +1601,59 @@ nsFrameLoader::CheckForRecursiveLoad(nsI
     nsCOMPtr<nsIDocShellTreeItem> temp;
     temp.swap(parentAsItem);
     temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
   }
 
   return NS_OK;
 }
 
+nsresult
+nsFrameLoader::GetWindowDimensions(nsRect& aRect)
+{
+  // Need to get outer window position here
+  nsIDocument* doc = mOwnerContent->GetDocument();
+  if (!doc) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (doc->GetDisplayDocument()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIWebNavigation> parentAsWebNav =
+    do_GetInterface(doc->GetScriptGlobalObject());
+
+  if (!parentAsWebNav) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIDocShellTreeItem> parentAsItem(do_QueryInterface(parentAsWebNav));
+
+  nsCOMPtr<nsIDocShellTreeOwner> parentOwner;
+  if (NS_FAILED(parentAsItem->GetTreeOwner(getter_AddRefs(parentOwner))) ||
+      !parentOwner) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_GetInterface(parentOwner));
+  treeOwnerAsWin->GetPosition(&aRect.x, &aRect.y);
+  treeOwnerAsWin->GetSize(&aRect.width, &aRect.height);
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsFrameLoader::UpdatePositionAndSize(nsIFrame *aIFrame)
 {
   if (mRemoteFrame) {
     if (mRemoteBrowser) {
       nsIntSize size = GetSubDocumentSize(aIFrame);
-      mRemoteBrowser->Move(size);
+      nsRect dimensions;
+      NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
+      mRemoteBrowser->UpdateDimensions(dimensions, size);
     }
     return NS_OK;
   }
   return UpdateBaseWindowPositionAndSize(aIFrame);
 }
 
 nsresult
 nsFrameLoader::UpdateBaseWindowPositionAndSize(nsIFrame *aIFrame)
--- a/content/base/src/nsFrameLoader.h
+++ b/content/base/src/nsFrameLoader.h
@@ -48,18 +48,18 @@
 #include "nsStringFwd.h"
 #include "nsIFrameLoader.h"
 #include "nsPoint.h"
 #include "nsSize.h"
 #include "nsIURI.h"
 #include "nsAutoPtr.h"
 #include "nsFrameMessageManager.h"
 #include "Layers.h"
+#include "nsIContent.h"
 
-class nsIContent;
 class nsIURI;
 class nsSubDocumentFrame;
 class nsIView;
 class nsIInProcessContentFrameMessageManager;
 class AutoResetInShow;
 
 namespace mozilla {
 namespace dom {
@@ -122,21 +122,21 @@ public:
     // enclosed content document.  If content-document layers have a
     // lower or higher resolution than the desired scale, then the
     // ratio is used to define a scale transform when painting the
     // content document.
     float mXScale;
     float mYScale;
   };
 
-  nsContentView(nsIContent* aOwnerContent, ViewID aScrollId,
+  nsContentView(nsFrameLoader* aFrameLoader, ViewID aScrollId,
                 ViewConfig aConfig = ViewConfig())
     : mViewportSize(0, 0)
     , mContentSize(0, 0)
-    , mOwnerContent(aOwnerContent)
+    , mFrameLoader(aFrameLoader)
     , mScrollId(aScrollId)
     , mConfig(aConfig)
   {}
 
   bool IsRoot() const;
 
   ViewID GetId() const
   {
@@ -146,17 +146,17 @@ public:
   ViewConfig GetViewConfig() const
   {
     return mConfig;
   }
 
   nsSize mViewportSize;
   nsSize mContentSize;
 
-  nsIContent *mOwnerContent; // WEAK
+  nsFrameLoader* mFrameLoader;  // WEAK
 
 private:
   nsresult Update(const ViewConfig& aConfig);
 
   ViewID mScrollId;
   ViewConfig mConfig;
 };
 
@@ -291,16 +291,17 @@ private:
    * initialize mDocShell.
    */
   nsresult MaybeCreateDocShell();
   nsresult EnsureMessageManager();
   NS_HIDDEN_(void) GetURL(nsString& aURL);
 
   // Properly retrieves documentSize of any subdocument type.
   NS_HIDDEN_(nsIntSize) GetSubDocumentSize(const nsIFrame *aIFrame);
+  nsresult GetWindowDimensions(nsRect& aRect);
 
   // Updates the subdocument position and size. This gets called only
   // when we have our own in-process DocShell.
   NS_HIDDEN_(nsresult) UpdateBaseWindowPositionAndSize(nsIFrame *aIFrame);
   nsresult CheckURILoad(nsIURI* aURI);
   void FireErrorEvent();
   nsresult ReallyStartLoadingInternal();
 
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1221,34 +1221,30 @@ nsIContent::UpdateEditableState(PRBool a
   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
 }
 
 void
 nsGenericElement::UpdateEditableState(PRBool aNotify)
 {
   nsIContent *parent = GetParent();
 
-  PRBool oldEditable = IsEditable();
   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
-  PRBool newEditable = IsEditable();
-  if (oldEditable != newEditable) {
-    if (aNotify) {
-      UpdateState(aNotify);
+  if (aNotify) {
+    UpdateState(aNotify);
+  } else {
+    // Avoid calling UpdateState in this very common case, because
+    // this gets called for pretty much every single element on
+    // insertion into the document and UpdateState can be slow for
+    // some kinds of elements even when not notifying.
+    if (IsEditable()) {
+      RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
+      AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
     } else {
-      // Avoid calling UpdateState in this very common case, because
-      // this gets called for pretty much every single element on
-      // insertion into the document and UpdateState can be slow for
-      // some kinds of elements even when not notifying.
-      if (oldEditable) {
-        RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
-        AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
-      } else {
-        RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
-        AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
-      }
+      RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
+      AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
     }
   }
 }
 
 nsIContent*
 nsIContent::FindFirstNonNativeAnonymous() const
 {
   // This handles also nested native anonymous content.
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -251,17 +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(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
@@ -74,16 +74,17 @@
 #include "nsContentUtils.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsDOMClassInfo.h"
 #include "nsSVGEffects.h"
 
 #include "mozAutoDocUpdate.h"
+#include "mozilla/dom/Element.h"
 
 #ifdef DEBUG_chb
 static void PrintReqURL(imgIRequest* req) {
   if (!req) {
     printf("(null req)\n");
     return;
   }
 
--- a/content/base/src/nsImageLoadingContent.h
+++ b/content/base/src/nsImageLoadingContent.h
@@ -47,16 +47,17 @@
 
 #include "nsIImageLoadingContent.h"
 #include "nsINode.h"
 #include "imgIRequest.h"
 #include "prtypes.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsString.h"
+#include "nsEventStates.h"
 
 class nsIURI;
 class nsIDocument;
 class imgILoader;
 class nsIIOService;
 
 class nsImageLoadingContent : public nsIImageLoadingContent
 {
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -50,16 +50,18 @@
 #include "nsDOMString.h"
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 #include "nsReadableUtils.h"
 #include "nsAutoPtr.h"
 #include NEW_H
 #include "nsFixedSizeAllocator.h"
 #include "prprf.h"
+#include "nsIDocument.h"
+#include "nsGkAtoms.h"
 
 static const size_t kNodeInfoPoolSizes[] = {
   sizeof(nsNodeInfo)
 };
 
 static const PRInt32 kNodeInfoPoolInitialSize = 
   (NS_SIZE_IN_HEAP(sizeof(nsNodeInfo))) * 64;
 
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -91,16 +91,17 @@
 // Concrete classes
 #include "nsFrameLoader.h"
 
 #include "nsObjectLoadingContent.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
+#include "mozilla/dom/Element.h"
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
 #endif
 
 #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
 
--- a/content/base/src/nsTreeWalker.cpp
+++ b/content/base/src/nsTreeWalker.cpp
@@ -42,16 +42,18 @@
  * Implementation of DOM Traversal's nsIDOMTreeWalker
  */
 
 #include "nsTreeWalker.h"
 
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsDOMError.h"
+#include "nsINode.h"
+#include "nsIContent.h"
 
 #include "nsContentUtils.h"
 
 /*
  * Factories, constructors and destructors
  */
 
 nsTreeWalker::nsTreeWalker(nsINode *aRoot,
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -1012,18 +1012,18 @@ nsWebSocket::ParseURL(const nsString& aU
     filePath.AssignLiteral("/");
   }
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
   nsCAutoString query;
   rv = parsedURL->GetQuery(query);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
-  nsXPIDLCString origin;
-  rv = mPrincipal->GetOrigin(getter_Copies(origin));
+  nsCString origin;
+  rv = nsContentUtils::GetASCIIOrigin(mPrincipal, origin);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
   if (scheme.LowerCaseEqualsLiteral("ws")) {
      mSecure = PR_FALSE;
      mPort = (port == -1) ? DEFAULT_WS_SCHEME_PORT : port;
   } else if (scheme.LowerCaseEqualsLiteral("wss")) {
     mSecure = PR_TRUE;
     mPort = (port == -1) ? DEFAULT_WSS_SCHEME_PORT : port;
@@ -1347,25 +1347,26 @@ nsWebSocket::Init(nsIPrincipal* aPrincip
     mWindowID = nsJSUtils::GetCurrentlyRunningCodeWindowID(cx);
   }
 
   // parses the url
   rv = ParseURL(PromiseFlatString(aURL));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Don't allow https:// to open ws://
-  nsCOMPtr<nsIURI> originURI;
-  PRBool originHTTPS;
   if (!mSecure && 
       !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS",
-                            PR_FALSE) &&
-      NS_SUCCEEDED(NS_NewURI(getter_AddRefs(originURI), mUTF16Origin)) &&
-      NS_SUCCEEDED(originURI->SchemeIs("https", &originHTTPS)) &&
-      originHTTPS) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+                            PR_FALSE)) {
+    // Confirmed we are opening plain ws:// and want to prevent this from a
+    // secure context (e.g. https). Check the security context of the document
+    // associated with this script, which is the same as associated with mOwner.
+    nsCOMPtr<nsIDocument> originDoc =
+      nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    if (originDoc && originDoc->GetSecurityInfo())
+      return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   // sets the protocol
   if (!aProtocol.IsEmpty()) {
     rv = SetProtocol(PromiseFlatString(aProtocol));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/content/html/content/public/nsIRadioGroupContainer.h
+++ b/content/html/content/public/nsIRadioGroupContainer.h
@@ -40,18 +40,18 @@
 #include "nsISupports.h"
 
 class nsIDOMHTMLInputElement;
 class nsString;
 class nsIRadioVisitor;
 class nsIFormControl;
 
 #define NS_IRADIOGROUPCONTAINER_IID   \
-{ 0x06de7839, 0xd0db, 0x47d3, \
-  { 0x82, 0x90, 0x3c, 0xb8, 0x62, 0x2e, 0xd9, 0x66 } }
+{ 0x22924a01, 0x4360, 0x401b, \
+  { 0xb1, 0xd1, 0x56, 0x8d, 0xf5, 0xa3, 0xda, 0x71 } }
 
 /**
  * A container that has multiple radio groups in it, defined by name.
  */
 class nsIRadioGroupContainer : public nsISupports
 {
 public:
 
@@ -127,33 +127,20 @@ public:
    * @param aRadio radio button's pointer
    * @param aPositionIndex out indicates 0-indexed position in the radio group,
    *                           or just 0 if a group cannot be found
    * @param aItemsInGroup the number of radio buttons in the group
    */
   NS_IMETHOD GetPositionInGroup(nsIDOMHTMLInputElement *aRadio,
                                 PRInt32 *aPositionIndex,
                                 PRInt32 *aItemsInGroup) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIRadioGroupContainer,
-                              NS_IRADIOGROUPCONTAINER_IID)
-
-#define NS_IRADIOGROUPCONTAINER_MOZILLA_2_0_BRANCH_IID \
-{ 0xaa9ec446, 0xcdc7, 0x4030, \
-  { 0xab, 0x02, 0xda, 0x44, 0xee, 0xb1, 0x80, 0x0a } }
-
-class nsIRadioGroupContainer_MOZILLA_2_0_BRANCH : public nsIRadioGroupContainer
-{
-public:
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IRADIOGROUPCONTAINER_MOZILLA_2_0_IID)
 
   virtual PRUint32 GetRequiredRadioCount(const nsAString& aName) const = 0;
   virtual void RadioRequiredChanged(const nsAString& aName,
                                     nsIFormControl* aRadio) = 0;
   virtual bool GetValueMissingState(const nsAString& aName) const = 0;
   virtual void SetValueMissingState(const nsAString& aName, bool aValue) = 0;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIRadioGroupContainer_MOZILLA_2_0_BRANCH,
-                              NS_IRADIOGROUPCONTAINER_MOZILLA_2_0_BRANCH_IID)
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIRadioGroupContainer,
+                              NS_IRADIOGROUPCONTAINER_IID)
 
 #endif /* nsIRadioGroupContainer_h__ */
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2870,16 +2870,30 @@ nsGenericHTMLFormElement::FormIdUpdated(
 
   NS_ASSERTION(element->IsHTML(), "aData should be an HTML element");
 
   element->UpdateFormOwner(false, aNewElement);
 
   return PR_TRUE;
 }
 
+PRBool 
+nsGenericHTMLFormElement::IsElementDisabledForEvents(PRUint32 aMessage, 
+                                                    nsIFrame* aFrame)
+{
+  PRBool disabled = IsDisabled();
+  if (!disabled && aFrame) {
+    const nsStyleUserInterface* uiStyle = aFrame->GetStyleUserInterface();
+    disabled = uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
+      uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED;
+
+  }
+  return disabled && aMessage != NS_MOUSE_MOVE;
+}
+
 void
 nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
                                           Element* aFormIdElement)
 {
   NS_PRECONDITION(!aBindToTree || !aFormIdElement,
                   "aFormIdElement shouldn't be set if aBindToTree is true!");
 
   PRBool needStateUpdate = PR_FALSE;
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -941,16 +941,19 @@ protected:
   /**
    * This method is a a callback for IDTargetObserver (from nsIDocument).
    * It will be called each time the element associated with the id in @form
    * changes.
    */
   static PRBool FormIdUpdated(Element* aOldElement, Element* aNewElement,
                               void* aData);
 
+  // Returns true if the event should not be handled from PreHandleEvent
+  virtual PRBool IsElementDisabledForEvents(PRUint32 aMessage, nsIFrame* aFrame);
+
   // The focusability state of this form control.  eUnfocusable means that it
   // shouldn't be focused at all, eInactiveWindow means it's in an inactive
   // window, eActiveWindow means it's in an active window.
   enum FocusTristate {
     eUnfocusable,
     eInactiveWindow,
     eActiveWindow
   };
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -277,33 +277,25 @@ nsHTMLButtonElement::ParseAttribute(PRIn
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 nsresult
 nsHTMLButtonElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
-  // Do not process any DOM events if the element is disabled
-  aVisitor.mCanHandle = PR_FALSE;
-  if (IsDisabled()) {
-    return NS_OK;
+  nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
+  nsIFrame* formFrame = NULL;
+  if (formControlFrame) {
+    formFrame = do_QueryFrame(formControlFrame);
   }
 
-  nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
-
-  if (formControlFrame) {
-    nsIFrame* formFrame = do_QueryFrame(formControlFrame);
-    if (formFrame) {
-      const nsStyleUserInterface* uiStyle = formFrame->GetStyleUserInterface();
-
-      if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
-          uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED)
-        return NS_OK;
-    }
+  aVisitor.mCanHandle = PR_FALSE;
+  if (IsElementDisabledForEvents(aVisitor.mEvent->message, formFrame)) {
+    return NS_OK;
   }
 
   // Track whether we're in the outermost Dispatch invocation that will
   // cause activation of the input.  That is, if we're a click event, or a
   // DOMActivate that was dispatched directly, this will be set, but if we're
   // a DOMActivate dispatched from click handling, it will not be set.
   PRBool outerActivateEvent =
     (NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) ||
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -36,16 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHTMLFieldSetElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsStyleConsts.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
+#include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(FieldSet)
 
 
 nsHTMLFieldSetElement::nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLFormElement(aNodeInfo)
@@ -104,17 +105,17 @@ NS_IMPL_STRING_ATTR(nsHTMLFieldSetElemen
 NS_IMPL_NSICONSTRAINTVALIDATION(nsHTMLFieldSetElement)
 
 // nsIContent
 nsresult
 nsHTMLFieldSetElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   // Do not process any DOM events if the element is disabled.
   aVisitor.mCanHandle = PR_FALSE;
-  if (IsDisabled()) {
+  if (IsElementDisabledForEvents(aVisitor.mEvent->message, NULL)) {
     return NS_OK;
   }
 
   return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
 }
 
 nsresult
 nsHTMLFieldSetElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -323,22 +323,21 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_ADDREF_INHERITED(nsHTMLFormElement, nsGenericElement) 
 NS_IMPL_RELEASE_INHERITED(nsHTMLFormElement, nsGenericElement) 
 
 
 DOMCI_NODE_DATA(HTMLFormElement, nsHTMLFormElement)
 
 // QueryInterface implementation for nsHTMLFormElement
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLFormElement)
-  NS_HTML_CONTENT_INTERFACE_TABLE5(nsHTMLFormElement,
+  NS_HTML_CONTENT_INTERFACE_TABLE4(nsHTMLFormElement,
                                    nsIDOMHTMLFormElement,
                                    nsIForm,
                                    nsIWebProgressListener,
-                                   nsIRadioGroupContainer,
-                                   nsIRadioGroupContainer_MOZILLA_2_0_BRANCH)
+                                   nsIRadioGroupContainer)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLFormElement,
                                                nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLFormElement)
 
 
 // nsIDOMHTMLFormElement
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsHTMLFormElement)
--- a/content/html/content/src/nsHTMLFormElement.h
+++ b/content/html/content/src/nsHTMLFormElement.h
@@ -89,17 +89,17 @@ public:
 private:
   const nsString mStr;
 };
 
 class nsHTMLFormElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLFormElement,
                           public nsIWebProgressListener,
                           public nsIForm,
-                          public nsIRadioGroupContainer_MOZILLA_2_0_BRANCH
+                          public nsIRadioGroupContainer
 {
 public:
   nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLFormElement();
 
   nsresult Init();
 
   // nsISupports
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -231,17 +231,17 @@ static const nsAttrValue::EnumTable kCro
   { "",                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_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;
@@ -346,17 +346,17 @@ 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) {
+    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,
@@ -650,15 +650,15 @@ nsHTMLImageElement::CopyInnerTo(nsGeneri
   return nsGenericHTMLElement::CopyInnerTo(aDest);
 }
 
 nsImageLoadingContent::CORSMode
 nsHTMLImageElement::GetCORSMode()
 {
   nsImageLoadingContent::CORSMode ret = nsImageLoadingContent::CORS_NONE;
 
-  const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossOrigin);
+  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
@@ -878,19 +878,17 @@ nsHTMLInputElement::AfterSetAttr(PRInt32
         nsAutoString src;
         if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
           LoadImage(src, PR_FALSE, aNotify);
         }
       }
     }
 
     if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
-      nsIRadioGroupContainer* c = GetRadioGroupContainer();
-      nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
-        do_QueryInterface(c);
+      nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
 
       if (container) {
         nsAutoString name;
         GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
         container->RadioRequiredChanged(name, this);
       }
     }
 
@@ -1849,34 +1847,20 @@ nsHTMLInputElement::NeedToInitializeEdit
   return PR_FALSE;
 }
 
 nsresult
 nsHTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   // Do not process any DOM events if the element is disabled
   aVisitor.mCanHandle = PR_FALSE;
-  if (IsDisabled()) {
+  if (IsElementDisabledForEvents(aVisitor.mEvent->message, GetPrimaryFrame())) {
     return NS_OK;
   }
 
-  // For some reason or another we also need to check if the style shows us
-  // as disabled.
-  {
-    nsIFrame* frame = GetPrimaryFrame();
-    if (frame) {
-      const nsStyleUserInterface* uiStyle = frame->GetStyleUserInterface();
-
-      if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
-          uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
-        return NS_OK;
-      }
-    }
-  }
-
   // Initialize the editor if needed.
   if (NeedToInitializeEditorForEvent(aVisitor)) {
     nsITextControlFrame* textControlFrame = do_QueryFrame(GetPrimaryFrame());
     if (textControlFrame)
       textControlFrame->EnsureEditorInitialized();
   }
 
   //FIXME Allow submission etc. also when there is no prescontext, Bug 329509.
@@ -3352,20 +3336,18 @@ nsHTMLInputElement::AddedToRadioGroup()
   nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
   if (container) {
     nsAutoString name;
     GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
     container->AddToRadioGroup(name, static_cast<nsIFormControl*>(this));
 
     // We initialize the validity of the element to the validity of the group
     // because we assume UpdateValueMissingState() will be called after.
-    nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container2 =
-      do_QueryInterface(container);
     SetValidityState(VALIDITY_STATE_VALUE_MISSING,
-                     container2->GetValueMissingState(name));
+                     container->GetValueMissingState(name));
   }
 }
 
 void
 nsHTMLInputElement::WillRemoveFromRadioGroup()
 {
   nsIRadioGroupContainer* container = GetRadioGroupContainer();
   if (!container) {
@@ -3742,19 +3724,17 @@ nsHTMLInputElement::UpdateValueMissingVa
   // If there is no selection, that might mean the radio is not in a group.
   // In that case, we can look for the checked state of the radio.
   bool selected = selection ? true
                             : aIgnoreSelf ? false : GetChecked();
   bool required = aIgnoreSelf ? false
                               : HasAttr(kNameSpaceID_None, nsGkAtoms::required);
   bool valueMissing = false;
 
-  nsIRadioGroupContainer* c = GetRadioGroupContainer();
-  nsCOMPtr<nsIRadioGroupContainer_MOZILLA_2_0_BRANCH> container =
-    do_QueryInterface(c);
+  nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
 
   if (!container) {
     SetValidityState(VALIDITY_STATE_VALUE_MISSING, required && !selected);
     return;
   }
 
   nsAutoString name;
   GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -638,17 +638,17 @@ nsHTMLSelectElement::GetSelectFrame()
 
   if (form_control_frame) {
     select_frame = do_QueryFrame(form_control_frame);
   }
 
   return select_frame;
 }
 
-NS_IMETHODIMP
+nsresult
 nsHTMLSelectElement::Add(nsIDOMHTMLElement* aElement,
                          nsIDOMHTMLElement* aBefore)
 {
   nsCOMPtr<nsIDOMNode> added;
   if (!aBefore) {
     return AppendChild(aElement, getter_AddRefs(added));
   }
 
@@ -675,16 +675,54 @@ nsHTMLSelectElement::Add(nsIDOMHTMLEleme
   }
 
   // If the before parameter is not null, we are equivalent to the
   // insertBefore method on the parent of before.
   return parent->InsertBefore(aElement, aBefore, getter_AddRefs(added));
 }
 
 NS_IMETHODIMP
+nsHTMLSelectElement::Add(nsIDOMHTMLElement* aElement,
+                         nsIVariant* aBefore)
+{
+  PRUint16 dataType;
+  nsresult rv = aBefore->GetDataType(&dataType);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // aBefore is omitted or null
+  if (dataType == nsIDataType::VTYPE_EMPTY) {
+    return Add(aElement);
+  }
+
+  nsCOMPtr<nsISupports> supports;
+  nsCOMPtr<nsIDOMHTMLElement> beforeElement;
+
+  // whether aBefore is nsIDOMHTMLElement...
+  if (NS_SUCCEEDED(aBefore->GetAsISupports(getter_AddRefs(supports)))) {
+    beforeElement = do_QueryInterface(supports);
+
+    NS_ENSURE_TRUE(beforeElement, NS_ERROR_DOM_SYNTAX_ERR);
+    return Add(aElement, beforeElement);
+  }
+
+  // otherwise, whether aBefore is long
+  PRInt32 index;
+  NS_ENSURE_SUCCESS(aBefore->GetAsInt32(&index), NS_ERROR_DOM_SYNTAX_ERR);
+
+  // If item index is out of range, insert to last.
+  // (since beforeElement becomes null, it is inserted to last)
+  nsCOMPtr<nsIDOMNode> beforeNode;
+  if (NS_SUCCEEDED(Item(index, getter_AddRefs(beforeNode)))) {
+    beforeElement = do_QueryInterface(beforeNode);
+  }
+
+  return Add(aElement, beforeElement);
+}
+
+NS_IMETHODIMP
 nsHTMLSelectElement::Remove(PRInt32 aIndex)
 {
   nsCOMPtr<nsIDOMNode> option;
   Item(aIndex, getter_AddRefs(option));
 
   if (option) {
     nsCOMPtr<nsIDOMNode> parent;
 
@@ -1499,34 +1537,25 @@ nsHTMLSelectElement::GetAttributeMapping
 {
   return &MapAttributesIntoRule;
 }
 
 
 nsresult
 nsHTMLSelectElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
-  aVisitor.mCanHandle = PR_FALSE;
-  // Do not process any DOM events if the element is disabled
-  // XXXsmaug This is not the right thing to do. But what is?
-  if (IsDisabled()) {
-    return NS_OK;
-  }
-
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
   nsIFrame* formFrame = nsnull;
-
-  if (formControlFrame &&
-      (formFrame = do_QueryFrame(formControlFrame))) {
-    const nsStyleUserInterface* uiStyle = formFrame->GetStyleUserInterface();
+  if (formControlFrame) {
+    formFrame = do_QueryFrame(formControlFrame);
+  }
 
-    if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
-        uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
-      return NS_OK;
-    }
+  aVisitor.mCanHandle = PR_FALSE;
+  if (IsElementDisabledForEvents(aVisitor.mEvent->message, formFrame)) {
+    return NS_OK;
   }
 
   return nsGenericHTMLFormElement::PreHandleEvent(aVisitor);
 }
 
 nsresult
 nsHTMLSelectElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
@@ -2198,45 +2227,27 @@ NS_IMETHODIMP
 nsHTMLOptionCollection::GetSelect(nsIDOMHTMLSelectElement **aReturn)
 {
   NS_IF_ADDREF(*aReturn = mSelect);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::Add(nsIDOMHTMLOptionElement *aOption,
-                            PRInt32 aIndex, PRUint8 optional_argc)
+                            nsIVariant *aBefore)
 {
   if (!aOption) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (aIndex < -1) {
-    return NS_ERROR_DOM_INDEX_SIZE_ERR;
-  }
-
   if (!mSelect) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  PRUint32 length;
-  GetLength(&length);
-
-  if (optional_argc == 0 || aIndex == -1 || aIndex > (PRInt32)length) {
-    // IE appends in these cases
-    aIndex = length;
-  }
-
-  nsCOMPtr<nsIDOMNode> beforeNode;
-  Item(aIndex, getter_AddRefs(beforeNode));
-
-  nsCOMPtr<nsIDOMHTMLOptionElement> beforeElement =
-    do_QueryInterface(beforeNode);
-
-  return mSelect->Add(aOption, beforeElement);
+  return mSelect->Add(aOption, aBefore);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::Remove(PRInt32 aIndex)
 {
   NS_ENSURE_TRUE(mSelect, NS_ERROR_UNEXPECTED);
 
   PRUint32 len = 0;
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -607,16 +607,21 @@ protected:
      */
     if (mForm && mForm->HasEverTriedInvalidSubmit()) {
       return true;
     }
 
     return mSelectionHasChanged;
   }
 
+  /**
+   * Insert aElement before the node given by aBefore
+   */
+  nsresult Add(nsIDOMHTMLElement* aElement, nsIDOMHTMLElement* aBefore = nsnull);
+
   /** The options[] array */
   nsRefPtr<nsHTMLOptionCollection> mOptions;
   /** false if the parser is in the middle of adding children. */
   PRPackedBool    mIsDoneAddingChildren;
   /** true if our disabled state has changed from the default **/
   PRPackedBool    mDisabledChanged;
   /** true if child nodes are being added or removed.
    *  Used by nsSafeOptionListMutation.
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -672,33 +672,25 @@ nsMapRuleToAttributesFunc
 nsHTMLTextAreaElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 nsresult
 nsHTMLTextAreaElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
-  // Do not process any DOM events if the element is disabled
-  aVisitor.mCanHandle = PR_FALSE;
-  if (IsDisabled()) {
-    return NS_OK;
+  nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
+  nsIFrame* formFrame = NULL;
+  if (formControlFrame) {
+    formFrame = do_QueryFrame(formControlFrame);
   }
 
-  nsIFormControlFrame* formControlFrame = GetFormControlFrame(PR_FALSE);
-  nsIFrame* formFrame = nsnull;
-
-  if (formControlFrame &&
-      (formFrame = do_QueryFrame(formControlFrame))) {
-    const nsStyleUserInterface* uiStyle = formFrame->GetStyleUserInterface();
-
-    if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE ||
-        uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) {
-      return NS_OK;
-    }
+  aVisitor.mCanHandle = PR_FALSE;
+  if (IsElementDisabledForEvents(aVisitor.mEvent->message, formFrame)) {
+    return NS_OK;
   }
 
   // Don't dispatch a second select event if we are already handling
   // one.
   if (aVisitor.mEvent->message == NS_FORM_SELECTED) {
     if (mHandlingSelect) {
       return NS_OK;
     }
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -929,17 +929,18 @@ nsTextInputListener::GetKeyBindings()
 // nsTextEditorState
 
 nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
   : mTextCtrlElement(aOwningElement),
     mRestoringSelection(nsnull),
     mBoundFrame(nsnull),
     mTextListener(nsnull),
     mEditorInitialized(PR_FALSE),
-    mInitializing(PR_FALSE)
+    mInitializing(PR_FALSE),
+    mValueTransferInProgress(PR_FALSE)
 {
   MOZ_COUNT_CTOR(nsTextEditorState);
 }
 
 nsTextEditorState::~nsTextEditorState()
 {
   MOZ_COUNT_DTOR(nsTextEditorState);
   Clear();
@@ -1008,27 +1009,30 @@ class PrepareEditorEvent : public nsRunn
 public:
   PrepareEditorEvent(nsTextEditorState &aState,
                      nsIContent *aOwnerContent,
                      const nsAString &aCurrentValue)
     : mState(aState)
     , mOwnerContent(aOwnerContent)
     , mCurrentValue(aCurrentValue)
   {
+    mState.mValueTransferInProgress = PR_TRUE;
   }
 
   NS_IMETHOD Run() {
     // Transfer the saved value to the editor if we have one
     const nsAString *value = nsnull;
     if (!mCurrentValue.IsEmpty()) {
       value = &mCurrentValue;
     }
 
     mState.PrepareEditor(value);
 
+    mState.mValueTransferInProgress = PR_FALSE;
+
     return NS_OK;
   }
 
 private:
   nsTextEditorState &mState;
   nsCOMPtr<nsIContent> mOwnerContent; // strong reference
   nsAutoString mCurrentValue;
 };
@@ -1493,17 +1497,20 @@ nsTextEditorState::UnbindFromFrame(nsTex
 
     NS_RELEASE(mTextListener);
     mTextListener = nsnull;
   }
 
   mBoundFrame = nsnull;
 
   // Now that we don't have a frame any more, store the value in the text buffer.
-  SetValue(value, PR_FALSE);
+  // The only case where we don't do this is if a value transfer is in progress.
+  if (!mValueTransferInProgress) {
+    SetValue(value, PR_FALSE);
+  }
 
   if (mRootNode && mMutationObserver) {
     mRootNode->RemoveMutationObserver(mMutationObserver);
     mMutationObserver = nsnull;
   }
 
   // Unbind the anonymous content from the tree.
   // We actually hold a reference to the content nodes so that
--- a/content/html/content/src/nsTextEditorState.h
+++ b/content/html/content/src/nsTextEditorState.h
@@ -250,26 +250,28 @@ private:
     PRBool IsInitializingRecursively() const {
       return !mGuardSet;
     }
   private:
     nsTextEditorState& mState;
     PRBool mGuardSet;
   };
   friend class InitializationGuard;
+  friend class PrepareEditorEvent;
 
   nsITextControlElement* const mTextCtrlElement;
   nsRefPtr<nsTextInputSelectionImpl> mSelCon;
   nsAutoPtr<SelectionState> mSelState;
   RestoreSelectionState* mRestoringSelection;
   nsCOMPtr<nsIEditor> mEditor;
   nsCOMPtr<nsIContent> mRootNode;
   nsCOMPtr<nsIContent> mPlaceholderDiv;
   nsTextControlFrame* mBoundFrame;
   nsTextInputListener* mTextListener;
   nsAutoPtr<nsCString> mValue;
   nsRefPtr<nsAnonDivObserver> mMutationObserver;
   mutable nsString mCachedValue; // Caches non-hard-wrapped value on a multiline control.
   PRPackedBool mEditorInitialized;
   PRPackedBool mInitializing; // Whether we're in the process of initialization
+  PRPackedBool mValueTransferInProgress; // Whether a value is being transferred to the frame
 };
 
 #endif
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -86,16 +86,17 @@ include $(topsrcdir)/config/rules.mk
 		bug242709_load.html \
 		test_bug242709.html \
 		bug277724_iframe1.html \
 		bug277724_iframe2.xhtml \
 		test_bug277724.html \
 		bug277890_iframe.html \
 		bug277890_load.html \
 		test_bug277890.html \
+		test_bug274626.html \
 		test_bug287465.html \
 		test_bug209275.xhtml \
 		file_bug209275_1.html \
 		file_bug209275_2.html \
 		file_bug209275_3.html \
 		test_bug295561.html \
 		test_bug300691-1.html \
 		test_bug300691-2.html \
@@ -269,14 +270,16 @@ include $(topsrcdir)/config/rules.mk
 		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_bug664299.html \
+		test_bug666200.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_bug274626.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=274626
+-->
+<head>
+  <title>Test for Bug 274626</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="/tests/SimpleTest/EventUtils.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=274626">Mozilla Bug 274626</a>
+<br>
+
+<input id='textbox_enabled' title='hello' value='hello' />
+<input id='textbox_disabled' title='hello' value='hello' disabled/>
+
+<br>
+<input id='input_button_enabled' title='hello' value='hello' type='button' />
+<input id='input_button_disabled' title='hello' value='hello' type='button' disabled />
+
+<br>
+<input id='checkbox_enabled' title='hello' type='checkbox'>hello</input>
+<input id='checkbox_disabled' title='hello' type='checkbox' disabled >hello</input>
+
+<br>
+<button id='button_enabled' title='hello' value='hello' type='button'>test</button>
+<button id='button_disabled' title='hello' value='hello' type='button' disabled>test</button>
+
+<br>
+<textarea id='textarea_enabled' title='hello' value='hello' onclick="alert('click event');"> </textarea>
+<textarea id='textarea_disabled' title='hello' value='hello' onclick="alert('click event');" disabled></textarea>
+
+
+<br>
+<select id='select_enabled' title='hello' onclick="alert('click event');">
+  <option value='item1'>item1</option>
+  <option value='item2'>item2</option>
+</select>
+<select id='select_disabled' title='hello' onclick="alert('click event');" disabled>
+  <option value='item1'>item1</option>
+  <option value='item2'>item2</option>
+</select>
+
+<br>
+<form>
+  <fieldset id='fieldset_enabled' title='hello' onclick="alert('click event');">
+    <legend>Enabled fieldset:</legend>
+    Name: <input type='text' size='30' /><br />
+    Email: <input type='text' size='30' /><br />
+    Date of birth: <input type='text' size='10' />
+  </fieldset>
+</form>
+<form>
+  <fieldset id='fieldset_disabled' title='hello' onclick="alert('click event');" disabled>
+    <legend>Disabled fieldset:</legend>
+    Name: <input type='text' size='30' /><br />
+    Email: <input type='text' size='30' /><br />
+    Date of birth: <input type='text' size='10' />
+  </fieldset>
+</form>
+
+<script class="testbody" type="application/javascript">
+
+/** Test for Bug 274626 **/
+
+  function HandlesMouseMove(evt) { 
+	evt.target.handlesMouseMove = true;
+  }
+
+  var controls=["textbox_enabled","textbox_disabled",
+    "input_button_enabled", "input_button_disabled", "checkbox_enabled", 
+    "checkbox_disabled", "button_enabled", "button_disabled",
+    "textarea_enabled", "textarea_disabled", "select_enabled", 
+    "select_disabled", "fieldset_enabled", "fieldset_disabled"];
+
+  for each(id in controls) {
+    var ctrl = document.getElementById(id);
+    ctrl.addEventListener('mousemove', HandlesMouseMove, false);
+    ctrl.handlesMouseMove = false;
+    var evt = document.createEvent("MouseEvents");
+    evt.initMouseEvent("mousemove", true, true, window,
+      0, 0, 0, 0, 0, false, false, false, false, 0, null);
+    ctrl.dispatchEvent(evt);
+
+    // Mouse move events are what causes tooltips to show up. 
+    // Before this fix we would not allow mouse move events to go through
+    // which in turn did not allow tooltips to be displayed.
+    // This test will ensure that all HTML elements handle mouse move events
+    // so that tooltips can be displayed
+    ok(ctrl.handlesMouseMove, "Disabled element need mouse move for tooltips");
+  }
+
+</script>
+</body>
+</html>
--- a/content/html/content/test/test_bug500885.html
+++ b/content/html/content/test/test_bug500885.html
@@ -15,16 +15,19 @@ https://bugzilla.mozilla.org/show_bug.cg
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=500885">Mozilla Bug 500885</a>
 <div>
   <input id="file" type="file" />
 </div>
 <script type="text/javascript">
 
 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+var Cu = Components.utils;
+var Ci = Components.interfaces;
+var Cr = Components.results;
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function MockFilePicker() { };
 MockFilePicker.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIFilePicker]),
   init: function(aParent, aTitle, aMode) { },
   appendFilters: function(aFilterMask) { },
   appendFilter: function(aTitle, aFilter) { },
--- a/content/html/content/test/test_bug592802.html
+++ b/content/html/content/test/test_bug592802.html
@@ -24,16 +24,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 <script type="application/javascript">
 
 /** Test for Bug 592802 **/
 
 SimpleTest.waitForExplicitFinish();
 
 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
+var Cu = Components.utils;
+var Ci = Components.interfaces;
+var Cr = Components.results;
+
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function simpleEnumerator(items)
 {
   this._items = items;
   this._nextIndex = 0;
 }
 
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_bug666200.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=666200
+-->
+<head>
+  <title>Test for Bug 666200</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666200">Mozilla Bug 666200</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 666200 **/
+var sel = document.createElement("select");
+var opt1 = new Option();
+var opt2 = new Option();
+var opt3 = new Option();
+var opt4 = new Option();
+opt1.value = 1;
+opt2.value = 2;
+opt3.value = 3;
+opt4.value = 4;
+sel.add(opt1);
+sel.add(opt2, 0);
+sel.add(opt3, 1000);
+sel.options.add(opt4, opt3);
+is(sel[0], opt2, "1st item should be 2");
+is(sel[1], opt1, "2nd item should be 1");
+is(sel[2], opt4, "3rd item should be 4");
+is(sel[3], opt3, "4th item should be 3");
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/document/src/MediaDocument.cpp
+++ b/content/html/document/src/MediaDocument.cpp
@@ -40,17 +40,16 @@
 #include "nsGkAtoms.h"
 #include "nsRect.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIScrollable.h"
 #include "nsIViewManager.h"
 #include "nsITextToSubURI.h"
 #include "nsIURL.h"
-#include "nsPrintfCString.h"
 #include "nsIContentViewer.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIDocShell.h"
 #include "nsIParser.h" // kCharsetFrom* macro definition
 #include "nsIDocumentCharsetInfo.h" 
 #include "nsNodeInfoManager.h"
 
 namespace mozilla {
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2580,17 +2580,22 @@ nsHTMLDocument::DeferredContentEditableC
       nsCOMPtr<nsIEditor> editor;
       editorDocShell->GetEditor(getter_AddRefs(editor));
       if (editor) {
         nsCOMPtr<nsIDOMRange> range;
         rv = NS_NewRange(getter_AddRefs(range));
         NS_ENSURE_SUCCESS(rv, );
 
         rv = range->SelectNode(node);
-        NS_ENSURE_SUCCESS(rv, );
+        if (NS_FAILED(rv)) {
+          // The node might be detached from the document at this point,
+          // which would cause this call to fail.  In this case, we can
+          // safely ignore the contenteditable count change.
+          return;
+        }
 
         nsCOMPtr<nsIInlineSpellChecker> spellChecker;
         rv = editor->GetInlineSpellChecker(PR_FALSE,
                                            getter_AddRefs(spellChecker));
         NS_ENSURE_SUCCESS(rv, );
 
         if (spellChecker) {
           rv = spellChecker->SpellCheckRange(range);
@@ -2936,17 +2941,17 @@ nsHTMLDocument::EditingStateChanged()
       mEditingState = eOff;
 
       return rv;
     }
   }
 
   if (updateState) {
     nsAutoScriptBlocker scriptBlocker;
-    NotifyEditableStateChange(this, this, !designMode);
+    NotifyEditableStateChange(this, this, designMode);
   }
 
   // Resync the editor's spellcheck state.
   if (spellRecheckAll) {
     nsCOMPtr<nsISelectionController> selcon;
     nsresult rv = editor->GetSelectionController(getter_AddRefs(selcon));
     NS_ENSURE_SUCCESS(rv, rv); 
 
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -177,45 +177,43 @@ nsresult nsOggCodecState::PageIn(ogg_pag
   } while (r != 0);
   if (ogg_stream_check(&mState)) {
     NS_WARNING("Unrecoverable error in ogg_stream_packetout");
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
-PRBool
-nsOggCodecState::PacketOutUntilGranulepos()
-{
+nsresult nsOggCodecState::PacketOutUntilGranulepos(PRBool& aFoundGranulepos) {
   int r;
-  PRBool foundGp = PR_FALSE;
+  aFoundGranulepos = PR_FALSE;
   // Extract packets from the sync state until either no more packets
   // come out, or we get a data packet with non -1 granulepos.
   do {
     ogg_packet packet;
     r = ogg_stream_packetout(&mState, &packet);
     if (r == 1) {
       ogg_packet* clone = Clone(&packet);
       if (IsHeader(&packet)) {
         // Header packets go straight into the packet queue.
         mPackets.Append(clone);
       } else {
         // We buffer data packets until we encounter a granulepos. We'll
         // then use the granulepos to figure out the granulepos of the
         // preceeding packets.
         mUnstamped.AppendElement(clone);
-        foundGp = packet.granulepos != -1;
+        aFoundGranulepos = packet.granulepos > 0;
       }
     }
-  } while (r != 0 && !foundGp);
+  } while (r != 0 && !aFoundGranulepos);
   if (ogg_stream_check(&mState)) {
     NS_WARNING("Unrecoverable error in ogg_stream_packetout");
     return NS_ERROR_FAILURE;
   }
-  return foundGp;
+  return NS_OK;
 }
 
 nsTheoraState::nsTheoraState(ogg_page* aBosPage) :
   nsOggCodecState(aBosPage, PR_TRUE),
   mSetup(0),
   mCtx(0),
   mPixelAspectRatio(0)
 {
@@ -372,17 +370,20 @@ nsresult
 nsTheoraState::PageIn(ogg_page* aPage)
 {
   if (!mActive)
     return NS_OK;
   NS_ASSERTION(static_cast<PRUint32>(ogg_page_serialno(aPage)) == mSerial,
                "Page must be for this stream!");
   if (ogg_stream_pagein(&mState, aPage) == -1)
     return NS_ERROR_FAILURE;
-  PRBool foundGp = PacketOutUntilGranulepos();
+  PRBool foundGp;
+  nsresult res = PacketOutUntilGranulepos(foundGp);
+  if (NS_FAILED(res))
+    return res;
   if (foundGp && mDoneReadingHeaders) {
     // We've found a packet with a granulepos, and we've loaded our metadata
     // and initialized our decoder. Determine granulepos of buffered packets.
     ReconstructTheoraGranulepos();
     for (PRUint32 i = 0; i < mUnstamped.Length(); ++i) {
       ogg_packet* packet = mUnstamped[i];
 #ifdef DEBUG
       NS_ASSERTION(!IsHeader(packet), "Don't try to recover header packet gp");
@@ -617,17 +618,20 @@ nsresult
 nsVorbisState::PageIn(ogg_page* aPage)
 {
   if (!mActive)
     return NS_OK;
   NS_ASSERTION(static_cast<PRUint32>(ogg_page_serialno(aPage)) == mSerial,
                "Page must be for this stream!");
   if (ogg_stream_pagein(&mState, aPage) == -1)
     return NS_ERROR_FAILURE;
-  PRBool foundGp = PacketOutUntilGranulepos();
+  PRBool foundGp;
+  nsresult res = PacketOutUntilGranulepos(foundGp);
+  if (NS_FAILED(res))
+    return res;
   if (foundGp && mDoneReadingHeaders) {
     // We've found a packet with a granulepos, and we've loaded our metadata
     // and initialized our decoder. Determine granulepos of buffered packets.
     ReconstructVorbisGranulepos();
     for (PRUint32 i = 0; i < mUnstamped.Length(); ++i) {
       ogg_packet* packet = mUnstamped[i];
       AssertHasRecordedPacketSamples(packet);
       NS_ASSERTION(!IsHeader(packet), "Don't try to recover header packet gp");
--- a/content/media/ogg/nsOggCodecState.h
+++ b/content/media/ogg/nsOggCodecState.h
@@ -197,17 +197,17 @@ protected:
 
   // Extracts packets out of mState until a data packet with a non -1
   // granulepos is encountered, or no more packets are readable. Header
   // packets are pushed into the packet queue immediately, and data packets
   // are buffered in mUnstamped. Once a non -1 granulepos packet is read
   // the granulepos of the packets in mUnstamped can be inferred, and they
   // can be pushed over to mPackets. Used by PageIn() implementations in
   // subclasses.
-  PRBool PacketOutUntilGranulepos();
+  nsresult PacketOutUntilGranulepos(PRBool& aFoundGranulepos);
 
   // Temporary buffer in which to store packets while we're reading packets
   // in order to capture granulepos.
   nsTArray<ogg_packet*> mUnstamped;
 };
 
 class nsVorbisState : public nsOggCodecState {
 public:
--- a/content/media/raw/nsRawReader.cpp
+++ b/content/media/raw/nsRawReader.cpp
@@ -65,19 +65,18 @@ nsresult nsRawReader::Init(nsBuiltinDeco
 nsresult nsRawReader::ResetDecode()
 {
   mCurrentFrame = 0;
   return nsBuiltinDecoderReader::ResetDecode();
 }
 
 nsresult nsRawReader::ReadMetadata(nsVideoInfo* aInfo)
 {
-  NS_ASSERTION(mDecoder->OnStateMachineThread(),
-               "Should be on state machine thread.");
-  mozilla::ReentrantMonitorAutoEnter autoEnter(mReentrantMonitor);
+  NS_ASSERTION(mDecoder->OnDecodeThread(),
+               "Should be on decode thread.");
 
   nsMediaStream* stream = mDecoder->GetCurrentStream();
   NS_ASSERTION(stream, "Decoder has no media stream");
 
   if (!ReadFromStream(stream, reinterpret_cast<PRUint8*>(&mMetadata),
                       sizeof(mMetadata)))
     return NS_ERROR_FAILURE;
 
@@ -128,17 +127,16 @@ nsresult nsRawReader::ReadMetadata(nsVid
     return NS_ERROR_FAILURE;
 
   mFrameSize = mMetadata.frameWidth * mMetadata.frameHeight *
     (mMetadata.lumaChannelBpp + mMetadata.chromaChannelBpp) / 8.0 +
     sizeof(nsRawPacketHeader);
 
   PRInt64 length = stream->GetLength();
   if (length != -1) {
-    mozilla::ReentrantMonitorAutoExit autoExitMonitor(mReentrantMonitor);
     mozilla::ReentrantMonitorAutoEnter autoMonitor(mDecoder->GetReentrantMonitor());
     mDecoder->GetStateMachine()->SetDuration(USECS_PER_S *
                                            (length - sizeof(nsRawVideoHeader)) /
                                            (mFrameSize * mFrameRate));
   }
 
   *aInfo = mInfo;
 
@@ -173,19 +171,18 @@ PRBool nsRawReader::ReadFromStream(nsMed
   }
 
   return PR_TRUE;
 }
 
 PRBool nsRawReader::DecodeVideoFrame(PRBool &aKeyframeSkip,
                                      PRInt64 aTimeThreshold)
 {
-  mozilla::ReentrantMonitorAutoEnter autoEnter(mReentrantMonitor);
-  NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
-               "Should be on state machine thread or decode thread.");
+  NS_ASSERTION(mDecoder->OnDecodeThread(),
+               "Should be on decode thread.");
 
   // Record number of frames decoded and parsed. Automatically update the
   // stats counters using the AutoNotifyDecoded stack-based class.
   PRUint32 parsed = 0, decoded = 0;
   nsMediaDecoder::AutoNotifyDecoded autoNotify(mDecoder, parsed, decoded);
 
   if (!mFrameSize)
     return PR_FALSE; // Metadata read failed.  We should refuse to play.
@@ -256,19 +253,18 @@ PRBool nsRawReader::DecodeVideoFrame(PRB
   decoded++;
   currentFrameTime += USECS_PER_S / mFrameRate;
 
   return PR_TRUE;
 }
 
 nsresult nsRawReader::Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime)
 {
-  mozilla::ReentrantMonitorAutoEnter autoEnter(mReentrantMonitor);
-  NS_ASSERTION(mDecoder->OnStateMachineThread(),
-               "Should be on state machine thread.");
+  NS_ASSERTION(mDecoder->OnDecodeThread(),
+               "Should be on decode thread.");
 
   nsMediaStream *stream = mDecoder->GetCurrentStream();
   NS_ASSERTION(stream, "Decoder has no media stream");
 
   PRUint32 frame = mCurrentFrame;
   if (aTime >= UINT_MAX)
     return NS_ERROR_FAILURE;
   mCurrentFrame = aTime * mFrameRate / USECS_PER_S;
@@ -287,17 +283,16 @@ nsresult nsRawReader::Seek(PRInt64 aTime
   while(mVideoQueue.GetSize() == 0) {
     PRBool keyframeSkip = PR_FALSE;
     if (!DecodeVideoFrame(keyframeSkip, 0)) {
       mCurrentFrame = frame;
       return NS_ERROR_FAILURE;
     }
 
     {
-      mozilla::ReentrantMonitorAutoExit autoMonitorExit(mReentrantMonitor);
       mozilla::ReentrantMonitorAutoEnter autoMonitor(mDecoder->GetReentrantMonitor());
       if (mDecoder->GetDecodeState() ==
           nsBuiltinDecoderStateMachine::DECODER_STATE_SHUTDOWN) {
         mCurrentFrame = frame;
         return NS_ERROR_FAILURE;
       }
     }
 
rename from content/smil/crashtests/665335-1.svg
rename to content/smil/crashtests/665334-1.svg
--- a/content/smil/crashtests/crashtests.list
+++ b/content/smil/crashtests/crashtests.list
@@ -29,9 +29,9 @@ load 594653-1.svg
 load 596796-1.svg
 load 605345-1.svg
 load 606101-1.svg
 load 608549-1.svg
 load 608295-1.html
 load 611927-1.svg
 load 615002-1.svg
 load 615872-1.svg
-load 665335-1.svg
+load 665334-1.svg
--- a/content/smil/nsSMILInstanceTime.cpp
+++ b/content/smil/nsSMILInstanceTime.cpp
@@ -33,42 +33,17 @@
  * 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 "nsSMILInstanceTime.h"
 #include "nsSMILInterval.h"
 #include "nsSMILTimeValueSpec.h"
-
-//----------------------------------------------------------------------
-// Helper classes
-
-namespace
-{
-  // Utility class to set a PRPackedBool value to PR_TRUE whilst it is in scope.
-  // Saves us having to remember to clear the flag at every possible return.
-  class AutoBoolSetter
-  {
-  public:
-    AutoBoolSetter(PRPackedBool& aValue)
-    : mValue(aValue)
-    {
-      mValue = PR_TRUE;
-    }
- 
-    ~AutoBoolSetter()
-    {
-      mValue = PR_FALSE;
-    }
-
-  private:
-    PRPackedBool&   mValue;
-  };
-}
+#include "mozilla/AutoRestore.h"
 
 //----------------------------------------------------------------------
 // Implementation
 
 nsSMILInstanceTime::nsSMILInstanceTime(const nsSMILTimeValue& aTime,
                                        nsSMILInstanceTimeSource aSource,
                                        nsSMILTimeValueSpec* aCreator,
                                        nsSMILInterval* aBaseInterval)
@@ -141,17 +116,18 @@ nsSMILInstanceTime::HandleChangedInterva
     // Break the cycle here
     Unlink();
     return;
   }
 
   PRBool objectChanged = mCreator->DependsOnBegin() ? aBeginObjectChanged :
                                                       aEndObjectChanged;
 
-  AutoBoolSetter setVisited(mVisited);
+  mozilla::AutoRestore<PRPackedBool> setVisited(mVisited);
+  mVisited = PR_TRUE;
 
   nsRefPtr<nsSMILInstanceTime> deathGrip(this);
   mCreator->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer, *this,
                                       objectChanged);
 }
 
 void
 nsSMILInstanceTime::HandleDeletedInterval()
@@ -219,17 +195,18 @@ nsSMILInstanceTime::IsDependentOn(const 
   const nsSMILInstanceTime* myBaseTime = GetBaseTime();
   if (!myBaseTime)
     return PR_FALSE;
 
   if (myBaseTime == &aOther)
     return PR_TRUE;
 
   // mVisited is mutable
-  AutoBoolSetter setVisited(const_cast<nsSMILInstanceTime*>(this)->mVisited);
+  mozilla::AutoRestore<PRPackedBool> setVisited(const_cast<nsSMILInstanceTime*>(this)->mVisited);
+  const_cast<nsSMILInstanceTime*>(this)->mVisited = PR_TRUE;
   return myBaseTime->IsDependentOn(aOther);
 }
 
 const nsSMILInstanceTime*
 nsSMILInstanceTime::GetBaseTime() const
 {
   if (!mBaseInterval) {
     return nsnull;
--- a/content/smil/nsSMILMappedAttribute.cpp
+++ b/content/smil/nsSMILMappedAttribute.cpp
@@ -40,16 +40,17 @@
 #include "nsPropertyTable.h"
 #include "nsContentErrors.h" // For NS_PROPTABLE_PROP_OVERWRITTEN
 #include "nsSMILValue.h"
 #include "nsSMILCSSValueType.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIPresShell.h"
 #include "nsCSSProps.h"
+#include "mozilla/dom/Element.h"
 
 // Callback function, for freeing string buffers stored in property table
 static void
 ReleaseStringBufferPropertyValue(void*    aObject,       /* unused */
                                  nsIAtom* aPropertyName, /* unused */
                                  void*    aPropertyValue,
                                  void*    aData          /* unused */)
 {
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -99,16 +99,18 @@
 #include "prprf.h"
 #include "nsNodeUtils.h"
 
 // Nasty hack.  Maybe we could move some of the classinfo utility methods
 // (e.g. WrapNative and ThrowJSException) over to nsContentUtils?
 #include "nsDOMClassInfo.h"
 #include "nsJSUtils.h"
 
+#include "mozilla/dom/Element.h"
+
 // Helper classes
 
 /***********************************************************************/
 //
 // The JS class for XBLBinding
 //
 static void
 XBLFinalize(JSContext *cx, JSObject *obj)
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -69,16 +69,17 @@
 #include "nsXBLProtoImpl.h"
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 
 #include "nsIScriptContext.h"
 
 #include "nsIStyleRuleProcessor.h"
 #include "nsXBLResourceLoader.h"
+#include "mozilla/dom/Element.h"
 
 // Helper Classes =====================================================================
 
 // nsXBLAttributeEntry and helpers.  This class is used to efficiently handle
 // attribute changes in anonymous content.
 
 class nsXBLAttributeEntry {
 public:
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -84,16 +84,17 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptError.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 #include "nsIDOMEventListener.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 #define NS_MAX_XBL_BINDING_RECURSION 20
 
 static PRBool IsChromeOrResourceURI(nsIURI* aURI)
 {
   PRBool isChrome = PR_FALSE;
--- a/content/xbl/src/nsXBLWindowKeyHandler.cpp
+++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp
@@ -64,16 +64,17 @@
 #include "nsPIWindowRoot.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocShell.h"
 #include "nsIPresShell.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsISelectionController.h"
 #include "nsGUIEvent.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 static nsINativeKeyBindings *sNativeEditorBindings = nsnull;
 
 class nsXBLSpecialDocInfo
 {
 public:
--- a/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp
+++ b/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp
@@ -49,16 +49,17 @@
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsTextFragment.h"
 #include "txXMLUtils.h"
 #include "txLog.h"
 #include "nsUnicharUtils.h"
 #include "nsAttrName.h"
 #include "nsTArray.h"
+#include "mozilla/dom/Element.h"
 
 const PRUint32 kUnknownIndex = PRUint32(-1);
 
 txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
     : mPosition(aOther.mPosition),
       mCurrentIndex(aOther.mCurrentIndex)
 {
 }
--- 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
@@ -66,16 +66,17 @@
 #include "nsServiceManagerUtils.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsLayoutUtils.h"
 #include "nsFrameManager.h"
 #include "nsHTMLReflowState.h"
 #include "nsIObjectLoadingContent.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/Element.h"
 
 // for event firing in context menus
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIViewManager.h"
 #include "nsDOMError.h"
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -650,21 +650,16 @@ protected:
      */
     nsresult DoneWalking();
 
     /**
      * Report that an overlay failed to load
      * @param aURI the URI of the overlay that failed to load
      */
     void ReportMissingOverlay(nsIURI* aURI);
-    
-#if defined(DEBUG_waterson) || defined(DEBUG_hyatt)
-    // timing
-    nsTime mLoadStart;
-#endif
 
     class CachedChromeStreamListener : public nsIStreamListener {
     protected:
         nsXULDocument* mDocument;
         PRPackedBool   mProtoLoaded;
 
         virtual ~CachedChromeStreamListener();
 
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -452,31 +452,31 @@ nsXULPrototypeCache::WritePrototype(nsXU
     FinishOutputStream(protoURI);
     return NS_FAILED(rv) ? rv : rv2;
 }
 
 nsresult
 nsXULPrototypeCache::GetInputStream(nsIURI* uri, nsIObjectInputStream** stream) 
 {
     nsCAutoString spec(kXULCachePrefix);
-    nsresult rv = NS_PathifyURI(uri, spec);
+    nsresult rv = PathifyURI(uri, spec);
     if (NS_FAILED(rv)) 
         return NS_ERROR_NOT_AVAILABLE;
     
     nsAutoArrayPtr<char> buf;
     PRUint32 len;
     nsCOMPtr<nsIObjectInputStream> ois;
     if (!gStartupCache)
         return NS_ERROR_NOT_AVAILABLE;
     
     rv = gStartupCache->GetBuffer(spec.get(), getter_Transfers(buf), &len);
     if (NS_FAILED(rv)) 
         return NS_ERROR_NOT_AVAILABLE;
 
-    rv = NS_NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(ois));
+    rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(ois));
     NS_ENSURE_SUCCESS(rv, rv);
     buf.forget();
 
     mInputStreamTable.Put(uri, ois);
     
     NS_ADDREF(*stream = ois);
     return NS_OK;
 }
@@ -496,19 +496,19 @@ nsXULPrototypeCache::GetOutputStream(nsI
     PRBool found = mOutputStreamTable.Get(uri, getter_AddRefs(storageStream));
     if (found) {
         objectOutput = do_CreateInstance("mozilla.org/binaryoutputstream;1");
         if (!objectOutput) return NS_ERROR_OUT_OF_MEMORY;
         nsCOMPtr<nsIOutputStream> outputStream
             = do_QueryInterface(storageStream);
         objectOutput->SetOutputStream(outputStream);
     } else {
-        rv = NS_NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput), 
-                                                    getter_AddRefs(storageStream),
-                                                    false);
+        rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput), 
+                                                 getter_AddRefs(storageStream),
+                                                 false);
         NS_ENSURE_SUCCESS(rv, rv);
         mOutputStreamTable.Put(uri, storageStream);
     }
     NS_ADDREF(*stream = objectOutput);
     return NS_OK;
 }
 
 nsresult
@@ -523,22 +523,22 @@ nsXULPrototypeCache::FinishOutputStream(
     if (!found)
         return NS_ERROR_UNEXPECTED;
     nsCOMPtr<nsIOutputStream> outputStream
         = do_QueryInterface(storageStream);
     outputStream->Close();
     
     nsAutoArrayPtr<char> buf;
     PRUint32 len;
-    rv = NS_NewBufferFromStorageStream(storageStream, getter_Transfers(buf), 
-                                       &len);
+    rv = NewBufferFromStorageStream(storageStream, getter_Transfers(buf), 
+                                    &len);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCAutoString spec(kXULCachePrefix);
-    rv = NS_PathifyURI(uri, spec);
+    rv = PathifyURI(uri, spec);
     if (NS_FAILED(rv))
         return NS_ERROR_NOT_AVAILABLE;
     rv = gStartupCache->PutBuffer(spec.get(), buf, len);
     if (NS_SUCCEEDED(rv))
         mOutputStreamTable.Remove(uri);
     
     return rv;
 }
@@ -548,17 +548,17 @@ nsXULPrototypeCache::FinishOutputStream(
 nsresult
 nsXULPrototypeCache::HasData(nsIURI* uri, PRBool* exists)
 {
     if (mOutputStreamTable.Get(uri, nsnull)) {
         *exists = PR_TRUE;
         return NS_OK;
     }
     nsCAutoString spec(kXULCachePrefix);
-    nsresult rv = NS_PathifyURI(uri, spec);
+    nsresult rv = PathifyURI(uri, spec);
     if (NS_FAILED(rv)) {
         *exists = PR_FALSE;
         return NS_OK;
     }
     nsAutoArrayPtr<char> buf;
     PRUint32 len;
     if (gStartupCache)
         rv = gStartupCache->GetBuffer(spec.get(), getter_Transfers(buf), 
@@ -663,17 +663,17 @@ nsXULPrototypeCache::BeginCaching(nsIURI
     
     nsAutoArrayPtr<char> buf;
     PRUint32 len, amtRead;
     nsCOMPtr<nsIObjectInputStream> objectInput;
 
     rv = startupCache->GetBuffer(kXULCacheInfoKey, getter_Transfers(buf), 
                                  &len);
     if (NS_SUCCEEDED(rv))
-        rv = NS_NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(objectInput));
+        rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(objectInput));
     
     if (NS_SUCCEEDED(rv)) {
         buf.forget();
         rv = objectInput->ReadCString(fileLocale);
         rv |= objectInput->ReadCString(fileChromePath);
         if (NS_FAILED(rv) ||
             (!fileChromePath.Equals(chromePath) ||
              !fileLocale.Equals(locale))) {
@@ -687,19 +687,19 @@ nsXULPrototypeCache::BeginCaching(nsIURI
         // NS_ERROR_NOT_AVAILABLE is normal, usually if there's no cachefile.
         return rv;
 
     if (NS_FAILED(rv)) {
         // Either the cache entry was invalid or it didn't exist, so write it now.
         nsCOMPtr<nsIObjectOutputStream> objectOutput;
         nsCOMPtr<nsIInputStream> inputStream;
         nsCOMPtr<nsIStorageStream> storageStream;
-        rv = NS_NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput),
-                                                    getter_AddRefs(storageStream),
-                                                    false);
+        rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput),
+                                                 getter_AddRefs(storageStream),
+                                                 false);
         if (NS_SUCCEEDED(rv)) {
             rv = objectOutput->WriteStringZ(locale.get());
             rv |= objectOutput->WriteStringZ(chromePath.get());
             rv |= objectOutput->Close();
             rv |= storageStream->NewInputStream(0, getter_AddRefs(inputStream));
         }
         if (NS_SUCCEEDED(rv))
             rv = inputStream->Available(&len);
--- a/content/xul/templates/src/nsContentTestNode.cpp
+++ b/content/xul/templates/src/nsContentTestNode.cpp
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsContentTestNode.h"
 #include "nsIRDFResource.h"
 #include "nsIAtom.h"
 #include "nsIDOMElement.h"
 #include "nsXULContentUtils.h"
-#include "nsPrintfCString.h"
 #include "nsIXULTemplateResult.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsXULTemplateQueryProcessorRDF.h"
 
 #include "prlog.h"
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gXULTemplateLog;
 #endif
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -105,16 +105,17 @@
 #include "nsIOfflineCacheUpdate.h"
 #include "nsITimedChannel.h"
 #include "nsCPrefetchService.h"
 #include "nsJSON.h"
 #include "IHistory.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/AutoRestore.h"
 
 // we want to explore making the document own the load group
 // so we can associate the document URI with the load group.
 // until this point, we have an evil hack:
 #include "nsIHttpChannelInternal.h"  
 
 
 // Local Includes
@@ -10872,35 +10873,16 @@ nsDocShell::GetRootScrollFrame()
 {
     nsCOMPtr<nsIPresShell> shell;
     NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(shell)), nsnull);
     NS_ENSURE_TRUE(shell, nsnull);
 
     return shell->GetRootScrollFrameAsScrollableExternal();
 }
 
-#ifdef DEBUG
-class nsDebugAutoBoolTrueSetter
-{
-public:
-    nsDebugAutoBoolTrueSetter(PRPackedBool *aBool)
-        : mBool(aBool)
-    {
-        *mBool = PR_TRUE;
-    }
-
-    ~nsDebugAutoBoolTrueSetter()
-    {
-        *mBool = PR_FALSE;
-    }
-protected:
-    PRPackedBool *mBool;
-};
-#endif
-
 NS_IMETHODIMP
 nsDocShell::EnsureScriptEnvironment()
 {
     if (mScriptGlobal)
         return NS_OK;
 
     if (mIsBeingDestroyed) {
         return NS_ERROR_NOT_AVAILABLE;
@@ -10910,17 +10892,18 @@ nsDocShell::EnsureScriptEnvironment()
 
 #ifdef DEBUG
     NS_ASSERTION(!mInEnsureScriptEnv,
                  "Infinite loop! Calling EnsureScriptEnvironment() from "
                  "within EnsureScriptEnvironment()!");
 
     // Yeah, this isn't re-entrant safe, but that's ok since if we
     // re-enter this method, we'll infinitely loop...
-    nsDebugAutoBoolTrueSetter boolSetter(&mInEnsureScriptEnv);
+    AutoRestore<PRPackedBool> boolSetter(mInEnsureScriptEnv);
+    mInEnsureScriptEnv = PR_TRUE;
 #endif
 
     nsCOMPtr<nsIDOMScriptObjectFactory> factory =
         do_GetService(kDOMScriptObjectFactoryCID);
     NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
     NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE);
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -41,19 +41,19 @@
 #define nsDOMNavigationTiming_h___
 
 #include "nsIDOMPerformanceTiming.h"
 #include "nsIDOMPerformanceNavigation.h"
 #include "nscore.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "TimeStamp.h"
+#include "nsIURI.h"
 
 class nsDOMNavigationTimingClock;
-class nsIURI;
 class nsIDocument;
 
 class nsDOMNavigationTiming
 {
 public:
   nsDOMNavigationTiming();
 
   NS_INLINE_DECL_REFCOUNTING(nsDOMNavigationTiming)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -88,17 +88,16 @@
 #include "xpcpublic.h"
 
 #include "jsdbgapi.h"           // for JS_ClearWatchPointsForObject
 #include "jswrapper.h"
 #include "jsxdrapi.h"
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
-#include "nsITimelineService.h"
 #include "nsDOMScriptObjectHolder.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
@@ -2103,18 +2102,16 @@ nsresult
 nsJSContext::Deserialize(nsIObjectInputStream* aStream,
                          nsScriptObjectHolder &aResult)
 {
     JSObject *result = nsnull;
     nsresult rv;
 
     NS_TIME_FUNCTION_MIN(1.0);
 
-    NS_TIMELINE_MARK_FUNCTION("js script deserialize");
-
     PRUint32 size;
     rv = aStream->Read32(&size);
     if (NS_FAILED(rv)) return rv;
 
     char* data;
     rv = aStream->ReadBytes(size, &data);
     if (NS_FAILED(rv)) return rv;
 
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -52,16 +52,17 @@
 #include "nsIScriptContext.h"
 #include "nsIScriptObjectOwner.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIServiceManager.h"
 #include "nsIXPConnect.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
+#include "nsPIDOMWindow.h"
 
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
 
 JSBool
 nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
                               PRUint32* aLineno)
 {
   // Get the current filename and line number
--- a/dom/interfaces/html/nsIDOMHTMLSelectElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLSelectElement.idl
@@ -48,34 +48,38 @@
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
 interface nsIDOMValidityState;
 
-[scriptable, uuid(5aeb2480-cb21-4483-b9b3-0c914502eb81)]
+[scriptable, uuid(069bc0d8-d16d-406a-8555-2f84384c9b3b)]
 interface nsIDOMHTMLSelectElement : nsIDOMHTMLElement
 {
            attribute boolean                     autofocus;
            attribute boolean                     disabled;
   readonly attribute nsIDOMHTMLFormElement       form;
            attribute boolean                     multiple;
            attribute DOMString                   name;
            attribute long                        size;
 
   readonly attribute DOMString                   type;
 
   readonly attribute nsIDOMHTMLOptionsCollection options;
            attribute unsigned long               length;
   nsIDOMNode                item(in unsigned long index);
   nsIDOMNode                namedItem(in DOMString name);
+  // This add method implementation means the following
+  // since IDL doesn't support overfload.
+  //   void add(in nsIDOMHTMLElement, [optional] in nsIDOMHTMLElement)
+  //   void add(in nsIDOMHTMLElement, in long)
   void                      add(in nsIDOMHTMLElement element, 
-                                [optional] in nsIDOMHTMLElement before)
+                                [optional] in nsIVariant before)
                                                      raises(DOMException);   
   void                      remove(in long index);
 
            attribute long                  selectedIndex;
            attribute DOMString             value;
 
            attribute long                  tabIndex;
 
--- a/dom/interfaces/html/nsIDOMNSHTMLOptionCollectn.idl
+++ b/dom/interfaces/html/nsIDOMNSHTMLOptionCollectn.idl
@@ -36,23 +36,29 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "domstubs.idl"
 
 interface nsIDOMHTMLOptionElement;
 interface nsIDOMHTMLSelectElement;
+interface nsIVariant;
 
-[scriptable, uuid(a4f2b279-8096-48ea-8a95-640c5a55b697)]
+[scriptable, uuid(03bd61d6-b851-465a-ab3f-99945f77cfa5)]
 interface nsIDOMNSHTMLOptionCollection : nsISupports
 {
            attribute long             selectedIndex;
 
   [noscript] void           setOption(in long index,
                                       in nsIDOMHTMLOptionElement option);
 
   [noscript] readonly attribute nsIDOMHTMLSelectElement select;
 
-  [optional_argc] void      add(in nsIDOMHTMLOptionElement option,
-                                [optional] in long index);
+  // This add method implementation means the following
+  // since IDL doesn't support overfload.
+  //   void add(in nsIDOMHTMLOptionElement,
+  //            [optional] in nsIDOMHTMLOptionElement)
+  //   void add(in nsIDOMHTMLOptionElement, in long)
+  void                      add(in nsIDOMHTMLOptionElement option,
+                                [optional] in nsIVariant before);
   void                      remove(in long index);
 };
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -99,16 +99,20 @@
 #include "APKOpen.h"
 #endif
 
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #endif
 
+#ifdef ACCESSIBILITY
+#include "nsIAccessibilityService.h"
+#endif
+
 using namespace mozilla::ipc;
 using namespace mozilla::net;
 using namespace mozilla::places;
 using namespace mozilla::docshell;
 
 namespace mozilla {
 namespace dom {
 
@@ -729,16 +733,28 @@ ContentChild::RecvFlushMemory(const nsSt
 {
     nsCOMPtr<nsIObserverService> os =
         mozilla::services::GetObserverService();
     if (os)
         os->NotifyObservers(nsnull, "memory-pressure", reason.get());
   return true;
 }
 
+bool
+ContentChild::RecvActivateA11y()
+{
+#ifdef ACCESSIBILITY
+    // Start accessibility in content process if it's running in chrome
+    // process.
+    nsCOMPtr<nsIAccessibilityService> accService =
+        do_GetService("@mozilla.org/accessibilityService;1");
+#endif
+    return true;
+}
+
 nsString&
 ContentChild::GetIndexedDBPath()
 {
     if (!gIndexedDBPath) {
         gIndexedDBPath = new nsString(); // cleaned up in the destructor
         SendGetIndexedDBDirectory(gIndexedDBPath);
     }
 
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -141,16 +141,18 @@ public:
     virtual bool RecvDeviceMotionChanged(const long int& type,
                                          const double& x, const double& y,
                                          const double& z);
 
     virtual bool RecvScreenSizeChanged(const gfxIntSize &size);
 
     virtual bool RecvFlushMemory(const nsString& reason);
 
+    virtual bool RecvActivateA11y();
+
 #ifdef ANDROID
     gfxIntSize GetScreenSize() { return mScreenSize; }
 #endif
 
     // Get the directory for IndexedDB files. We query the parent for this and
     // cache the value
     nsString &GetIndexedDBPath();
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -57,16 +57,17 @@
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsFrameMessageManager.h"
+#include "nsIPresShell.h"
 #include "nsIAlertsService.h"
 #include "nsToolkitCompsCID.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsConsoleMessage.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "IDBFactory.h"
@@ -174,30 +175,41 @@ void
 ContentParent::Init()
 {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
         obs->AddObserver(this, "xpcom-shutdown", PR_FALSE);
         obs->AddObserver(this, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, PR_FALSE);
         obs->AddObserver(this, "child-memory-reporter-request", PR_FALSE);
         obs->AddObserver(this, "memory-pressure", PR_FALSE);
+#ifdef ACCESSIBILITY
+        obs->AddObserver(this, "a11y-init-or-shutdown", PR_FALSE);
+#endif
     }
     nsCOMPtr<nsIPrefBranch2> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
     if (prefs) {
         prefs->AddObserver("", this, PR_FALSE);
     }
     nsCOMPtr<nsIThreadInternal>
             threadInt(do_QueryInterface(NS_GetCurrentThread()));
     if (threadInt) {
         threadInt->GetObserver(getter_AddRefs(mOldObserver));
         threadInt->SetObserver(this);
     }
     if (obs) {
         obs->NotifyObservers(nsnull, "ipc:content-created", nsnull);
     }
+
+#ifdef ACCESSIBILITY
+    // If accessibility is running in chrome process then start it in content
+    // process.
+    if (nsIPresShell::IsAccessibilityActive()) {
+        SendActivateA11y();
+    }
+#endif
 }
 
 void
 ContentParent::OnChannelConnected(int32 pid)
 {
     ProcessHandle handle;
     if (!base::OpenPrivilegedProcessHandle(pid, &handle)) {
         NS_WARNING("Can't open handle to child process.");
@@ -252,16 +264,19 @@ ContentParent::ActorDestroy(ActorDestroy
     nsCOMPtr<nsIThreadObserver>
         kungFuDeathGrip(static_cast<nsIThreadObserver*>(this));
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     if (obs) {
         obs->RemoveObserver(static_cast<nsIObserver*>(this), "xpcom-shutdown");
         obs->RemoveObserver(static_cast<nsIObserver*>(this), "memory-pressure");
         obs->RemoveObserver(static_cast<nsIObserver*>(this), "child-memory-reporter-request");
         obs->RemoveObserver(static_cast<nsIObserver*>(this), NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC);
+#ifdef ACCESSIBILITY
+        obs->RemoveObserver(static_cast<nsIObserver*>(this), "a11y-init-or-shutdown");
+#endif
     }
 
     // clear the child memory reporters
     InfallibleTArray<MemoryReport> empty;
     SetChildMemoryReporters(empty);
 
     // remove the global remote preferences observers
     nsCOMPtr<nsIPrefBranch2> prefs 
@@ -651,16 +666,24 @@ ContentParent::Observe(nsISupports* aSub
              !strcmp(aTopic, "alertclickcallback") ) {
         if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
                                       nsDependentString(aData)))
             return NS_ERROR_NOT_AVAILABLE;
     }
     else if (!strcmp(aTopic, "child-memory-reporter-request")) {
         SendPMemoryReportRequestConstructor();
     }
+#ifdef ACCESSIBILITY
+    // Make sure accessibility is running in content process when accessibility
+    // gets initiated in chrome process.
+    else if (aData && (*aData == '1') &&
+             !strcmp(aTopic, "a11y-init-or-shutdown")) {
+        SendActivateA11y();
+    }
+#endif
 
     return NS_OK;
 }
 
 PBrowserParent*
 ContentParent::AllocPBrowser(const PRUint32& aChromeFlags)
 {
   TabParent* parent = new TabParent();
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -234,17 +234,17 @@ child:
      * |Show()| and |Move()| take IntSizes rather than Rects because
      * content processes always render to a virtual <0, 0> top-left
      * point.
      */
     Show(nsIntSize size);
 
     LoadURL(nsCString uri);
 
-    Move(nsIntSize size);
+    UpdateDimensions(nsRect rect, nsIntSize size);
 
     /**
      * Sending an activate message moves focus to the child.
      */
     Activate();
 
     Deactivate();
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -124,16 +124,21 @@ child:
     AddPermission(Permission permission);
 
     DeviceMotionChanged(long type, double x, double y, double z);
 
     ScreenSizeChanged(gfxIntSize size);
 
     FlushMemory(nsString reason);
 
+    /**
+     * Start accessibility engine in content process.
+     */
+    ActivateA11y();
+
 parent:
     PNecko();
     PCrashReporter();
     
     PStorage(StorageConstructData data);
 
     PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -117,16 +117,17 @@ public:
                               const InfallibleTArray<nsString>& aStringParams);
 };
 
 
 TabChild::TabChild(PRUint32 aChromeFlags)
   : mRemoteFrame(nsnull)
   , mTabChildGlobal(nsnull)
   , mChromeFlags(aChromeFlags)
+  , mOuterRect(0, 0, 0, 0)
 {
     printf("creating %d!\n", NS_IsMainThread());
 }
 
 nsresult
 TabChild::Init()
 {
   nsCOMPtr<nsIWebBrowser> webBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
@@ -256,19 +257,30 @@ TabChild::SetDimensions(PRUint32 aFlags,
 
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 TabChild::GetDimensions(PRUint32 aFlags, PRInt32* aX,
                              PRInt32* aY, PRInt32* aCx, PRInt32* aCy)
 {
-  NS_NOTREACHED("TabChild::GetDimensions not supported in TabChild");
+  if (aX) {
+    *aX = mOuterRect.x;
+  }
+  if (aY) {
+    *aY = mOuterRect.y;
+  }
+  if (aCx) {
+    *aCx = mOuterRect.width;
+  }
+  if (aCy) {
+    *aCy = mOuterRect.height;
+  }
 
-  return NS_ERROR_NOT_IMPLEMENTED;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChild::SetFocus()
 {
   NS_NOTREACHED("TabChild::SetFocus not supported in TabChild");
 
   return NS_ERROR_NOT_IMPLEMENTED;
@@ -529,26 +541,34 @@ TabChild::RecvShow(const nsIntSize& size
         NS_WARNING("baseWindow doesn't QI to nsIWebBrowserSetup, skipping "
                    "DNS prefetching enable step.");
     }
 
     return InitTabChildGlobal();
 }
 
 bool
-TabChild::RecvMove(const nsIntSize& size)
+TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size)
 {
-    printf("[TabChild] RESIZE to (w,h)= (%ud, %ud)\n", size.width, size.height);
+#ifdef DEBUG
+    printf("[TabChild] Update Dimensions to (x,y,w,h)= (%ud, %ud, %ud, %ud) and move to (w,h)= (%ud, %ud)\n", rect.x, rect.y, rect.width, rect.height, size.width, size.height);
+#endif
+
+    mOuterRect.x = rect.x;
+    mOuterRect.y = rect.y;
+    mOuterRect.width = rect.width;
+    mOuterRect.height = rect.height;
 
     mWidget->Resize(0, 0, size.width, size.height,
                     PR_TRUE);
 
     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mWebNav);
     baseWin->SetPositionAndSize(0, 0, size.width, size.height,
                                 PR_TRUE);
+
     return true;
 }
 
 bool
 TabChild::RecvActivate()
 {
   nsCOMPtr<nsIWebBrowserFocus> browser = do_QueryInterface(mWebNav);
   browser->Activate();
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -173,17 +173,17 @@ public:
     NS_DECL_NSIEMBEDDINGSITEWINDOW2
     NS_DECL_NSIWEBBROWSERCHROMEFOCUS
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSIWINDOWPROVIDER
     NS_DECL_NSIDIALOGCREATOR
 
     virtual bool RecvLoadURL(const nsCString& uri);
     virtual bool RecvShow(const nsIntSize& size);
-    virtual bool RecvMove(const nsIntSize& size);
+    virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size);
     virtual bool RecvActivate();
     virtual bool RecvDeactivate();
     virtual bool RecvMouseEvent(const nsString& aType,
                                 const float&    aX,
                                 const float&    aY,
                                 const PRInt32&  aButton,
                                 const PRInt32&  aClickCount,
                                 const PRInt32&  aModifiers,
@@ -263,16 +263,17 @@ private:
     bool InitWidget(const nsIntSize& size);
     void DestroyWindow();
 
     nsCOMPtr<nsIWebNavigation> mWebNav;
     nsCOMPtr<nsIWidget> mWidget;
     RenderFrameChild* mRemoteFrame;
     nsRefPtr<TabChildGlobal> mTabChildGlobal;
     PRUint32 mChromeFlags;
+    nsIntRect mOuterRect;
 
     DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 inline TabChild*
 GetTabChildFrom(nsIDocShell* aDocShell)
 {
     nsCOMPtr<nsITabChild> tc = do_GetInterface(aDocShell);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -204,19 +204,19 @@ TabParent::LoadURL(nsIURI* aURI)
 void
 TabParent::Show(const nsIntSize& size)
 {
     // sigh
     unused << SendShow(size);
 }
 
 void
-TabParent::Move(const nsIntSize& size)
+TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
 {
-    unused << SendMove(size);
+    unused << SendUpdateDimensions(rect, size);
 }
 
 void
 TabParent::Activate()
 {
     unused << SendActivate();
 }
 
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -121,17 +121,17 @@ public:
     }
 
 
     void LoadURL(nsIURI* aURI);
     // XXX/cjones: it's not clear what we gain by hiding these
     // message-sending functions under a layer of indirection and
     // eating the return values
     void Show(const nsIntSize& size);
-    void Move(const nsIntSize& size);
+    void UpdateDimensions(const nsRect& rect, const nsIntSize& size);
     void Activate();
     void Deactivate();
     void SendMouseEvent(const nsAString& aType, float aX, float aY,
                         PRInt32 aButton, PRInt32 aClickCount,
                         PRInt32 aModifiers, PRBool aIgnoreRootScrollFrame);
     void SendKeyEvent(const nsAString& aType, PRInt32 aKeyCode,
                       PRInt32 aCharCode, PRInt32 aModifiers,
                       PRBool aPreventDefault);
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -54,16 +54,17 @@
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsJSNPRuntime.h"
 #include "nsPluginStreamListenerPeer.h"
 #include "nsSize.h"
 #include "nsNetCID.h"
+#include "nsIContent.h"
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
 
 NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -77,17 +77,16 @@
 #include "nsIProgressEventSink.h"
 #include "nsIDocument.h"
 #include "nsICachingChannel.h"
 #include "nsHashtable.h"
 #include "nsIProxyInfo.h"
 #include "nsPluginLogging.h"
 #include "nsIPrefBranch2.h"
 #include "nsIScriptChannel.h"
-#include "nsPrintfCString.h"
 #include "nsIBlocklistService.h"
 #include "nsVersionComparator.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsPluginStreamListenerPeer.h"
 
 #include "nsEnumeratorUtils.h"
@@ -2268,28 +2267,22 @@ nsresult nsPluginHost::LoadPlugins()
       mozilla::services::GetObserverService();
     if (obsService)
       obsService->NotifyObservers(nsnull, "plugins-list-updated", nsnull);
   }
 
   return NS_OK;
 }
 
-#include "nsITimelineService.h"
-
 // if aCreatePluginList is false we will just scan for plugins
 // and see if any changes have been made to the plugins.
 // This is needed in ReloadPlugins to prevent possible recursive reloads
 nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsChanged)
 {
   Telemetry::AutoTimer<Telemetry::FIND_PLUGINS> telemetry;
-  // let's start timing if we are only really creating the plugin list
-  if (aCreatePluginList) {
-    NS_TIMELINE_START_TIMER("LoadPlugins");
-  }
 
 #ifdef CALL_SAFETY_ON
   // check preferences on whether or not we want to try safe calls to plugins
   NS_INIT_PLUGIN_SAFE_CALLS;
 #endif
 
   NS_ENSURE_ARG_POINTER(aPluginsChanged);
 
@@ -2454,19 +2447,16 @@ nsresult nsPluginHost::FindPlugins(PRBoo
   // update the plugins info cache if changes are detected
   if (*aPluginsChanged)
     WritePluginInfo();
 
   // No more need for cached plugins. Clear it up.
   NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
   NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
 
-  NS_TIMELINE_STOP_TIMER("LoadPlugins");
-  NS_TIMELINE_MARK_TIMER("LoadPlugins");
-
   return NS_OK;
 }
 
 nsresult
 nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
 {
   ReadPluginInfo();
   WritePluginInfo();
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -300,17 +300,16 @@ nsPluginInstanceOwner::nsPluginInstanceO
   mTagText = nsnull;
 #ifdef XP_MACOSX
   memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
 #ifndef NP_NO_QUICKDRAW
   memset(&mQDPluginPortCopy, 0, sizeof(NP_Port));
 #endif
   mInCGPaintLevel = 0;
   mSentInitialTopLevelWindowEvent = PR_FALSE;
-  mIOSurface = nsnull;
   mColorProfile = nsnull;
   mPluginPortChanged = PR_FALSE;
 #endif
   mContentFocused = PR_FALSE;
   mWidgetVisible = PR_TRUE;
   mPluginWindowVisible = PR_FALSE;
   mNumCachedAttrs = 0;
   mNumCachedParams = 0;
@@ -1467,30 +1466,28 @@ void nsPluginInstanceOwner::RenderCoreAn
                                                 int aWidth, int aHeight)
 {
   if (aWidth == 0 || aHeight == 0)
     return;
 
   if (!mIOSurface || 
       (mIOSurface->GetWidth() != (size_t)aWidth || 
        mIOSurface->GetHeight() != (size_t)aHeight)) {
-    delete mIOSurface;
+    mIOSurface = nsnull;
 
     // If the renderer is backed by an IOSurface, resize it as required.
     mIOSurface = nsIOSurface::CreateIOSurface(aWidth, aHeight);
     if (mIOSurface) {
       nsRefPtr<nsIOSurface> attachSurface = nsIOSurface::LookupSurface(
                                               mIOSurface->GetIOSurfaceID());
       if (attachSurface) {
         mCARenderer.AttachIOSurface(attachSurface);
       } else {
         NS_ERROR("IOSurface attachment failed");
-        delete attachSurface;
-        delete mIOSurface;
-        mIOSurface = NULL;
+        mIOSurface = nsnull;
       }
     }
   }
 
   if (!mColorProfile) {
     mColorProfile = CreateSystemColorSpace();
   }
 
@@ -2494,17 +2491,16 @@ nsresult
 nsPluginInstanceOwner::Destroy()
 {
 #ifdef MAC_CARBON_PLUGINS
   // stop the timer explicitly to reduce reference count.
   CancelTimer();
 #endif
 #ifdef XP_MACOSX
   RemoveFromCARefreshTimer(this);
-  delete mIOSurface;
   if (mColorProfile)
     ::CGColorSpaceRelease(mColorProfile);  
 #endif
 
   // unregister context menu listener
   if (mCXMenuListener) {
     mCXMenuListener->Destroy(mContent);
     mCXMenuListener = nsnull;
--- a/dom/src/notification/nsDesktopNotification.h
+++ b/dom/src/notification/nsDesktopNotification.h
@@ -52,16 +52,17 @@
 #include "nsString.h"
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMWindow.h"
 #include "nsThreadUtils.h"
 
 #include "nsDOMEventTargetHelper.h"
 #include "nsIPrivateDOMEvent.h"
+#include "nsIDocument.