Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Thu, 01 Dec 2011 11:35:17 -0800
changeset 108967 c1b222852377b86e59026f904681e11b08101f95
parent 108966 c22780eba624c86dcfcb61224af74aaaba86ee43 (current diff)
parent 81889 c120734d20ba448629dd4fc97e8441c33bcd1e01 (diff)
child 108968 98db3d8d24386392ef24d20027730b8e7f8971d2
push idunknown
push userunknown
push dateunknown
milestone11.0a1
Merge from mozilla-central.
accessible/src/base/Makefile.in
accessible/src/base/nsARIAMap.h
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsAccessibilityService.h
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsAccessible.h
accessible/src/base/nsDocAccessible.cpp
accessible/src/base/nsDocAccessible.h
accessible/src/html/nsHTMLFormControlAccessible.cpp
accessible/src/html/nsHTMLFormControlAccessible.h
accessible/src/html/nsHTMLTableAccessible.cpp
accessible/src/html/nsHyperTextAccessible.cpp
accessible/src/msaa/CAccessibleText.cpp
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/tests/mochitest/events.js
accessible/tests/mochitest/table/test_layoutguess.html
browser/base/content/browser.xul
browser/base/content/highlighter.css
browser/base/content/nsContextMenu.js
browser/components/nsBrowserGlue.js
browser/components/sessionstore/src/nsSessionStore.js
browser/components/sessionstore/test/browser/Makefile.in
browser/components/tabview/groupitems.js
browser/components/tabview/tabitems.js
browser/components/tabview/tabview.js
browser/components/tabview/test/Makefile.in
browser/components/tabview/test/head.js
browser/components/tabview/ui.js
browser/devtools/highlighter/test/browser_inspector_tab_switch.js
browser/devtools/webconsole/HUDService.jsm
browser/devtools/webconsole/test/browser/Makefile.in
browser/devtools/webconsole/test/browser/browser_webconsole_storage_create_display.js
browser/devtools/webconsole/test/browser/browser_webconsole_storage_iteration.js
browser/devtools/webconsole/test/browser/browser_webconsole_storage_record_entry.js
browser/devtools/webconsole/test/browser/browser_webconsole_storage_record_many_entries.js
browser/locales/en-US/chrome/browser/browser.properties
build/mobile/devicemanagerSUT.py
configure.in
content/base/src/nsFrameLoader.cpp
content/base/src/nsFrameLoader.h
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
content/base/src/nsGkAtomList.h
content/base/src/nsInProcessTabChildGlobal.cpp
content/base/src/nsXMLHttpRequest.cpp
content/events/public/nsEventNameList.h
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/html/content/src/nsHTMLMediaElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
content/media/nsBuiltinDecoder.cpp
content/media/nsMediaCache.cpp
content/media/nsMediaCache.h
content/media/nsMediaStream.cpp
content/media/nsMediaStream.h
content/smil/nsSMILParserUtils.cpp
content/svg/content/src/nsSVGPathElement.cpp
dom/Makefile.in
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsMimeTypeArray.cpp
dom/base/nsMimeTypeArray.h
dom/base/nsPluginArray.cpp
dom/base/nsPluginArray.h
dom/ipc/TabChild.cpp
dom/plugins/base/android/ANPBase.h
dom/plugins/base/android/ANPCanvas.cpp
dom/plugins/base/android/ANPTypeface.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/src/storage/nsDOMStorage.cpp
dom/src/storage/nsDOMStorage.h
dom/src/storage/nsDOMStorageDBWrapper.cpp
dom/src/storage/nsDOMStorageDBWrapper.h
dom/src/storage/nsDOMStoragePersistentDB.cpp
dom/src/storage/nsDOMStoragePersistentDB.h
dom/system/NetworkGeolocationProvider.js
editor/libeditor/base/nsEditorEventListener.cpp
gfx/gl/GLContext.h
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/src/nsRegion.cpp
gfx/thebes/gfxPlatformFontList.cpp
js/src/Makefile.in
js/src/configure.in
js/src/jsprvtd.h
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
js/src/vm/RegExpObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/xpconnect/src/dom_quickstubs.qsconf
js/xpconnect/wrappers/AccessCheck.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsPresShell.cpp
layout/forms/nsFileControlFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIFrame.h
layout/generic/nsSubDocumentFrame.cpp
layout/generic/nsSubDocumentFrame.h
layout/generic/nsViewportFrame.cpp
layout/mathml/nsMathMLmactionFrame.cpp
layout/reftests/bugs/reftest.list
layout/style/nsLayoutStylesheetCache.cpp
layout/style/nsLayoutStylesheetCache.h
layout/style/ua.css
layout/tables/nsTableRowGroupFrame.cpp
memory/jemalloc/jemalloc.c
mobile/xul/installer/package-manifest.in
modules/libpref/src/init/all.js
netwerk/base/src/nsURLHelper.cpp
netwerk/protocol/http/nsAHttpConnection.h
netwerk/protocol/http/nsHttpConnection.h
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpPipeline.cpp
netwerk/protocol/http/nsHttpPipeline.h
parser/html/nsHtml5Parser.cpp
parser/html/nsHtml5Parser.h
parser/html/nsHtml5StreamParser.cpp
parser/html/nsHtml5StreamParser.h
parser/html/nsHtml5Tokenizer.cpp
parser/html/nsHtml5TreeBuilder.cpp
parser/html/nsHtml5TreeBuilder.h
parser/html/nsHtml5TreeBuilderCppSupplement.h
parser/html/nsHtml5TreeBuilderHSupplement.h
storage/src/mozStorageStatementWrapper.cpp
testing/testsuite-targets.mk
toolkit/components/places/History.cpp
toolkit/components/places/nsNavHistory.cpp
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/content/widgets/videocontrols.xml
toolkit/crashreporter/google-breakpad/src/common/md5.c
toolkit/empty-file
toolkit/mozapps/webapps/Makefile.in
toolkit/mozapps/webapps/OpenWebapps.idl
toolkit/mozapps/webapps/OpenWebapps.js
toolkit/mozapps/webapps/OpenWebapps.jsm
toolkit/mozapps/webapps/OpenWebapps.manifest
toolkit/themes/gnomestripe/global/icons/webconsole.png
toolkit/themes/gnomestripe/global/webConsole.css
toolkit/themes/gnomestripe/global/webConsole_networkPanel.css
toolkit/themes/pinstripe/global/icons/webconsole.png
toolkit/themes/pinstripe/global/media/videocontrols.css
toolkit/themes/pinstripe/global/webConsole.css
toolkit/themes/pinstripe/global/webConsole_networkPanel.css
toolkit/themes/winstripe/global/icons/webconsole.png
toolkit/themes/winstripe/global/media/videocontrols.css
toolkit/themes/winstripe/global/webConsole.css
toolkit/themes/winstripe/global/webConsole_networkPanel.css
tools/profiler/sps/platform.cc
uriloader/exthandler/nsExternalHelperAppService.cpp
widget/public/nsGUIEvent.h
widget/src/android/AndroidBridge.h
widget/src/cocoa/GfxInfo.mm
widget/src/cocoa/nsAppShell.mm
widget/src/cocoa/nsMenuBarX.mm
widget/src/os2/nsWindow.h
--- a/Makefile.in
+++ b/Makefile.in
@@ -61,17 +61,17 @@ TIERS += base
 tier_base_dirs = \
 	config \
 	build \
 	probes \
 	$(NULL)
 
 ifndef LIBXUL_SDK
 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
-tier_base_dirs += other-licenses/android
+tier_base_dirs += other-licenses/android other-licenses/skia-npapi
 endif
 
 tier_base_dirs += memory
 endif
 
 ifdef COMPILE_ENVIRONMENT
 include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
 endif
--- a/accessible/build/Makefile.in
+++ b/accessible/build/Makefile.in
@@ -52,24 +52,21 @@ MODULE_NAME	= nsAccessibilityModule
 GRE_MODULE	= 1
 LIBXUL_LIBRARY	= 1
 
 CPPSRCS		= nsAccessibilityFactory.cpp
 
 LOCAL_INCLUDES	= -I$(srcdir)/../src
 
 SHARED_LIBRARY_LIBS = \
-	../src/base/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \
-	../src/html/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
-	../src/xpcom/$(LIB_PREFIX)accessibility_xpcom_s.$(LIB_SUFFIX) \
-	../src/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
-	$(NULL)
+  ../src/base/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \
+  ../src/html/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \
+  ../src/xpcom/$(LIB_PREFIX)accessibility_xpcom_s.$(LIB_SUFFIX) \
+  ../src/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \
+  ../src/xforms/$(LIB_PREFIX)accessibility_xforms_s.$(LIB_SUFFIX) \
+  $(NULL)
 
 ifdef MOZ_XUL
 SHARED_LIBRARY_LIBS += ../src/xul/$(LIB_PREFIX)accessibility_xul_s.$(LIB_SUFFIX)
 endif
 
-ifndef DISABLE_XFORMS_HOOKS
-SHARED_LIBRARY_LIBS += ../src/xforms/$(LIB_PREFIX)accessibility_xforms_s.$(LIB_SUFFIX)
-endif
-
 include $(topsrcdir)/config/rules.mk
 
--- a/accessible/public/nsIAccessNode.idl
+++ b/accessible/public/nsIAccessNode.idl
@@ -49,17 +49,17 @@ interface nsIDOMCSSPrimitiveValue;
  * every DOM node can have one nsIAccessNode for each
  * pres shell the DOM node is rendered in.
  * The nsIAccessNode implementations are instantiated lazily.
  * The nsIAccessNode tree for a given dom window
  * has a one to one relationship to the DOM tree.
  * If the DOM node for this access node is "accessible",
  * then a QueryInterface to nsIAccessible will succeed.
  */
-[scriptable, uuid(bbbd5a68-bad2-48c1-ab09-beb6c34f03d9)]
+[scriptable, uuid(08bb2c50-1b30-11e1-bddb-0800200c9a66)]
 interface nsIAccessNode : nsISupports
 {
   /**
    * The DOM node this nsIAccessNode is associated with.
    */
   readonly attribute nsIDOMNode DOMNode;
 
   /**
@@ -95,22 +95,16 @@ interface nsIAccessNode : nsISupports
    *                         the screen or the parent object (for available
    *                         constants refer to nsIAccessibleCoordinateType)
    * @param aX - defines the x coordinate
    * @param aY - defines the y coordinate
   */
   void scrollToPoint(in unsigned long aCoordinateType, in long aX, in long aY);
 
   /**
-   * A unique ID calculated for this DOM node, for the 
-   * purposes of caching and referencing this object.
-   */
-  [noscript] readonly attribute voidPtr uniqueID;
-
-  /**
    * Retrieve the computed style value for this DOM node, if it is a DOM element.
    * Note: the meanings of width, height and other size measurements depend
    * on the version of CSS being used. Therefore, for bounds information, 
    * it is better to use nsIAccessible::accGetBounds.
    * @param pseudoElt The pseudo element to retrieve style for, or NULL
    *                  for general computed style information for this node.
    * @param propertyName Retrieve the computed style value for this property name,
    *                     for example "border-bottom".
--- a/accessible/src/Makefile.in
+++ b/accessible/src/Makefile.in
@@ -58,19 +58,16 @@ endif
 endif
 
 DIRS += $(PLATFORM_DIR)
 
 DIRS += \
   base \
   html \
   xpcom \
+  xforms \
   $(null)
 
 ifdef MOZ_XUL
 DIRS +=   xul
 endif
 
-ifndef DISABLE_XFORMS_HOOKS
-DIRS +=   xforms
-endif
-
 include $(topsrcdir)/config/rules.mk
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -101,19 +101,16 @@ include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../xpcom \
   -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
+  -I$(srcdir)/../xforms \
   $(NULL)
 
-ifndef DISABLE_XFORMS_HOOKS
-LOCAL_INCLUDES += -I$(srcdir)/../xforms
-endif
-
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 LOCAL_INCLUDES += \
   -I$(srcdir)/../atk \
   $(NULL)
 endif
--- a/accessible/src/base/TextUpdater.cpp
+++ b/accessible/src/base/TextUpdater.cpp
@@ -117,23 +117,17 @@ TextUpdater::DoUpdate(const nsAString& a
 
     if (strLen2 > 0) {
       // Fire text change event for insertion.
       nsRefPtr<AccEvent> textInsertEvent =
         new AccTextChangeEvent(mHyperText, mTextOffset, str2, true);
       mDocument->FireDelayedAccessibleEvent(textInsertEvent);
     }
 
-    // Fire value change event.
-    if (mHyperText->Role() == nsIAccessibleRole::ROLE_ENTRY) {
-      nsRefPtr<AccEvent> valueChangeEvent =
-        new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, mHyperText,
-                     eAutoDetect, AccEvent::eRemoveDupes);
-      mDocument->FireDelayedAccessibleEvent(valueChangeEvent);
-    }
+    mDocument->MaybeNotifyOfValueChange(mHyperText);
 
     // Update the text.
     mTextLeaf->SetText(aNewText);
     return;
   }
 
   // Otherwise find the difference between strings and fire events.
   // Note: we can skip initial and final coinciding characters since they don't
@@ -168,22 +162,17 @@ TextUpdater::DoUpdate(const nsAString& a
   ComputeTextChangeEvents(str1, str2, entries, events);
 
   delete [] entries;
 
   // Fire events.
   for (PRInt32 idx = events.Length() - 1; idx >= 0; idx--)
     mDocument->FireDelayedAccessibleEvent(events[idx]);
 
-  if (mHyperText->Role() == nsIAccessibleRole::ROLE_ENTRY) {
-    nsRefPtr<AccEvent> valueChangeEvent =
-      new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, mHyperText,
-                   eAutoDetect, AccEvent::eRemoveDupes);
-    mDocument->FireDelayedAccessibleEvent(valueChangeEvent);
-  }
+  mDocument->MaybeNotifyOfValueChange(mHyperText);
 
   // Update the text.
   mTextLeaf->SetText(aNewText);
 }
 
 void
 TextUpdater::ComputeTextChangeEvents(const nsAString& aStr1,
                                      const nsAString& aStr2,
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -342,11 +342,25 @@ struct nsARIAMap
    */
   static eStateMapEntryID gWAIUnivStateMap[];
   
   /**
    * Map of attribute to attribute characteristics.
    */
   static nsAttributeCharacteristics gWAIUnivAttrMap[];
   static PRUint32 gWAIUnivAttrMapLength;
+
+  /**
+   * Return accessible state from ARIA universal states applied to the given
+   * element.
+   */
+  static PRUint64 UniversalStatesFor(nsIContent* aContent)
+  {
+    PRUint64 state = 0;
+    PRUint32 index = 0;
+    while (nsStateMapEntry::MapToStates(aContent, &state, gWAIUnivStateMap[index]))
+      index++;
+
+    return state;
+  }
 };
 
 #endif
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -144,26 +144,16 @@ nsAccessNode::Init()
 
 void
 nsAccessNode::Shutdown()
 {
   mContent = nsnull;
   mWeakShell = nsnull;
 }
 
-// nsIAccessNode
-NS_IMETHODIMP
-nsAccessNode::GetUniqueID(void **aUniqueID)
-{
-  NS_ENSURE_ARG_POINTER(aUniqueID);
-
-  *aUniqueID = UniqueID();
-  return NS_OK;
-}
-
 nsApplicationAccessible*
 nsAccessNode::GetApplicationAccessible()
 {
   NS_ASSERTION(!nsAccessibilityService::IsShutdown(),
                "Accessibility wasn't initialized!");
 
   if (!gApplicationAccessible) {
     nsApplicationAccessibleWrap::PreCreate();
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -101,20 +101,18 @@
 #include "nsHTMLWin32ObjectAccessible.h"
 #endif
 
 // For embedding plugin accessibles
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "AtkSocketAccessible.h"
 #endif
 
-#ifndef DISABLE_XFORMS_HOOKS
 #include "nsXFormsFormControlsAccessible.h"
 #include "nsXFormsWidgetsAccessible.h"
-#endif
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -282,16 +280,26 @@ nsAccessibilityService::CreateHTMLCanvas
 {
   nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
   nsAccessible* accessible = new nsHTMLCanvasAccessible(aContent, weakShell);
   NS_IF_ADDREF(accessible);
   return accessible;
 }
 
 already_AddRefed<nsAccessible>
+nsAccessibilityService::CreateHTMLFileInputAccessible(nsIContent* aContent,
+                                                      nsIPresShell* aPresShell)
+{
+  nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
+  nsAccessible* accessible = new nsHTMLFileInputAccessible(aContent, weakShell);
+  NS_IF_ADDREF(accessible);
+  return accessible;
+}
+
+already_AddRefed<nsAccessible>
 nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
                                                   nsIPresShell* aPresShell)
 {
   nsAutoString mapElmName;
   aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, mapElmName);
   nsCOMPtr<nsIDOMHTMLMapElement> mapElm;
   if (nsIDocument* document = aContent->GetCurrentDoc()) {
     mapElm = do_QueryInterface(document->FindImageMap(mapElmName));
@@ -1501,17 +1509,16 @@ nsAccessibilityService::CreateAccessible
       break;
 
     case nsIAccessibleProvider::XULToolbarButton:
       accessible = new nsXULToolbarButtonAccessible(aContent, aWeakShell);
       break;
 
 #endif // MOZ_XUL
 
-#ifndef DISABLE_XFORMS_HOOKS
     // XForms elements
     case nsIAccessibleProvider::XFormsContainer:
       accessible = new nsXFormsContainerAccessible(aContent, aWeakShell);
       break;
 
     case nsIAccessibleProvider::XFormsLabel:
       accessible = new nsXFormsLabelAccessible(aContent, aWeakShell);
       break;
@@ -1579,18 +1586,16 @@ nsAccessibilityService::CreateAccessible
     case nsIAccessibleProvider::XFormsCalendarWidget:
       accessible = new nsXFormsCalendarWidgetAccessible(aContent, aWeakShell);
       break;
 
     case nsIAccessibleProvider::XFormsComboboxPopupWidget:
       accessible = new nsXFormsComboboxPopupWidgetAccessible(aContent, aWeakShell);
       break;
 
-#endif
-
     default:
       return nsnull;
   }
 
   NS_IF_ADDREF(accessible);
   return accessible;
 }
 
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -86,16 +86,18 @@ public:
   already_AddRefed<nsAccessible>
     CreateHTMLCanvasAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLCaptionAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLCheckboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLComboboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
+  already_AddRefed<nsAccessible>
+    CreateHTMLFileInputAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLGroupboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
   virtual already_AddRefed<nsAccessible>
     CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -1596,21 +1596,17 @@ nsAccessible::State()
  
   return state;
 }
 
 void
 nsAccessible::ApplyARIAState(PRUint64* aState)
 {
   // Test for universal states first
-  PRUint32 index = 0;
-  while (nsStateMapEntry::MapToStates(mContent, aState,
-                                      nsARIAMap::gWAIUnivStateMap[index])) {
-    ++ index;
-  }
+  *aState |= nsARIAMap::UniversalStatesFor(mContent);
 
   if (mRoleMapEntry) {
 
     // We only force the readonly bit off if we have a real mapping for the aria
     // role. This preserves the ability for screen readers to use readonly
     // (primarily on the document) as the hint for creating a virtual buffer.
     if (mRoleMapEntry->role != nsIAccessibleRole::ROLE_NOTHING)
       *aState &= ~states::READONLY;
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -419,16 +419,18 @@ public:
   inline bool IsCombobox() const { return mFlags & eComboboxAccessible; }
 
   inline bool IsDoc() const { return mFlags & eDocAccessible; }
   nsDocAccessible* AsDoc();
 
   inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
   nsHyperTextAccessible* AsHyperText();
 
+  inline bool IsHTMLFileInput() const { return mFlags & eHTMLFileInputAccessible; }
+
   inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
   nsHTMLLIAccessible* AsHTMLListItem();
 
   inline bool IsListControl() const { return mFlags & eListControlAccessible; }
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
   inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
@@ -640,22 +642,23 @@ protected:
    */
   enum AccessibleTypes {
     eApplicationAccessible = 1 << 2,
     eAutoCompleteAccessible = 1 << 3,
     eAutoCompletePopupAccessible = 1 << 4,
     eComboboxAccessible = 1 << 5,
     eDocAccessible = 1 << 6,
     eHyperTextAccessible = 1 << 7,
-    eHTMLListItemAccessible = 1 << 8,
-    eListControlAccessible = 1 << 9,
-    eMenuButtonAccessible = 1 << 10,
-    eMenuPopupAccessible = 1 << 11,
-    eRootAccessible = 1 << 12,
-    eTextLeafAccessible = 1 << 13
+    eHTMLFileInputAccessible = 1 << 8,
+    eHTMLListItemAccessible = 1 << 9,
+    eListControlAccessible = 1 << 10,
+    eMenuButtonAccessible = 1 << 11,
+    eMenuPopupAccessible = 1 << 12,
+    eRootAccessible = 1 << 13,
+    eTextLeafAccessible = 1 << 14
   };
 
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous helpers
 
   /**
    * Return ARIA role (helper method).
    */
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1846,21 +1846,17 @@ nsDocAccessible::UpdateTree(nsAccessible
       // Don't climb above this document.
       if (ancestor == this)
         break;
 
       ancestor = ancestor->Parent();
     }
   }
 
-  // Fire value change event.
-  if (aContainer->Role() == nsIAccessibleRole::ROLE_ENTRY) {
-    FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
-                               aContainer->GetNode());
-  }
+  MaybeNotifyOfValueChange(aContainer);
 
   // Fire reorder event so the MSAA clients know the children have changed. Also
   // the event is used internally by MSAA layer.
   nsRefPtr<AccEvent> reorderEvent =
     new AccEvent(nsIAccessibleEvent::EVENT_REORDER, aContainer->GetNode(),
                  eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
   if (reorderEvent)
     FireDelayedAccessibleEvent(reorderEvent);
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -200,16 +200,31 @@ public:
   /**
    * Fire accessible event after timeout.
    *
    * @param aEvent  [in] the event to fire
    */
   nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
 
   /**
+   * Fire value change event on the given accessible if applicable.
+   */
+  inline void MaybeNotifyOfValueChange(nsAccessible* aAccessible)
+  {
+    PRUint32 role = aAccessible->Role();
+    if (role == nsIAccessibleRole::ROLE_ENTRY ||
+        role == nsIAccessibleRole::ROLE_COMBOBOX) {
+      nsRefPtr<AccEvent> valueChangeEvent =
+        new AccEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aAccessible,
+                     eAutoDetect, AccEvent::eRemoveDupes);
+      FireDelayedAccessibleEvent(valueChangeEvent);
+    }
+  }
+
+  /**
    * Get/set the anchor jump.
    */
   inline nsAccessible* AnchorJump()
     { return GetAccessibleOrContainer(mAnchorJumpElm); }
 
   inline void SetAnchorJump(nsIContent* aTargetNode)
     { mAnchorJumpElm = aTargetNode; }
 
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -268,16 +268,35 @@ nsHTMLButtonAccessible::DoAction(PRUint8
   if (aIndex != eAction_Click)
     return NS_ERROR_INVALID_ARG;
 
   DoCommand();
   return NS_OK;
 }
 
 PRUint64
+nsHTMLButtonAccessible::State()
+{
+  PRUint64 state = nsHyperTextAccessibleWrap::State();
+  if (state == states::DEFUNCT)
+    return state;
+
+  // Inherit states from input@type="file" suitable for the button. Note,
+  // no special processing for unavailable state since inheritance is supplied
+  // other code paths.
+  if (mParent && mParent->IsHTMLFileInput()) {
+    PRUint64 parentState = mParent->State();
+    state |= parentState & (states::BUSY | states::REQUIRED |
+                            states::HASPOPUP | states::INVALID);
+  }
+
+  return state;
+}
+
+PRUint64
 nsHTMLButtonAccessible::NativeState()
 {
   PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
 
   nsEventStates elmState = mContent->AsElement()->State();
   if (elmState.HasState(NS_EVENT_STATE_DEFAULT))
     state |= states::DEFAULT;
 
@@ -472,17 +491,35 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible:
 }
 
 void
 nsHTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState)
 {
   nsHyperTextAccessibleWrap::ApplyARIAState(aState);
 
   nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete);
+}
 
+PRUint64
+nsHTMLTextFieldAccessible::State()
+{
+  PRUint64 state = nsHyperTextAccessibleWrap::State();
+  if (state & states::DEFUNCT)
+    return state;
+
+  // Inherit states from input@type="file" suitable for the button. Note,
+  // no special processing for unavailable state since inheritance is supplied
+  // by other code paths.
+  if (mParent && mParent->IsHTMLFileInput()) {
+    PRUint64 parentState = mParent->State();
+    state |= parentState & (states::BUSY | states::REQUIRED |
+      states::HASPOPUP | states::INVALID);
+  }
+
+  return state;
 }
 
 PRUint64
 nsHTMLTextFieldAccessible::NativeState()
 {
   PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
 
   // can be focusable, focused, protected. readonly, unavailable, selected
@@ -611,16 +648,71 @@ nsHTMLTextFieldAccessible::ContainerWidg
     mParent : nsnull;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLGroupboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
+nsHTMLFileInputAccessible::
+nsHTMLFileInputAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
+  nsHyperTextAccessibleWrap(aContent, aShell)
+{
+  mFlags |= eHTMLFileInputAccessible;
+}
+
+PRUint32
+nsHTMLFileInputAccessible::NativeRole()
+{
+  // JAWS wants a text container, others don't mind. No specific role in
+  // AT APIs.
+  return nsIAccessibleRole::ROLE_TEXT_CONTAINER;
+}
+
+nsresult
+nsHTMLFileInputAccessible::HandleAccEvent(AccEvent* aEvent)
+{
+  nsresult rv = nsHyperTextAccessibleWrap::HandleAccEvent(aEvent);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Redirect state change events for inherited states to child controls. Note,
+  // unavailable state is not redirected. That's a standard for unavailable
+  // state handling.
+  AccStateChangeEvent* event = downcast_accEvent(aEvent);
+  if (event &&
+      (event->GetState() == states::BUSY ||
+       event->GetState() == states::REQUIRED ||
+       event->GetState() == states::HASPOPUP ||
+       event->GetState() == states::INVALID)) {
+    nsAccessible* input = GetChildAt(0);
+    if (input && input->Role() == nsIAccessibleRole::ROLE_ENTRY) {
+      nsRefPtr<AccStateChangeEvent> childEvent =
+        new AccStateChangeEvent(input, event->GetState(),
+                                event->IsStateEnabled(),
+                                (event->IsFromUserInput() ? eFromUserInput : eNoUserInput));
+      nsEventShell::FireEvent(childEvent);
+    }
+
+    nsAccessible* button = GetChildAt(1);
+    if (button && button->Role() == nsIAccessibleRole::ROLE_PUSHBUTTON) {
+      nsRefPtr<AccStateChangeEvent> childEvent =
+        new AccStateChangeEvent(button, event->GetState(),
+                                event->IsStateEnabled(),
+                                (event->IsFromUserInput() ? eFromUserInput : eNoUserInput));
+      nsEventShell::FireEvent(childEvent);
+    }
+  }
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsHTMLGroupboxAccessible
+////////////////////////////////////////////////////////////////////////////////
+
 nsHTMLGroupboxAccessible::
   nsHTMLGroupboxAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsHyperTextAccessibleWrap(aContent, aShell)
 {
 }
 
 PRUint32
 nsHTMLGroupboxAccessible::NativeRole()
--- a/accessible/src/html/nsHTMLFormControlAccessible.h
+++ b/accessible/src/html/nsHTMLFormControlAccessible.h
@@ -104,16 +104,17 @@ public:
 
   // nsIAccessible
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
 
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
+  virtual PRUint64 State();
   virtual PRUint64 NativeState();
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // Widgets
   virtual bool IsWidget() const;
 };
@@ -166,28 +167,42 @@ public:
 
   // nsIAccessibleEditableText
   NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
 
   // nsAccessible
   virtual void ApplyARIAState(PRUint64* aState);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
+  virtual PRUint64 State();
   virtual PRUint64 NativeState();
 
   // ActionAccessible
   virtual PRUint8 ActionCount();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual nsAccessible* ContainerWidget() const;
 };
 
 
 /**
+ * Accessible for input@type="file" element.
+ */
+class nsHTMLFileInputAccessible : public nsHyperTextAccessibleWrap
+{
+public:
+  nsHTMLFileInputAccessible(nsIContent* aContent, nsIWeakReference* aShell);
+
+  // nsAccessible
+  virtual PRUint32 NativeRole();
+  virtual nsresult HandleAccEvent(AccEvent* aAccEvent);
+};
+
+/**
  * Accessible for HTML fieldset element.
  */
 class nsHTMLGroupboxAccessible : public nsHyperTextAccessibleWrap
 {
 public:
   nsHTMLGroupboxAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
   // nsAccessible
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -1409,16 +1409,19 @@ nsHTMLTableAccessible::IsProbablyForLayo
 
   if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
     // Role attribute is present, but overridden roles have already been dealt with.
     // Only landmarks and other roles that don't override the role from native
     // markup are left to deal with here.
     RETURN_LAYOUT_ANSWER(false, "Has role attribute, weak role, and role is table");
   }
 
+  if (mContent->Tag() != nsGkAtoms::table)
+    RETURN_LAYOUT_ANSWER(true, "table built by CSS display:table style");
+
   // Check if datatable attribute has "0" value.
   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::datatable,
                             NS_LITERAL_STRING("0"), eCaseMatters)) {
     RETURN_LAYOUT_ANSWER(true, "Has datatable = 0 attribute, it's for layout");
   }
 
   // Check for legitimate data table attributes.
   nsAutoString summary;
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -155,22 +155,18 @@ nsHyperTextAccessible::NativeRole()
   if (tag == nsGkAtoms::footer)
     return nsIAccessibleRole::ROLE_FOOTER;
 
   if (tag == nsGkAtoms::aside)
     return nsIAccessibleRole::ROLE_NOTE;
 
   // Treat block frames as paragraphs
   nsIFrame *frame = GetFrame();
-  if (frame && frame->GetType() == nsGkAtoms::blockFrame &&
-      frame->GetContent()->Tag() != nsGkAtoms::input) {
-    // An html:input @type="file" is the only input that is exposed as a
-    // blockframe. It must be exposed as ROLE_TEXT_CONTAINER for JAWS.
+  if (frame && frame->GetType() == nsGkAtoms::blockFrame)
     return nsIAccessibleRole::ROLE_PARAGRAPH;
-  }
 
   return nsIAccessibleRole::ROLE_TEXT_CONTAINER; // In ATK this works
 }
 
 PRUint64
 nsHyperTextAccessible::NativeState()
 {
   PRUint64 states = nsAccessibleWrap::NativeState();
--- a/accessible/src/msaa/CAccessibleText.cpp
+++ b/accessible/src/msaa/CAccessibleText.cpp
@@ -171,16 +171,18 @@ CAccessibleText::get_characterExtents(lo
 
 STDMETHODIMP
 CAccessibleText::get_nSelections(long *aNSelections)
 {
 __try {
   *aNSelections = 0;
 
   nsRefPtr<nsHyperTextAccessible> textAcc(do_QueryObject(this));
+  if (textAcc->IsDefunct())
+    return E_FAIL;
 
   PRInt32 selCount = 0;
   nsresult rv = textAcc->GetSelectionCount(&selCount);
   if (NS_FAILED(rv))
     return GetHRESULT(rv);
 
   *aNSelections = selCount;
   return S_OK;
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -307,32 +307,35 @@ STDMETHODIMP nsAccessibleWrap::get_accNa
 
 
 STDMETHODIMP nsAccessibleWrap::get_accValue(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ BSTR __RPC_FAR *pszValue)
 {
 __try {
   *pszValue = NULL;
-  nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
-  if (xpAccessible) {
-    nsAutoString value;
-    if (NS_FAILED(xpAccessible->GetValue(value)))
-      return E_FAIL;
+
+  nsAccessible* xpAccessible = GetXPAccessibleFor(varChild);
+  if (!xpAccessible || xpAccessible->IsDefunct())
+    return E_FAIL;
+
+  nsAutoString value;
+  if (NS_FAILED(xpAccessible->GetValue(value)))
+    return E_FAIL;
 
-    // see bug 438784: Need to expose URL on doc's value attribute.
-    // For this, reverting part of fix for bug 425693 to make this MSAA method 
-    // behave IAccessible2-style.
-    if (value.IsEmpty())
-      return S_FALSE;
+  // See bug 438784: need to expose URL on doc's value attribute. For this,
+  // reverting part of fix for bug 425693 to make this MSAA method behave
+  // IAccessible2-style.
+  if (value.IsEmpty())
+    return S_FALSE;
 
-    *pszValue = ::SysAllocStringLen(value.get(), value.Length());
-    if (!*pszValue)
-      return E_OUTOFMEMORY;
-  }
+  *pszValue = ::SysAllocStringLen(value.get(), value.Length());
+  if (!*pszValue)
+    return E_OUTOFMEMORY;
+
 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
   return S_OK;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_accDescription(VARIANT varChild,
                                      BSTR __RPC_FAR *pszDescription)
 {
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -1350,19 +1350,20 @@ function stateChangeChecker(aState, aIsE
       var event = aEvent.QueryInterface(nsIAccessibleStateChangeEvent);
     } catch (e) {
       ok(false, "State change event was expected");
     }
 
     if (!event)
       return;
 
-    is(event.state, aState, "Wrong state of the statechange event.");
     is(event.isExtraState(), aIsExtraState,
        "Wrong extra state bit of the statechange event.");
+    isState(event.state, aState, aIsExtraState,
+            "Wrong state of the statechange event.");
     is(event.isEnabled(), aIsEnabled,
       "Wrong state of statechange event state");
 
     var state = aIsEnabled ? (aIsExtraState ? 0 : aState) : 0;
     var extraState = aIsEnabled ? (aIsExtraState ? aState : 0) : 0;
     var unxpdState = aIsEnabled ? 0 : (aIsExtraState ? 0 : aState);
     var unxpdExtraState = aIsEnabled ? 0 : (aIsExtraState ? aState : 0);
     testStates(event.accessible, state, extraState, unxpdState, unxpdExtraState);
--- a/accessible/tests/mochitest/events/test_statechange.html
+++ b/accessible/tests/mochitest/events/test_statechange.html
@@ -65,34 +65,68 @@
         testStates(aNodeOrID, STATE_INVALID);
       };
 
       this.getID = function invalidInput_getID() {
         return prettyName(aNodeOrID) + " became invalid";
       };
     }
 
+    function stateChangeOnFileInput(aID, aAttr, aValue,
+                                    aState, aIsExtraState, aIsEnabled)
+    {
+      this.fileControlNode = getNode(aID);
+      this.fileControl = getAccessible(this.fileControlNode);
+      this.textEntry = this.fileControl.firstChild;
+      this.browseButton = this.fileControl.lastChild;
+
+      this.invoke = function stateChangeOnFileInput_invoke()
+      {
+        this.fileControlNode.setAttribute(aAttr, aValue);
+      }
+
+      this.eventSeq = [
+        new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.fileControl),
+        new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.textEntry),
+        new stateChangeChecker(aState, aIsExtraState, aIsEnabled, this.browseButton)
+      ];
+
+      this.getID = function stateChangeOnFileInput_getID()
+      {
+        return "inherited state change on file input on attribute '" + aAttr + "' change";
+      }
+    }
+
     ////////////////////////////////////////////////////////////////////////////
     // Do tests
 
     var gQueue = null;
 
     // var gA11yEventDumpID = "eventdump"; // debug stuff
+    //gA11yEventDumpToConsole = true; // debug stuff
 
     function doTests()
     {
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_STATE_CHANGE);
 
       // Test delayed editable state change
       var doc = document.getElementById("iframe").contentDocument;
       gQueue.push(new makeEditableDoc(doc));
 
       // invalid state change
       gQueue.push(new invalidInput("email"));
 
+      // file input inherited state changes
+      gQueue.push(new stateChangeOnFileInput("file", "aria-busy", "true",
+                                             STATE_BUSY, false, true));
+      gQueue.push(new stateChangeOnFileInput("file", "aria-required", "true",
+                                             STATE_REQUIRED, false, true));
+      gQueue.push(new stateChangeOnFileInput("file", "aria-invalid", "true",
+                                             STATE_INVALID, false, true));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -103,23 +137,30 @@
      title="Make state change events async">
     Mozilla Bug 564471
   </a><br>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=555728"
      title="Fire a11y event based on HTML5 constraint validation">
     Mozilla Bug 555728
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
+     title="File input control should be propogate states to descendants">
+    Mozilla Bug 699017
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="testContainer">
     <iframe id="iframe"></iframe>
   </div>
 
   <input id="email" type='email'>
 
+  <input id="file" type="file">
+
   <div id="eventdump"></div>
 </body>
 </html>
--- a/accessible/tests/mochitest/events/test_valuechange.html
+++ b/accessible/tests/mochitest/events/test_valuechange.html
@@ -53,32 +53,55 @@
             "Wrong value of " + prettyName(aNodeOrID));
       }
 
       this.getID = function changeValue_getID() {
         return prettyName(aNodeOrID) + " value changed";
       }
     }
 
+    function changeInputValue(aID, aValue)
+    {
+      this.DOMNode = getNode(aID);
+
+      this.invoke = function changeInputValue_invoke()
+      {
+        this.DOMNode.value = aValue;
+      }
+
+      this.check = function changeInputValue_check()
+      {
+        var acc = getAccessible(this.DOMNode);
+        is(acc.value, aValue, "Wrong value for " + prettyName(aID));
+      }
+
+      this.getID = function changeInputValue_getID()
+      {
+        return prettyName(aID) + " value changed";
+      }
+    }
+
     function doTests()
     {
       // Test initial values
       testValue("slider_vn", "5", 5, 0, 1000, 0);
       testValue("slider_vnvt", "plain", 0, 0, 5, 0);
       testValue("slider_vt", "hi", 0, 0, 3, 0);
       testValue("scrollbar", "5", 5, 0, 1000, 0);
 
       // Test value change events
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
 
       gQueue.push(new changeValue("slider_vn", "6", undefined));
       gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
       gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
       gQueue.push(new changeValue("scrollbar", "6", undefined));
 
+      gQueue.push(new changeInputValue("combobox", "hello"));
+
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -89,16 +112,21 @@
      title=" Fire delayed value changed event for aria-valuetext changes">
     Mozilla Bug 478032
   </a>
   <a target="_blank"
     href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289"
     title="We dont expose new aria role 'scrollbar' and property aria-orientation">
    Mozilla Bug 529289
   </a>
+  <a target="_blank"
+    href="https://bugzilla.mozilla.org/show_bug.cgi?id=703202"
+    title="ARIA comboboxes don't fire value change events">
+   Mozilla Bug 703202
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- ARIA sliders -->
@@ -109,10 +137,13 @@
        aria-valuemin="0" aria-valuemax="3">greeting slider</div>
 
   <div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
        aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
 
   <!-- ARIA scrollbar -->
   <div id="scrollbar" role="scrollbar" aria-valuenow="5"
        aria-valuemin="0" aria-valuemax="1000">slider</div>
+
+  <!-- ARIA combobox -->
+  <input id="combobox" role="combobox" aria-autocomplete="inline">
 </body>
 </html>
--- a/accessible/tests/mochitest/states/test_aria.html
+++ b/accessible/tests/mochitest/states/test_aria.html
@@ -92,16 +92,24 @@
       // aria-checked
       testStates("aria_checked_checkbox", STATE_CHECKED);
       testStates("aria_mixed_checkbox", STATE_MIXED);
 
       // test disabled group and all its descendants to see if they are
       // disabled, too. See bug 429285.
       testAriaDisabledTree("group");
 
+      // universal ARIA properties inherited from file input control
+      var fileTextField = getAccessible("fileinput").firstChild;
+      testStates(fileTextField,
+                 STATE_BUSY | STATE_UNAVAILABLE | STATE_REQUIRED | STATE_HASPOPUP | STATE_INVALID);
+      var fileBrowseButton = getAccessible("fileinput").lastChild;
+      testStates(fileBrowseButton,
+                 STATE_BUSY | STATE_UNAVAILABLE | STATE_REQUIRED | STATE_HASPOPUP | STATE_INVALID);
+
       // offscreen test
       testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
 
       //
       // This section tests aria roles on links/anchors for underlying
       // nsHTMLLinkAccessible creation. (see closed bug 494807)
       //
 
@@ -166,16 +174,21 @@
      title="aria-autocomplete not supported on standard form text input controls">
     Mozilla Bug 681674
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=681674"
      title="aria-orientation should be applied to separator and slider roles">
     Mozilla Bug 681674
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
+     title="File input control should be propogate states to descendants">
+    Mozilla Bug 699017
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
   <div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
   <div id="textbox_autocomplete_both" role="textbox" aria-autocomplete="both"></div>
@@ -210,17 +223,25 @@
     <div tabindex="0" role="listbox" aria-activedescendant="item1">
       <div role="option" id="item1">Item 1</div>
       <div role="option" id="item2">Item 2</div>
       <div role="option" id="item3">Item 3</div>
       <div role="option" id="item4">Item 4</div>
     </div>
     <div role="slider" tabindex="0">A slider</div>
   </div>
-  
+
+  <!-- universal ARIA properties should be inherited by text field of file input -->
+  <input type="file" id="fileinput"
+         aria-busy="true"
+         aria-disabled="true"
+         aria-required="true"
+         aria-haspopup="true"
+         aria-invalid="true">
+
   <div id="offscreen_log" role="log" class="offscreen">
     <div id="aria_offscreen_textbox" role="textbox" aria-readonly="true">This text should be offscreen</div>
   </div>
 
   <a id="aria_menuitem_link" role="menuitem" href="foo">menuitem</a>
   <a id="aria_button_link" role="button" href="foo">button</a>
   <a id="aria_checkbox_link" role="checkbox" href="foo">checkbox</a>
 
--- a/accessible/tests/mochitest/states/test_inputs.html
+++ b/accessible/tests/mochitest/states/test_inputs.html
@@ -31,16 +31,22 @@
       testStates(never_required[i], 0, 0, STATE_REQUIRED);
     }
 
     // inherited 'unavailable' state
     testStates("f", STATE_UNAVAILABLE);
     testStates("f_input", STATE_UNAVAILABLE);
     testStates("f_input_disabled", STATE_UNAVAILABLE);
 
+    // inherited from file control
+    var fileTextField = getAccessible("file").firstChild;
+    testStates(fileTextField, STATE_UNAVAILABLE | STATE_REQUIRED);
+    var fileBrowseButton = getAccessible("file").lastChild;
+    testStates(fileBrowseButton, STATE_UNAVAILABLE | STATE_REQUIRED);
+
     /**
      * maxlength doesn't make the element invalid until bug 613016 and bug 613019
      * are fixed. Commenting out related lines and adding a todo to make sure
      * it will be uncommented as soon as possible.
      */
     var todoInput = document.createElement("input");
     todoInput.maxLength = '2';
     todoInput.value = 'foo';
@@ -105,16 +111,21 @@
      title="Expose intrinsic invalid state to accessibility API">
     Mozilla Bug 601205
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=559766"
      title="Add accessibility support for @list on HTML input and for HTML datalist">
     Mozilla Bug 559766
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=699017"
+     title="File input control should be propogate states to descendants">
+    Mozilla Bug 699017
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
 
   <form>
     <input id="input" type="input" required>
@@ -141,16 +152,19 @@
   <input id="image" type="image" required>
 
   <!-- inherited disabled -->
   <fieldset id="f" disabled>
     <input id="f_input">
     <input id="f_input_disabled" disabled>
   </fieldset>
 
+  <!-- inherited from input@type="file" -->
+  <input id="file" type="file" required disabled>
+
   <!-- invalid/valid -->
   <input id="maxlength" maxlength="1">
   <input id="maxlength2" maxlength="100" value="foo">
   <input id="pattern" pattern="bar" value="foo">
   <input id="pattern2" pattern="bar" value="bar">
   <input id="email" type="email" value="foo">
   <input id="email2" type="email" value="foo@bar.com">
   <input id="url" type="url" value="foo">
--- a/accessible/tests/mochitest/table/test_layoutguess.html
+++ b/accessible/tests/mochitest/table/test_layoutguess.html
@@ -18,16 +18,18 @@
     {
       // Attribute we're looking for
       var attr = {
         "layout-guess": "true"
       };
 
       // table with role of grid
       testAbsentAttrs("table1", attr);
+      // table with role of grid and datatable="0"
+      testAbsentAttrs("table1.1", attr);
 
       // table with landmark role
       testAbsentAttrs("table2", attr);
 
       // table with summary
       testAbsentAttrs("table3", attr);
 
       // table with caption
@@ -88,16 +90,22 @@
       // layout table containing nested data table (having data structures)
       testAttrs("table21", attr, true);
       testAttrs("table21.2", attr, true);
       testAttrs("table21.3", attr, true);
       testAttrs("table21.4", attr, true);
       testAttrs("table21.5", attr, true);
       testAttrs("table21.6", attr, true);
 
+      // layout table having datatable="0" attribute and containing data table structure (tfoot element)
+      testAttrs("table22", attr, true);
+
+      // css table with non-table tag
+      testAttrs("table23", attr, true);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
@@ -107,16 +115,21 @@
      title="Don't treat tables that have a landmark role as layout table">
     Mozilla Bug 495388
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=690222"
      title="Data table elements used to determine layout-guess attribute shouldn't be picked from nested tables">
     Mozilla Bug 690222
   </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=693948"
+     title="Expose layout-guess: true object attribute on CSS table accessible">
+    Mozilla Bug 693948
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <!-- Table with role of grid -->
   <table id="table1" role="grid">
@@ -136,16 +149,22 @@
       <td>June 12</td>
     </tr>
     <tr>
       <td>Alex</td>
       <td>Third test</td>
       <td>June 12</td>
     </tr>
   </table>
+   <!-- table with role of grid and datatable="0"-->
+  <table id="table1.1" role="grid" datatable="0">
+    <tr>
+      <td>Cell1</td><td>cell2</td>
+    </tr>
+  </table>
 
   <!-- table with landmark role -->
   <table id="table2" role="main">
     <tr>
       <th>Sender</th>
       <th>Subject</th>
       <th>Date</th>
     </tr>
@@ -406,10 +425,28 @@
         <table>
           <tfoot>
             <tr><td>Cell</td></tr>
           </tfoot>
         </table>
       </td>
     </tr>
   </table>
+
+  <!-- layout table with datatable="0" and tfoot element-->
+  <table id="table22" datatable="0">
+    <tfoot>
+      <tr>
+        <td>Cell1</td><td>cell2</td>
+      </tr>
+    </tfoot>
+  </table>
+
+  <!-- css table with noon-table tag -->
+  <div id="table23" style="display:table;">
+    <div style="display:table-row;">
+      <div style="display:table-cell;">Row 1, column 1</div>
+      <div style="display:table-cell;">Row 1, column 2</div>
+      <div style="display:table-cell;">Row 1, column 3</div>
+    </div>
+  </div>
 </body>
 </html>
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -36,73 +36,124 @@
 #
 # ***** END LICENSE BLOCK *****
 
 # allmakefiles.sh - List of all makefiles.
 #   Appends the list of makefiles to the variable, MAKEFILES.
 #   There is no need to rerun autoconf after adding makefiles.
 #   You only need to run configure.
 
+# Turn on exit on error
+set -o errexit
+
 MAKEFILES=""
 
 # add_makefiles - Shell function to add makefiles to MAKEFILES
 add_makefiles() {
   MAKEFILES="$MAKEFILES $*"
 }
 
 if [ "$srcdir" = "" ]; then
   srcdir=.
 fi
 
-#
 # Common makefiles used by everyone
-#
 add_makefiles "
 Makefile
 build/Makefile
 build/pgo/Makefile
 build/pgo/blueprint/Makefile
 build/pgo/js-input/Makefile
-build/unix/Makefile
-build/win32/Makefile
-build/win32/crashinjectdll/Makefile
 config/Makefile
 config/autoconf.mk
-config/mkdepend/Makefile
 config/nspr/Makefile
 config/doxygen.cfg
 config/expandlibs_config.py
 config/tests/src-simple/Makefile
 probes/Makefile
 extensions/Makefile
 "
 
-if [ "$MOZ_MEMORY" -a "$LIBXUL_SDK" = "" ]; then
+if [ ! "$LIBXUL_SDK" ]; then
   add_makefiles "
-    memory/jemalloc/Makefile
+    memory/Makefile
+    memory/mozalloc/Makefile
+    memory/mozutils/Makefile
+  "
+  if [ "$MOZ_MEMORY" ]; then
+    add_makefiles "
+      memory/jemalloc/Makefile
+    "
+  fi
+  if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
+    add_makefiles "
+      other-licenses/android/Makefile
+    "
+  fi
+fi
+
+if [ "$OS_ARCH" = "WINNT" ]; then
+  add_makefiles "
+    build/win32/Makefile
+    build/win32/crashinjectdll/Makefile
   "
 fi
 
-#
+if [ "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2" ]; then
+  add_makefiles "
+    build/unix/Makefile
+  "
+  if [ "$USE_ELF_HACK" ]; then
+    add_makefiles "
+      build/unix/elfhack/Makefile
+    "
+  fi
+fi
+
+if [ "$COMPILER_DEPEND" = "" -a "$MOZ_NATIVE_MAKEDEPEND" = "" ]; then
+  add_makefiles "
+    config/mkdepend/Makefile
+  "
+fi
+
+if [ "$ENABLE_TESTS" ]; then
+  if [ "$_MSC_VER" -a "$OS_TEST" != "x86_64" ]; then
+    add_makefiles "
+      build/win32/vmwarerecordinghelper/Makefile
+    "
+  fi
+  if [ "$OS_ARCH" != "WINNT" -a "$OS_ARCH" != "OS2" ]; then 
+    add_makefiles "
+      build/unix/test/Makefile
+    "
+  fi
+  if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
+    add_makefiles "
+      build/mobile/sutagent/android/Makefile
+      build/mobile/sutagent/android/fencp/Makefile
+      build/mobile/sutagent/android/ffxcp/Makefile
+      build/mobile/sutagent/android/watcher/Makefile
+    "
+  fi
+fi
+
 # Application-specific makefiles
-#
-if test -f "${srcdir}/${MOZ_BUILD_APP}/makefiles.sh"; then
+if [ -f "${srcdir}/${MOZ_BUILD_APP}/makefiles.sh" ]; then
   . "${srcdir}/${MOZ_BUILD_APP}/makefiles.sh"
 fi
 
-#
 # Extension makefiles
-#
 for extension in $MOZ_EXTENSIONS; do
   if [ -f "${srcdir}/extensions/${extension}/makefiles.sh" ]; then
     . "${srcdir}/extensions/${extension}/makefiles.sh"
   fi
 done
 
-#
 # Toolkit makefiles
-#
-if test -z "$LIBXUL_SDK"; then
+if [ ! "$LIBXUL_SDK" ]; then
   . "${srcdir}/toolkit/toolkit-makefiles.sh"
 fi
 
 # Services makefiles
 . "${srcdir}/services/makefiles.sh"
+
+# Turn off exit on error, since it breaks the rest of configure
+set +o errexit
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -49,17 +49,17 @@
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
 <?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
-<?xml-stylesheet href="chrome://global/skin/webConsole.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/skin/devtools/webconsole.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
 
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/places/placesOverlay.xul"?>
 
 # All DTD information is stored in a separate file so that it can be shared by
 # hiddenWindow.xul.
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -7,20 +7,20 @@
   top: 0;
   left: 0;
 }
 
 #highlighter-veil-container {
   overflow: hidden;
 }
 
-#highlighter-veil-container:not([locked]) > .highlighter-veil,
-#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox,
-#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox > .highlighter-veil,
-#highlighter-veil-container:not([locked]) > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
+#highlighter-veil-container:not([disable-transitions]) > .highlighter-veil,
+#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox,
+#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox > .highlighter-veil,
+#highlighter-veil-container:not([disable-transitions]) > #highlighter-veil-middlebox > #highlighter-veil-transparentbox {
   -moz-transition-property: width, height;
   -moz-transition-duration: 0.1s;
   -moz-transition-timing-function: linear;
 }
 
 #highlighter-veil-bottombox,
 #highlighter-veil-rightbox {
   -moz-box-flex: 1;
@@ -46,28 +46,39 @@
 /*
  * Node Infobar
  */
 
 #highlighter-nodeinfobar-container {
   position: absolute;
 }
 
-#highlighter-nodeinfobar-container:not([locked]) {
+#highlighter-nodeinfobar-container:not([disable-transitions]) {
   -moz-transition-property: top, left;
   -moz-transition-duration: 0.1s;
   -moz-transition-timing-function: linear;
 }
 
 #highlighter-nodeinfobar {
   display: block;
   white-space: nowrap;
   direction: ltr;
 }
 
+#highlighter-nodeinfobar-container[locked] > #highlighter-nodeinfobar {
+  pointer-events: auto;
+}
+
+#highlighter-nodeinfobar-id,
+.highlighter-nodeinfobar-class,
+#highlighter-nodeinfobar-tagname {
+  -moz-user-select: text;
+  cursor: text;
+}
+
 .highlighter-nodeinfobar-arrow {
   display: none;
 }
 
 #highlighter-nodeinfobar-container[position="top"]:not([hide-arrow]) > #highlighter-nodeinfobar-arrow-bottom {
   display: block;
 }
 
@@ -78,19 +89,11 @@
 #highlighter-nodeinfobar-container[disabled] {
   visibility: hidden;
 }
 
 #highlighter-nodeinfobar-id:empty {
   display: none;
 }
 
-#highlighter-nodeinfobar-id::before {
-  content: "#";
-}
-
-.highlighter-nodeinfobar-class::before {
-  content: ".";
-}
-
 #highlighter-nodeinfobar-tagname {
   text-transform: lowercase;
 }
--- a/browser/build.mk
+++ b/browser/build.mk
@@ -50,16 +50,32 @@ tier_app_dirs += $(MOZ_BRANDING_DIRECTOR
 ifdef MOZ_SERVICES_SYNC
 tier_app_dirs += services
 endif
 
 tier_app_dirs += browser
 # Never add other tier_app_dirs after browser. They won't get packaged
 # properly on mac.
 
+################################################
+# Parallel build on Windows with GNU make check
+
+default::
+ifeq (,$(findstring pymake,$(MAKE)))
+ifeq ($(HOST_OS_ARCH),WINNT)
+ifneq (1,$(NUMBER_OF_PROCESSORS))
+	@echo $(if $(findstring -j,$(value MAKEFLAGS)), \
+$(error You are using GNU make to build Firefox with -jN on Windows. \
+This will randomly deadlock. To compile a parallel build on Windows \
+run "python -OO build/pymake/make.py -f client.mk build". \
+See https://developer.mozilla.org/en/pymake for more details.))
+endif
+endif
+endif
+
 installer:
 	@$(MAKE) -C browser/installer installer
 
 package:
 	@$(MAKE) -C browser/installer
 
 package-compare:
 	@$(MAKE) -C browser/installer package-compare
--- a/browser/components/migration/src/ChromeProfileMigrator.js
+++ b/browser/components/migration/src/ChromeProfileMigrator.js
@@ -474,33 +474,33 @@ ChromeProfileMigrator.prototype = {
     return result;
   },
 
   /*
    * Whether we support migration of Chrome
    *
    * @return true if supported
    */
-  sourceExists: function Chrome_sourceExists()
+  get sourceExists()
   {
     let result = this.getMigrateData(null, false);
     return result != 0;
   },
 
   // Although Chrome supports multi-profiles, there is no way
   // to get profile lists.
   sourceHasMultipleProfiles: false,
   sourceProfiles: null,
 
   /*
    * Return home page URL
    *
    * @return  home page URL
    */
-  sourceHomePageURL: function Chrome_sourceHomePageURL()
+  get sourceHomePageURL()
   {
     try  {
       if (this._homepageURL)
         return this._homepageURL;
 
       if (!this._paths.prefs)
         this.getMigrateData(null, false);
 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1527,39 +1527,39 @@ ContentPermissionPrompt.prototype = {
       },
     };
 
     var message;
     var secondaryActions = [];
 
     // Different message/options if it is a local file
     if (requestingURI.schemeIs("file")) {
-      message = browserBundle.formatStringFromName("geolocation.fileWantsToKnow",
+      message = browserBundle.formatStringFromName("geolocation.shareWithFile",
                                                    [requestingURI.path], 1);
     } else {
-      message = browserBundle.formatStringFromName("geolocation.siteWantsToKnow",
+      message = browserBundle.formatStringFromName("geolocation.shareWithSite",
                                                    [requestingURI.host], 1);
 
       // Don't offer to "always/never share" in PB mode
       var inPrivateBrowsing = Cc["@mozilla.org/privatebrowsing;1"].
                               getService(Ci.nsIPrivateBrowsingService).
                               privateBrowsingEnabled;
 
       if (!inPrivateBrowsing) {
         secondaryActions.push({
-          label: browserBundle.GetStringFromName("geolocation.alwaysShare"),
-          accessKey: browserBundle.GetStringFromName("geolocation.alwaysShare.accesskey"),
+          label: browserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
+          accessKey: browserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
           callback: function () {
             Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.ALLOW_ACTION);
             request.allow();
           }
         });
         secondaryActions.push({
-          label: browserBundle.GetStringFromName("geolocation.neverShare"),
-          accessKey: browserBundle.GetStringFromName("geolocation.neverShare.accesskey"),
+          label: browserBundle.GetStringFromName("geolocation.neverShareLocation"),
+          accessKey: browserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
           callback: function () {
             Services.perms.add(requestingURI, "geo", Ci.nsIPermissionManager.DENY_ACTION);
             request.cancel();
           }
         });
       }
     }
 
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -354,17 +354,17 @@ SessionStoreService.prototype = {
           if (lastSessionCrashed) {
             this._recentCrashes = (this._initialState.session &&
                                    this._initialState.session.recentCrashes || 0) + 1;
             
             if (this._needsRestorePage(this._initialState, this._recentCrashes)) {
               // replace the crashed session with a restore-page-only session
               let pageData = {
                 url: "about:sessionrestore",
-                formdata: { "#sessionData": JSON.stringify(this._initialState) }
+                formdata: { "#sessionData": this._initialState }
               };
               this._initialState = { windows: [{ tabs: [{ entries: [pageData] }] }] };
             }
           }
 
           // Load the session start time from the previous state
           this._sessionStartTime = this._initialState.session &&
                                    this._initialState.session.startTime ||
@@ -1641,35 +1641,23 @@ SessionStoreService.prototype = {
     // We might be able to overwrite the existing tabs instead of just adding
     // the previous session's tabs to the end. This will be set if possible.
     let canOverwriteTabs = false;
 
     // Step 1 of processing:
     // Inspect extData for Panorama identifiers. If found, then we want to
     // inspect further. If there is a single group, then we can use this
     // window. If there are multiple groups then we won't use this window.
-    let data = this.getWindowValue(aWindow, "tabview-group");
-    if (data) {
-      data = JSON.parse(data);
-
-      // Multiple keys means multiple groups, which means we don't want to use this window.
-      if (Object.keys(data).length > 1) {
+    let groupsData = this.getWindowValue(aWindow, "tabview-groups");
+    if (groupsData) {
+      groupsData = JSON.parse(groupsData);
+
+      // If there are multiple groups, we don't want to use this window.
+      if (groupsData.totalNumber > 1)
         return [false, false];
-      }
-      else {
-        // If there is only one group, then we want to ensure that its group id
-        // is 0. This is how Panorama forces group merging when new tabs are opened.
-        //XXXzpao This is a hack and the proper fix really belongs in Panorama.
-        let groupKey = Object.keys(data)[0];
-        if (groupKey !== "0") {
-          data["0"] = data[groupKey];
-          delete data[groupKey];
-          this.setWindowValue(aWindow, "tabview-groups", JSON.stringify(data));
-        }
-      }
     }
 
     // Step 2 of processing:
     // If we're still here, then the window is usable. Look at the open tabs in
     // comparison to home pages. If all the tabs are home pages then we'll end
     // up overwriting all of them. Otherwise we'll just close the tabs that
     // match home pages.
     let homePages = aWindow.gHomeButton.getHomePage().split("|");
@@ -2135,20 +2123,27 @@ SessionStoreService.prototype = {
     for (var i = 0; i < aContent.frames.length; i++) {
       if (aData.children && aData.children[i])
         this._updateTextAndScrollDataForFrame(aWindow, aContent.frames[i],
                                               aData.children[i], aUpdateFormData,
                                               aFullData, aIsPinned);
     }
     var isHTTPS = this._getURIFromString((aContent.parent || aContent).
                                          document.location.href).schemeIs("https");
-    if (aFullData || this._checkPrivacyLevel(isHTTPS, aIsPinned) ||
-        aContent.top.document.location.href == "about:sessionrestore") {
+    let isAboutSR = aContent.top.document.location.href == "about:sessionrestore";
+    if (aFullData || this._checkPrivacyLevel(isHTTPS, aIsPinned) || isAboutSR) {
       if (aFullData || aUpdateFormData) {
         let formData = this._collectFormDataForFrame(aContent.document);
+
+        // We want to avoid saving data for about:sessionrestore as a string.
+        // Since it's stored in the form as stringified JSON, stringifying further
+        // causes an explosion of escape characters. cf. bug 467409
+        if (formData && isAboutSR)
+          formData["#sessionData"] = JSON.parse(formData["#sessionData"]);
+
         if (formData)
           aData.formdata = formData;
         else if (aData.formdata)
           delete aData.formdata;
       }
       
       // designMode is undefined e.g. for XUL documents (as about:config)
       if ((aContent.document.designMode || "") == "on") {
@@ -2976,18 +2971,19 @@ SessionStoreService.prototype = {
    * @param aTabData
    *        Array of tab data
    * @param aIdMap
    *        Hash for ensuring unique frame IDs
    */
   restoreHistory:
     function sss_restoreHistory(aWindow, aTabs, aTabData, aIdMap, aDocIdentMap) {
     var _this = this;
-    while (aTabs.length > 0 && (!aTabs[0].linkedBrowser.__SS_tabStillLoading || !aTabs[0].parentNode)) {
-      aTabs.shift(); // this tab got removed before being completely restored
+    // if the tab got removed before being completely restored, then skip it
+    while (aTabs.length > 0 && !(this._canRestoreTabHistory(aTabs[0]))) {
+      aTabs.shift();
       aTabData.shift();
     }
     if (aTabs.length == 0) {
       // At this point we're essentially ready for consumers to read/write data
       // via the sessionstore API so we'll send the SSWindowStateReady event.
       this._setWindowStateReady(aWindow);
       return; // no more tabs to restore
     }
@@ -3374,16 +3370,23 @@ SessionStoreService.prototype = {
 
         let node = key.charAt(0) == "#" ? aDocument.getElementById(key.slice(1)) :
                                           XPathHelper.resolve(aDocument, key);
         if (!node)
           continue;
 
         let eventType;
         let value = aData[key];
+
+        // for about:sessionrestore we saved the field as JSON to avoid nested
+        // instances causing humongous sessionstore.js files. cf. bug 467409
+        if (aURL == "about:sessionrestore" && typeof value == "object") {
+          value = JSON.stringify(value);
+        }
+
         if (typeof value == "string" && node.type != "file") {
           if (node.value == value)
             continue; // don't dispatch an input event for no change
 
           node.value = value;
           eventType = "input";
         }
         else if (typeof value == "boolean") {
@@ -3992,16 +3995,30 @@ SessionStoreService.prototype = {
     // store this tab's data.
     return aTabState.entries.length &&
            !(aTabState.entries.length == 1 &&
              aTabState.entries[0].url == "about:blank" &&
              !aTabState.userTypedValue);
   },
 
   /**
+   * Determine if we can restore history into this tab.
+   * This will be false when a tab has been removed (usually between
+   * restoreHistoryPrecursor && restoreHistory) or if the tab is still marked
+   * as loading.
+   *
+   * @param aTab
+   * @returns boolean
+   */
+  _canRestoreTabHistory: function sss__canRestoreTabHistory(aTab) {
+    return aTab.parentNode && aTab.linkedBrowser &&
+           aTab.linkedBrowser.__SS_tabStillLoading;
+  },
+
+  /**
    * This is going to take a state as provided at startup (via
    * nsISessionStartup.state) and split it into 2 parts. The first part
    * (defaultState) will be a state that should still be restored at startup,
    * while the second part (state) is a state that should be saved for later.
    * defaultState will be comprised of windows with only pinned tabs, extracted
    * from state. It will contain the cookies that go along with the history
    * entries in those tabs. It will also contain window position information.
    *
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -95,16 +95,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_464620_a.html \
 	browser_464620_b.js \
 	browser_464620_b.html \
 	browser_464620_xd.html \
 	browser_465215.js \
 	browser_465223.js \
 	browser_466937.js \
 	browser_466937_sample.html \
+	browser_467409-backslashplosion.js \
 	browser_477657.js \
 	browser_480148.js \
 	browser_480893.js \
 	browser_483330.js \
 	browser_485482.js \
 	browser_485482_sample.html \
 	browser_485563.js \
 	browser_490040.js \
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_467409-backslashplosion.js
@@ -0,0 +1,90 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test Summary:
+// 1.  Open about:sessionrestore via setBrowserState where formdata is a JS object, not a string
+// 1a. Check that #sessionData on the page is readable after JSON.parse (skipped, checking formdata is sufficient)
+// 1b. Check that there are no backslashes in the formdata
+// 1c. Check that formdata (via getBrowserState) doesn't require JSON.parse
+//
+// 2.  Use the current state (currently about:sessionrestore with data) and then open than in a new instance of about:sessionrestore
+// 2a. Check that there are no backslashes in the formdata
+// 2b. Check that formdata (via getBrowserState) doesn't require JSON.parse
+//
+// 3.  [backwards compat] Use a stringified state as formdata when opening about:sessionrestore
+// 3a. Make sure there are nodes in the tree on about:sessionrestore (skipped, checking formdata is sufficient)
+// 3b. Check that there are no backslashes in the formdata
+// 3c. Check that formdata (via getBrowserState) doesn't require JSON.parse
+
+function test() {
+  waitForExplicitFinish();
+
+  let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
+  let crashState = { windows: [{ tabs: [{ entries: [{ url: "about:mozilla" }] }]}]};
+
+  let pagedata = { url: "about:sessionrestore",
+                   formdata: { "#sessionData": crashState } };
+  let state = { windows: [{ tabs: [{ entries: [pagedata] }] }] };
+
+  // test1 calls test2 calls test3 calls finish
+  test1(state);
+
+
+  function test1(aState) {
+    waitForBrowserState(aState, function() {
+      checkState("test1", test2);
+    });
+  }
+
+  function test2(aState) {
+    let pagedata2 = { url: "about:sessionrestore",
+                      formdata: { "#sessionData": aState } };
+    let state2 = { windows: [{ tabs: [{ entries: [pagedata2] }] }] };
+
+    waitForBrowserState(state2, function() {
+      checkState("test2", test3);
+    });
+  }
+
+  function test3(aState) {
+    let pagedata3 = { url: "about:sessionrestore",
+                      formdata: { "#sessionData": JSON.stringify(crashState) } };
+    let state3 = { windows: [{ tabs: [{ entries: [pagedata3] }] }] };
+    waitForBrowserState(state3, function() {
+      // In theory we should do inspection of the treeview on about:sessionrestore,
+      // but we don't actually need to. If we fail tests in checkState then
+      // about:sessionrestore won't be able to turn the form value into a usable page.
+      checkState("test3", function() waitForBrowserState(blankState, finish));
+    });
+  }
+
+  function checkState(testName, callback) {
+    let curState = JSON.parse(ss.getBrowserState());
+    let formdata = curState.windows[0].tabs[0].entries[0].formdata;
+
+    ok(formdata["#sessionData"], testName + ": we have form data for about:sessionrestore");
+
+    let sessionData_raw = JSON.stringify(formdata["#sessionData"]);
+    ok(!/\\/.test(sessionData_raw), testName + ": #sessionData contains no backslashes");
+    info(sessionData_raw);
+
+    let gotError = false;
+    try {
+      JSON.parse(formdata["#sessionData"]);
+    }
+    catch (e) {
+      info(testName + ": got error: " + e);
+      gotError = true;
+    }
+    ok(gotError, testName + ": attempting to JSON.parse form data threw error");
+
+    // Panorama sticks JSON into extData, which we stringify causing the
+    // naive backslash check to fail. extData doesn't matter in the grand
+    // scheme here, so we'll delete the extData so doesn't end up in future states.
+    delete curState.windows[0].extData;
+    delete curState.windows[0].tabs[0].extData;
+    callback(curState);
+  }
+
+}
+
--- a/browser/components/sessionstore/test/browser/browser_590563.js
+++ b/browser/components/sessionstore/test/browser/browser_590563.js
@@ -7,17 +7,17 @@ function test() {
       tabs: [
         { entries: [{ url: "about:robots" }], hidden: true },
         { entries: [{ url: "about:blank" }], hidden: false }
       ]
     }]
   };
   let pageData = {
     url: "about:sessionrestore",
-    formdata: { "#sessionData": "(" + JSON.stringify(oldState) + ")" }
+    formdata: { "#sessionData": oldState }
   };
   let state = { windows: [{ tabs: [{ entries: [pageData] }] }] };
 
   waitForExplicitFinish();
 
   newWindowWithState(state, function (win) {
     registerCleanupFunction(function () win.close());
 
--- a/browser/components/tabview/groupitems.js
+++ b/browser/components/tabview/groupitems.js
@@ -1086,31 +1086,31 @@ GroupItem.prototype = Utils.extend(new I
   //   options - An optional object with settings for this call. See below.
   //
   // Possible options: 
   //   dontArrange - don't rearrange the remaining items
   //   dontClose - don't close the group even if it normally would
   //   immediately - don't animate
   remove: function GroupItem_remove(a, options) {
     try {
-      var $el;
-      var item;
+      let $el;
+      let item;
 
       if (a.isAnItem) {
         item = a;
         $el = iQ(item.container);
       } else {
         $el = iQ(a);
         item = Items.item($el);
       }
 
       if (!options)
         options = {};
 
-      var index = this._children.indexOf(item);
+      let index = this._children.indexOf(item);
       if (index != -1)
         this._children.splice(index, 1);
 
       if (item == this._activeTab || !this._activeTab) {
         if (this._children.length > 0)
           this._activeTab = this._children[0];
         else
           this._activeTab = null;
@@ -1137,17 +1137,19 @@ GroupItem.prototype = Utils.extend(new I
         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;
 
       let closed = options.dontClose ? false : this.closeIfEmpty();
-      if (closed) {
+      if (closed ||
+          (this._children.length == 0 && !gBrowser.selectedTab.pinned &&
+           !item.isDragging)) {
         this._makeLastActiveGroupItemActive();
       } else if (!options.dontArrange) {
         this.arrange({animate: !options.immediately});
         this._unfreezeItemSize({dontArrange: true});
       }
 
       this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
     } catch(e) {
@@ -2226,22 +2228,36 @@ let GroupItems = {
             }
           }
         }
 
         toClose.forEach(function(groupItem) {
           // All remaining children in to-be-closed groups are re-used by
           // session restore. Reconnect them so that they're put into their
           // right groups.
-          groupItem.getChildren().forEach(function (tabItem) {
+          let children = groupItem.getChildren().concat();
+
+          children.forEach(function (tabItem) {
             if (tabItem.parent && tabItem.parent.hidden)
               iQ(tabItem.container).show();
+
+            // sanity check the tab's groupID
+            let tabData = Storage.getTabData(tabItem.tab);
+            let parentGroup = GroupItems.groupItem(tabData.groupID);
+
+            // correct the tab's groupID if necessary
+            if (!parentGroup || -1 < toClose.indexOf(parentGroup)) {
+              tabData.groupID = activeGroupId || Object.keys(groupItemData)[0];
+              Storage.saveTab(tabItem.tab, tabData);
+            }
+
             tabItem._reconnected = false;
             tabItem._reconnect();
           });
+
           groupItem.close({immediately: true});
         });
       }
 
       // set active group item
       if (activeGroupId) {
         let activeGroupItem = this.groupItem(activeGroupId);
         if (activeGroupItem)
--- a/browser/components/tabview/tabitems.js
+++ b/browser/components/tabview/tabitems.js
@@ -255,19 +255,25 @@ TabItem.prototype = Utils.extend(new Ite
   // Loads the tabItems thumbnail.
   loadThumbnail: function TabItem_loadThumbnail(tabData) {
     Utils.assert(tabData, "invalid or missing argument <tabData>");
 
     let self = this;
 
     function TabItem_loadThumbnail_callback(error, imageData) {
       // we could have been unlinked while waiting for the thumbnail to load
-      if (error || !imageData || !self.tab)
+      if (!self.tab)
         return;
 
+      if (error || !imageData) {
+        // paint the canvas to avoid leaving traces when dragging tab over it
+        self.tabCanvas.paint();
+        return;
+      }
+
       self._sendToSubscribers("loadedCachedImageData");
 
       // If we have a cached image, then show it if the loaded URL matches
       // what the cache is from, OR the loaded URL is blank, which means
       // that the page hasn't loaded yet.
       let currentUrl = self.tab.linkedBrowser.currentURI.spec;
       if (tabData.url == currentUrl || currentUrl == "about:blank")
         self.showCachedData(tabData, imageData);
--- a/browser/components/tabview/test/Makefile.in
+++ b/browser/components/tabview/test/Makefile.in
@@ -159,16 +159,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug673729.js \
                  browser_tabview_bug677310.js \
                  browser_tabview_bug679853.js \
                  browser_tabview_bug681599.js \
                  browser_tabview_bug685476.js \
                  browser_tabview_bug685692.js \
                  browser_tabview_bug686654.js \
                  browser_tabview_bug697390.js \
+                 browser_tabview_bug705621.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 \
--- a/browser/components/tabview/test/browser_tabview_apptabs.js
+++ b/browser/components/tabview/test/browser_tabview_apptabs.js
@@ -44,16 +44,20 @@ function onTabViewWindowLoaded() {
   // create a second group and make sure it gets the icon too
   box.offset(box.width + 20, 0);
   let groupItemTwo = new contentWindow.GroupItem([],
       { bounds: box, title: "test2" });
   is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
   is(appTabCount(groupItemTwo), 1,
       "there's an app tab icon in the second group");
 
+  // When the tab was pinned, the last active group with an item got the focus.
+  // Therefore, switching the focus back to group item one.
+  contentWindow.UI.setActive(groupItemOne);
+
   // unpin the tab, make sure the icon goes away and the TabItem comes on
   gBrowser.unpinTab(xulTab);
   is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
   is(appTabCount(groupItemOne), 0, "the icon is gone from group one");
   is(appTabCount(groupItemTwo), 0, "the icon is gone from group 2");
 
   // pin the tab again
   gBrowser.pinTab(xulTab);
--- a/browser/components/tabview/test/browser_tabview_bug595965.js
+++ b/browser/components/tabview/test/browser_tabview_bug595965.js
@@ -99,16 +99,20 @@ function onTabViewShown(win) {
   is(tray.css("-moz-column-count"), 1,
      "$appTabTray column count is 1");
 
   is(appTabCount(groupItem), 1, "there's now one app tab icon");
 
   ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
      "$appTabTray container does not have .appTabTrayContainerTruncated");
 
+  // When the tab was pinned, the last active group with an item got the focus.
+  // Therefore, switching the focus back to group item one.
+  contentWindow.UI.setActive(groupItem);
+
   // unpin the last remaining tab
   gBrowser.unpinTab(xulTabs[0]);
 
   is(parseInt(trayContainer.css("width")), 0,
      "$appTabTray container is not visible");
 
   is(appTabCount(groupItem), 0, "there are no app tab icons");
 
new file mode 100644
--- /dev/null
+++ b/browser/components/tabview/test/browser_tabview_bug705621.js
@@ -0,0 +1,30 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function test() {
+  waitForExplicitFinish();
+
+  newWindowWithTabView(function(win) {
+    registerCleanupFunction(function() {
+      win.close();
+    });
+
+    let cw = win.TabView.getContentWindow();
+
+    let groupItemOne = cw.GroupItems.groupItems[0];
+    is(groupItemOne.getChildren().length, 1, "Group one has 1 tab item");
+
+    let groupItemTwo = createGroupItemWithBlankTabs(win, 300, 300, 40, 1);
+    is(groupItemTwo.getChildren().length, 1, "Group two has 2 tab items");
+
+    whenTabViewIsHidden(function() {
+      executeSoon(function() { 
+        win.gBrowser.removeTab(win.gBrowser.selectedTab);
+        is(cw.UI.getActiveTab(), groupItemOne.getChild(0), "TabItem in Group one is selected");
+        finish();
+      });
+    }, win);
+    groupItemTwo.getChild(0).zoomIn();
+  });
+}
+
--- a/browser/components/tabview/ui.js
+++ b/browser/components/tabview/ui.js
@@ -779,17 +779,17 @@ let UI = {
         // if not closing the last tab
         if (gBrowser.tabs.length > 1) {
           // Don't return to TabView if there are any app tabs
           for (let a = 0; a < gBrowser._numPinnedTabs; a++) {
             if (!gBrowser.tabs[a].closing)
               return;
           }
 
-          var groupItem = GroupItems.getActiveGroupItem();
+          let groupItem = GroupItems.getActiveGroupItem();
 
           // 1) Only go back to the TabView tab when there you close the last
           // tab of a groupItem.
           let closingLastOfGroup = (groupItem && 
               groupItem._children.length == 1 && 
               groupItem._children[0].tab == tab);
 
           // 2) When a blank tab is active while restoring a closed tab the
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -142,19 +142,26 @@ Highlighter.prototype = {
     stack.appendChild(this.highlighterContainer);
 
     // The veil will make the whole page darker except
     // for the region of the selected box.
     this.buildVeil(this.veilContainer);
 
     this.buildInfobar(controlsBox);
 
+    if (!this.IUI.store.getValue(this.winID, "inspecting")) {
+      this.veilContainer.setAttribute("locked", true);
+      this.nodeInfo.container.setAttribute("locked", true);
+    }
+
     this.browser.addEventListener("resize", this, true);
     this.browser.addEventListener("scroll", this, true);
 
+    this.transitionDisabler = null;
+
     this.handleResize();
   },
 
   /**
    * Build the veil:
    *
    * <vbox id="highlighter-veil-container">
    *   <box id="highlighter-veil-topbox" class="highlighter-veil"/>
@@ -482,30 +489,30 @@ Highlighter.prototype = {
    * Update node information (tagName#id.class) 
    */
   updateInfobar: function Highlighter_updateInfobar()
   {
     // Tag name
     this.nodeInfo.tagNameLabel.textContent = this.node.tagName;
 
     // ID
-    this.nodeInfo.idLabel.textContent = this.node.id;
+    this.nodeInfo.idLabel.textContent = this.node.id ? "#" + this.node.id : "";
 
     // Classes
     let classes = this.nodeInfo.classesBox;
     while (classes.hasChildNodes()) {
       classes.removeChild(classes.firstChild);
     }
 
     if (this.node.className) {
       let fragment = this.chromeDoc.createDocumentFragment();
       for (let i = 0; i < this.node.classList.length; i++) {
         let classLabel = this.chromeDoc.createElement("label");
         classLabel.className = "highlighter-nodeinfobar-class plain";
-        classLabel.textContent = this.node.classList[i];
+        classLabel.textContent = "." + this.node.classList[i];
         fragment.appendChild(classLabel);
       }
       classes.appendChild(fragment);
     }
   },
 
   /**
    * Move the Infobar to the right place in the highlighter.
@@ -660,31 +667,53 @@ Highlighter.prototype = {
     switch (aEvent.type) {
       case "click":
         this.handleClick(aEvent);
         break;
       case "mousemove":
         this.handleMouseMove(aEvent);
         break;
       case "resize":
+        this.brieflyDisableTransitions();
         this.handleResize(aEvent);
         break;
       case "dblclick":
       case "mousedown":
       case "mouseup":
         aEvent.stopPropagation();
         aEvent.preventDefault();
         break;
       case "scroll":
+        this.brieflyDisableTransitions();
         this.highlight();
         break;
     }
   },
 
   /**
+   * Disable the CSS transitions for a short time to avoid laggy animations
+   * during scrolling or resizing.
+   */
+  brieflyDisableTransitions: function Highlighter_brieflyDisableTransitions()
+  {
+   if (this.transitionDisabler) {
+     this.IUI.win.clearTimeout(this.transitionDisabler);
+   } else {
+     this.veilContainer.setAttribute("disable-transitions", "true");
+     this.nodeInfo.container.setAttribute("disable-transitions", "true");
+   }
+   this.transitionDisabler =
+     this.IUI.win.setTimeout(function() {
+       this.veilContainer.removeAttribute("disable-transitions");
+       this.nodeInfo.container.removeAttribute("disable-transitions");
+       this.transitionDisabler = null;
+     }.bind(this), 500);
+  },
+
+  /**
    * Handle clicks.
    *
    * @param nsIDOMEvent aEvent
    *        The DOM event.
    */
   handleClick: function Highlighter_handleClick(aEvent)
   {
     // Stop inspection when the user clicks on a node.
@@ -958,16 +987,18 @@ InspectorUI.prototype = {
   },
 
   /**
    * Initialize highlighter.
    */
   initializeHighlighter: function IUI_initializeHighlighter()
   {
     this.highlighter = new Highlighter(this);
+    this.browser.addEventListener("keypress", this, true);
+    this.highlighter.highlighterContainer.addEventListener("keypress", this, true);
     this.highlighterReady();
   },
 
   /**
    * Initialize the InspectorStore.
    */
   initializeStore: function IUI_initializeStore()
   {
@@ -1081,20 +1112,16 @@ InspectorUI.prototype = {
   startInspecting: function IUI_startInspecting()
   {
     // if currently editing an attribute value, starting
     // "live inspection" mode closes the editor
     if (this.treePanel && this.treePanel.editingContext)
       this.treePanel.closeEditor();
 
     this.inspectToolbutton.checked = true;
-    // Attach event listeners to content window and child windows to enable
-    // highlighting and click to stop inspection.
-    this.browser.addEventListener("keypress", this, true);
-    this.highlighter.highlighterContainer.addEventListener("keypress", this, true);
     this.highlighter.attachInspectListeners();
 
     this.inspecting = true;
     this.toolsDim(true);
     this.highlighter.veilContainer.removeAttribute("locked");
     this.highlighter.nodeInfo.container.removeAttribute("locked");
   },
 
--- a/browser/devtools/highlighter/test/browser_inspector_infobar.js
+++ b/browser/devtools/highlighter/test/browser_inspector_infobar.js
@@ -19,19 +19,19 @@ function test()
   let style = "body{width:100%;height: 100%} div {position: absolute;height: 100px;width: 500px}#bottom {bottom: 0px}#vertical {height: 100%}";
   let html = "<style>" + style + "</style><div id=vertical></div><div id=top class='class1 class2'></div><div id=bottom></div>"
 
   content.location = "data:text/html," + encodeURIComponent(html);
 
   function setupInfobarTest()
   {
     nodes = [
-      {node: doc.querySelector("#top"), position: "bottom", tag: "DIV", id: "top", classes: "class1 class2"},
-      {node: doc.querySelector("#vertical"), position: "overlap", tag: "DIV", id: "vertical", classes: ""},
-      {node: doc.querySelector("#bottom"), position: "top", tag: "DIV", id: "bottom", classes: ""},
+      {node: doc.querySelector("#top"), position: "bottom", tag: "DIV", id: "#top", classes: ".class1 .class2"},
+      {node: doc.querySelector("#vertical"), position: "overlap", tag: "DIV", id: "#vertical", classes: ""},
+      {node: doc.querySelector("#bottom"), position: "top", tag: "DIV", id: "#bottom", classes: ""},
       {node: doc.querySelector("body"), position: "overlap", tag: "BODY", id: "", classes: ""},
     ]
 
     for (let i = 0; i < nodes.length; i++) {
       ok(nodes[i].node, "node " + i + " found");
     }
 
     Services.obs.addObserver(runTests,
--- a/browser/devtools/highlighter/test/browser_inspector_tab_switch.js
+++ b/browser/devtools/highlighter/test/browser_inspector_tab_switch.js
@@ -182,20 +182,28 @@ function inspectorFocusTab2()
 
   // Make sure the inspector is still open.
   ok(!InspectorUI.inspecting, "Inspector is not highlighting");
   ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is not open");
   ok(!InspectorUI.isSidebarOpen, "Inspector Sidebar is not open");
   is(InspectorUI.store.length, 2, "Inspector.store.length is 2");
   isnot(InspectorUI.selection, div, "selection does not match the div element");
 
-  // Switch back to tab 1.
-  Services.obs.addObserver(inspectorSecondFocusTab1,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
-  gBrowser.selectedTab = tab1;
+  // Make sure keybindings still sork
+  EventUtils.synthesizeKey("VK_RETURN", { });
+
+  executeSoon(function() {
+    ok(InspectorUI.inspecting, "Inspector is highlighting");
+    InspectorUI.toggleInspection();
+
+    // Switch back to tab 1.
+    Services.obs.addObserver(inspectorSecondFocusTab1,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
+    gBrowser.selectedTab = tab1;
+  });
 }
 
 function inspectorSecondFocusTab1()
 {
   Services.obs.removeObserver(inspectorSecondFocusTab1,
     InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY);
 
   ok(InspectorUI.inspecting, "Inspector is highlighting");
--- a/browser/devtools/styleeditor/Makefile.in
+++ b/browser/devtools/styleeditor/Makefile.in
@@ -38,17 +38,15 @@
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 ifdef ENABLE_TESTS
-  ifneq (mobile,$(MOZ_BUILD_APP))
-  	  DIRS += test
-  endif
+DIRS += test
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 libs::
 	$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
--- a/browser/devtools/styleinspector/Makefile.in
+++ b/browser/devtools/styleinspector/Makefile.in
@@ -39,17 +39,15 @@
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 ifdef ENABLE_TESTS
-ifneq (mobile,$(MOZ_BUILD_APP))
 DIRS += test/browser
 endif
-endif
 
 include $(topsrcdir)/config/rules.mk
 
 libs::
 	$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -24,16 +24,17 @@
  *   David Dahl <ddahl@mozilla.com> (original author)
  *   Rob Campbell <rcampbell@mozilla.com>
  *   Johnathan Nightingale <jnightingale@mozilla.com>
  *   Patrick Walton <pcwalton@mozilla.com>
  *   Julian Viereck <jviereck@mozilla.com>
  *   Mihai Șucan <mihai.sucan@gmail.com>
  *   Michael Ratcliffe <mratcliffe@mozilla.com>
  *   Joe Walker <jwalker@mozilla.com>
+ *   Sonny Piers <sonny.piers@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
@@ -279,16 +280,19 @@ const ERRORS = { LOG_MESSAGE_MISSING_ARG
                  CANNOT_GET_HUD: "Cannot getHeads Up Display with provided ID",
                  MISSING_ARGS: "Missing arguments",
                  LOG_OUTPUT_FAILED: "Log Failure: Could not append messageNode to outputNode",
 };
 
 // The indent of a console group in pixels.
 const GROUP_INDENT = 12;
 
+// The pref prefix for webconsole filters
+const PREFS_PREFIX = "devtools.webconsole.filter.";
+
 /**
  * Implements the nsIStreamListener and nsIRequestObserver interface. Used
  * within the HS_httpObserverFactory function to get the response body of
  * requests.
  *
  * The code is mostly based on code listings from:
  *
  *   http://www.softwareishard.com/blog/firebug/
@@ -1785,19 +1789,28 @@ HUD_SERVICE.prototype =
    * @returns void
    */
   registerDisplay: function HS_registerDisplay(aHUDId)
   {
     // register a display DOM node Id with the service.
     if (!aHUDId){
       throw new Error(ERRORS.MISSING_ARGS);
     }
-    this.filterPrefs[aHUDId] = this.defaultFilterPrefs;
-    // init storage objects:
-    this.storage.createDisplay(aHUDId);
+    this.filterPrefs[aHUDId] = {
+      network: Services.prefs.getBoolPref(PREFS_PREFIX + "network"),
+      networkinfo: Services.prefs.getBoolPref(PREFS_PREFIX + "networkinfo"),
+      csserror: Services.prefs.getBoolPref(PREFS_PREFIX + "csserror"),
+      cssparser: Services.prefs.getBoolPref(PREFS_PREFIX + "cssparser"),
+      exception: Services.prefs.getBoolPref(PREFS_PREFIX + "exception"),
+      jswarn: Services.prefs.getBoolPref(PREFS_PREFIX + "jswarn"),
+      error: Services.prefs.getBoolPref(PREFS_PREFIX + "error"),
+      info: Services.prefs.getBoolPref(PREFS_PREFIX + "info"),
+      warn: Services.prefs.getBoolPref(PREFS_PREFIX + "warn"),
+      log: Services.prefs.getBoolPref(PREFS_PREFIX + "log"),
+    };
   },
 
   /**
    * When a display is being destroyed, unregister it first
    *
    * @param string aHUDId
    *        The ID of a HUD.
    * @returns void
@@ -1834,19 +1847,16 @@ HUD_SERVICE.prototype =
     }
 
     if (hud.jsterm) {
       hud.jsterm.autocompletePopup.destroy();
     }
 
     delete this.hudReferences[aHUDId];
 
-    // remove the related storage object
-    this.storage.removeDisplay(aHUDId);
-
     for (let windowID in this.windowIds) {
       if (this.windowIds[windowID] == aHUDId) {
         delete this.windowIds[windowID];
       }
     }
 
     this.unregisterActiveContext(aHUDId);
 
@@ -1877,20 +1887,16 @@ HUD_SERVICE.prototype =
    * @returns void
    */
   wakeup: function HS_wakeup()
   {
     if (Object.keys(this.hudReferences).length > 0) {
       return;
     }
 
-    this.storage = new ConsoleStorage();
-    this.defaultFilterPrefs = this.storage.defaultDisplayPrefs;
-    this.defaultGlobalConsolePrefs = this.storage.defaultGlobalConsolePrefs;
-
     // begin observing HTTP traffic
     this.startHTTPObservation();
 
     HUDWindowObserver.init();
     HUDConsoleObserver.init();
     ConsoleAPIObserver.init();
   },
 
@@ -1906,20 +1912,17 @@ HUD_SERVICE.prototype =
     delete this.httpObserver;
 
     Services.obs.removeObserver(this.httpResponseExaminer,
                                 "http-on-examine-response");
 
     this.openRequests = {};
     this.openResponseHeaders = {};
 
-    // delete the storage as it holds onto channels
-    delete this.storage;
     delete this.defaultFilterPrefs;
-    delete this.defaultGlobalConsolePrefs;
 
     delete this.lastFinishedRequestCallback;
 
     HUDWindowObserver.uninit();
     HUDConsoleObserver.uninit();
     ConsoleAPIObserver.shutdown();
   },
 
@@ -3933,40 +3936,40 @@ HeadsUpDisplay.prototype = {
     toolbarButton.setAttribute("tooltip", this.getStr("tip" + name));
     toolbarButton.setAttribute("category", aDescriptor.category);
     toolbarButton.setAttribute("hudId", this.hudId);
     toolbarButton.classList.add("webconsole-filter-button");
 
     let menuPopup = this.makeXULNode("menupopup");
     toolbarButton.appendChild(menuPopup);
 
-    let allChecked = true;
+    let someChecked = false;
     for (let i = 0; i < aDescriptor.severities.length; i++) {
       let severity = aDescriptor.severities[i];
       let menuItem = this.makeXULNode("menuitem");
       menuItem.setAttribute("label", this.getStr("btn" + severity.name));
       menuItem.setAttribute("type", "checkbox");
       menuItem.setAttribute("autocheck", "false");
       menuItem.setAttribute("hudId", this.hudId);
 
       let prefKey = severity.prefKey;
       menuItem.setAttribute("prefKey", prefKey);
 
       let checked = this.filterPrefs[prefKey];
       menuItem.setAttribute("checked", checked);
-      if (!checked) {
-        allChecked = false;
+      if (checked) {
+        someChecked = true;
       }
 
       menuItem.addEventListener("command", toggleFilter, false);
 
       menuPopup.appendChild(menuItem);
     }
 
-    toolbarButton.setAttribute("checked", allChecked);
+    toolbarButton.setAttribute("checked", someChecked);
   },
 
   /**
    * Creates the close button on the toolbar.
    *
    * @param nsIDOMNode aParent
    *        The toolbar to attach the close button to.
    * @return void
@@ -6326,185 +6329,16 @@ HeadsUpDisplayUICommands = {
         HUDService.saveRequestAndResponseBodies = checked;
         break;
       }
     }
   },
 
 };
 
-//////////////////////////////////////////////////////////////////////////
-// ConsoleStorage
-//////////////////////////////////////////////////////////////////////////
-
-var prefs = Services.prefs;
-
-const GLOBAL_STORAGE_INDEX_ID = "GLOBAL_CONSOLE";
-const PREFS_PREFIX = "devtools.webconsole.filter.";
-const PREFS = { network: PREFS_PREFIX + "network",
-                networkinfo: PREFS_PREFIX + "networkinfo",
-                csserror: PREFS_PREFIX + "csserror",
-                cssparser: PREFS_PREFIX + "cssparser",
-                exception: PREFS_PREFIX + "exception",
-                jswarn: PREFS_PREFIX + "jswarn",
-                error: PREFS_PREFIX + "error",
-                info: PREFS_PREFIX + "info",
-                warn: PREFS_PREFIX + "warn",
-                log: PREFS_PREFIX + "log",
-              };
-
-function ConsoleStorage()
-{
-  this.sequencer = null;
-  this.consoleDisplays = {};
-  // each display will have an index that tracks each ConsoleEntry
-  this.displayIndexes = {};
-  this.globalStorageIndex = [];
-  this.globalDisplay = {};
-  this.createDisplay(GLOBAL_STORAGE_INDEX_ID);
-  // TODO: need to create a method that truncates the message
-  // see bug 570543
-
-  this.defaultDisplayPrefs = {
-    network: prefs.getBoolPref(PREFS.network),
-    networkinfo: prefs.getBoolPref(PREFS.networkinfo),
-    csserror: prefs.getBoolPref(PREFS.csserror),
-    cssparser: prefs.getBoolPref(PREFS.cssparser),
-    exception: prefs.getBoolPref(PREFS.exception),
-    jswarn: prefs.getBoolPref(PREFS.jswarn),
-    error: prefs.getBoolPref(PREFS.error),
-    info: prefs.getBoolPref(PREFS.info),
-    warn: prefs.getBoolPref(PREFS.warn),
-    log: prefs.getBoolPref(PREFS.log),
-  };
-}
-
-ConsoleStorage.prototype = {
-
-  sequenceId: function CS_sequencerId()
-  {
-    if (!this.sequencer) {
-      this.sequencer = this.createSequencer();
-    }
-    return this.sequencer.next();
-  },
-
-  createSequencer: function CS_createSequencer()
-  {
-    function sequencer(aInt) {
-      while(1) {
-        aInt++;
-        yield aInt;
-      }
-    }
-    return sequencer(-1);
-  },
-
-  globalStore: function CS_globalStore(aIndex)
-  {
-    return this.displayStore(GLOBAL_CONSOLE_DOM_NODE_ID);
-  },
-
-  displayStore: function CS_displayStore(aId)
-  {
-    var self = this;
-    var idx = -1;
-    var id = aId;
-    var aLength = self.displayIndexes[id].length;
-
-    function displayStoreGenerator(aInt, aLength)
-    {
-      // create a generator object to iterate through any of the display stores
-      // from any index-starting-point
-      while(1) {
-        // throw if we exceed the length of displayIndexes?
-        aInt++;
-        var indexIt = self.displayIndexes[id];
-        var index = indexIt[aInt];
-        if (aLength < aInt) {
-          // try to see if we have more entries:
-          var newLength = self.displayIndexes[id].length;
-          if (newLength > aLength) {
-            aLength = newLength;
-          }
-          else {
-            throw new StopIteration();
-          }
-        }
-        var entry = self.consoleDisplays[id][index];
-        yield entry;
-      }
-    }
-
-    return displayStoreGenerator(-1, aLength);
-  },
-
-  recordEntries: function CS_recordEntries(aHUDId, aConfigArray)
-  {
-    var len = aConfigArray.length;
-    for (var i = 0; i < len; i++){
-      this.recordEntry(aHUDId, aConfigArray[i]);
-    }
-  },
-
-
-  recordEntry: function CS_recordEntry(aHUDId, aConfig)
-  {
-    var id = this.sequenceId();
-
-    this.globalStorageIndex[id] = { hudId: aHUDId };
-
-    var displayStorage = this.consoleDisplays[aHUDId];
-
-    var displayIndex = this.displayIndexes[aHUDId];
-
-    if (displayStorage && displayIndex) {
-      var entry = new ConsoleEntry(aConfig, id);
-      displayIndex.push(entry.id);
-      displayStorage[entry.id] = entry;
-      return entry;
-    }
-    else {
-      throw new Error("Cannot get displayStorage or index object for id " + aHUDId);
-    }
-  },
-
-  getEntry: function CS_getEntry(aId)
-  {
-    var display = this.globalStorageIndex[aId];
-    var storName = display.hudId;
-    return this.consoleDisplays[storName][aId];
-  },
-
-  updateEntry: function CS_updateEntry(aUUID)
-  {
-    // update an individual entry
-    // TODO: see bug 568634
-  },
-
-  createDisplay: function CS_createdisplay(aId)
-  {
-    if (!this.consoleDisplays[aId]) {
-      this.consoleDisplays[aId] = {};
-      this.displayIndexes[aId] = [];
-    }
-  },
-
-  removeDisplay: function CS_removeDisplay(aId)
-  {
-    try {
-      delete this.consoleDisplays[aId];
-      delete this.displayIndexes[aId];
-    }
-    catch (ex) {
-      Cu.reportError("Could not remove console display for id " + aId);
-    }
-  }
-};
-
 /**
  * A Console log entry
  *
  * @param JSObject aConfig, object literal with ConsolEntry properties
  * @param integer aId
  * @returns void
  */
 
--- a/browser/devtools/webconsole/Makefile.in
+++ b/browser/devtools/webconsole/Makefile.in
@@ -52,14 +52,12 @@ EXTRA_JS_MODULES = \
 		GcliCommands.jsm \
 		$(NULL)
 
 EXTRA_PP_JS_MODULES = \
 		HUDService.jsm \
 		$(NULL)
 
 ifdef ENABLE_TESTS
-ifneq (mobile,$(MOZ_BUILD_APP))
 DIRS += test/browser
 endif
-endif
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/devtools/webconsole/NetworkPanel.xhtml
+++ b/browser/devtools/webconsole/NetworkPanel.xhtml
@@ -44,17 +44,17 @@
    - the terms of any one of the MPL, the GPL or the LGPL.
    -
    - ***** END LICENSE BLOCK ***** -->
 
 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
-  <link rel="stylesheet" href="chrome://global/skin/webConsole_networkPanel.css" type="text/css"/>
+  <link rel="stylesheet" href="chrome://browser/skin/devtools/webconsole_networkpanel.css" type="text/css"/>
 </head>
 <body role="application">
 <table id="header">
   <tr>
     <th class="property-name"
         scope="row">&networkPanel.requestURL;:</th>
     <td class="property-value"
         id="headUrl"></td>
--- a/browser/devtools/webconsole/test/browser/Makefile.in
+++ b/browser/devtools/webconsole/test/browser/Makefile.in
@@ -17,16 +17,17 @@
 # Portions created by the Initial Developer are Copyright (C) 2010
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #  David Dahl <ddahl@mozilla.com>
 #  Patrick Walton <pcwalton@mozilla.com>
 #  Mihai Șucan <mihai.sucan@gmail.com>
 #  Rob Campbell <rcampbell@mozilla.com>
+#  Sonny Piers <sonny.piers@gmail.com>
 #
 # Alternatively, the contents of this file may be used under the terms of
 # either of 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
@@ -76,20 +77,16 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_log_node_classes.js \
 	browser_webconsole_network_panel.js \
 	browser_webconsole_jsterm.js \
 	browser_webconsole_null_and_undefined_output.js \
 	browser_webconsole_output_order.js \
 	browser_webconsole_property_panel.js \
 	browser_webconsole_property_provider.js \
 	browser_webconsole_registries.js \
-	browser_webconsole_storage_create_display.js \
-	browser_webconsole_storage_iteration.js \
-	browser_webconsole_storage_record_entry.js \
-	browser_webconsole_storage_record_many_entries.js \
 	browser_webconsole_bug_587617_output_copy.js \
 	browser_webconsole_bug_585237_line_limit.js \
 	browser_webconsole_bug_581231_close_button.js \
 	browser_webconsole_bug_582201_duplicate_errors.js \
 	browser_webconsole_bug_580454_timestamp_l10n.js \
 	browser_webconsole_netlogging.js \
 	browser_webconsole_bug_583816_tab_focus.js \
 	browser_webconsole_bug_594477_clickable_output.js \
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_bug_622303_persistent_filters.js
+++ b/browser/devtools/webconsole/test/browser/browser_webconsole_bug_622303_persistent_filters.js
@@ -1,59 +1,116 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
   let prefService = Services.prefs;
-  let prefs = [
-    "network",
-    "networkinfo",
-    "csserror",
-    "cssparser",
-    "exception",
-    "jswarn",
-    "error",
-    "warn",
-    "info",
-    "log"
-  ];
 
-  //Set all prefs to true
-  prefs.forEach(function(pref) {
-    prefService.setBoolPref("devtools.webconsole.filter." + pref, true);
-  });
+  let prefs = {
+    "net": [
+      "network",
+      "networkinfo"
+    ],
+    "css": [
+      "csserror",
+      "cssparser"
+    ],
+    "js": [
+      "exception",
+      "jswarn"
+    ],
+    "logging": [
+       "error",
+       "warn",
+       "info",
+       "log"
+    ]
+  };
+
+  // Set all prefs to true
+  for (let category in prefs) {
+    prefs[category].forEach(function(pref) {
+      prefService.setBoolPref("devtools.webconsole.filter." + pref, true);
+    });
+  }
 
   addTab("about:blank");
   openConsole();
-  
+
   let hud = HUDService.getHudByWindow(content);
-  let hudId = HUDService.getHudIdByWindow(content);
+
+  // Check if the filters menuitems exists and are checked
+  for (let category in prefs) {
+    let button = hud.HUDBox.querySelector(".webconsole-filter-button[category=\""
+                                           + category + "\"]");
+    ok(isChecked(button), "main button for " + category + " category is checked");
 
-  //Check if the filters menuitems exists and is checked
-  prefs.forEach(function(pref) {
-    let checked = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]").
-      getAttribute("checked");
-    is(checked, "true", "menuitem for " + pref + " exists and is checked");
-  });
-  
-  //Set all prefs to false
-  prefs.forEach(function(pref) {
-    HUDService.setFilterState(hudId, pref, false);
-  });
+    prefs[category].forEach(function(pref) {
+      let menuitem = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]");
+      ok(isChecked(menuitem), "menuitem for " + pref + " is checked");
+    });
+  }
+
+  // Set all prefs to false
+  for (let category in prefs) {
+    prefs[category].forEach(function(pref) {
+      HUDService.setFilterState(hud.hudId, pref, false);
+    });
+  }
 
   //Re-init the console
   closeConsole();
   openConsole();
 
   hud = HUDService.getHudByWindow(content);
-  
-  //Check if filters menuitems exists and are unchecked
-  prefs.forEach(function(pref) {
-    let checked = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]").
-      getAttribute("checked");
-    is(checked, "false", "menuitem for " + pref + " exists and is not checked");
-    prefService.clearUserPref("devtools.webconsole.filter." + pref);
-  });
-  
+
+  // Check if the filter button and menuitems are unchecked
+  for (let category in prefs) {
+    let button = hud.HUDBox.querySelector(".webconsole-filter-button[category=\""
+                                           + category + "\"]");
+    ok(isUnchecked(button), "main button for " + category + " category is not checked");
+
+    prefs[category].forEach(function(pref) {
+      let menuitem = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]");
+      ok(isUnchecked(menuitem), "menuitem for " + pref + " is not checked");
+    });
+  }
+
+  // Set first pref in each category to true
+  for (let category in prefs) {
+    HUDService.setFilterState(hud.hudId, prefs[category][0], true);
+  }
+
+  // Re-init the console
+  closeConsole();
+  openConsole();
+
+  hud = HUDService.getHudByWindow(content);
+
+  // Check the main category button is checked and first menuitem is checked
+  for (let category in prefs) {
+    let button = hud.HUDBox.querySelector(".webconsole-filter-button[category=\""
+                                           + category + "\"]");
+    ok(isChecked(button), category  + " button is checked when first pref is true");
+
+    let pref = prefs[category][0];
+    let menuitem = hud.HUDBox.querySelector("menuitem[prefKey=" + pref + "]");
+    ok(isChecked(menuitem), "first " + category + " menuitem is checked");
+  }
+
+  // Clear prefs
+  for (let category in prefs) {
+    prefs[category].forEach(function(pref) {
+      prefService.clearUserPref("devtools.webconsole.filter." + pref);
+    });
+  }
+
   gBrowser.removeCurrentTab();
-  
   finish();
 }
+
+function isChecked(aNode) {
+  return aNode.getAttribute("checked") === "true";
+}
+
+function isUnchecked(aNode) {
+  return aNode.getAttribute("checked") === "false";
+}
deleted file mode 100644
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_storage_create_display.js
+++ /dev/null
@@ -1,73 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is DevTools test code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  David Dahl <ddahl@mozilla.com>
- *  Patrick Walton <pcwalton@mozilla.com>
- *  Julian Viereck <jviereck@mozilla.com>
- *  Mihai Sucan <mihai.sucan@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// Tests that the console message store is initialized properly.
-
-const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
-
-function test() {
-  addTab(TEST_URI);
-  browser.addEventListener("DOMContentLoaded", testStorageCreateDisplay,
-                           false);
-}
-
-function testStorageCreateDisplay() {
-  browser.removeEventListener("DOMContentLoaded", testStorageCreateDisplay,
-                              false);
-
-  openConsole();
-
-  let cs = HUDService.storage;
-
-  ok(typeof cs.consoleDisplays == "object",
-     "consoledisplays exist");
-  ok(typeof cs.displayIndexes == "object",
-     "console indexes exist");
-  cs.createDisplay("foo");
-  ok(typeof cs.consoleDisplays["foo"] == "object",
-     "foo display exists");
-  ok(typeof cs.displayIndexes["foo"] == "object",
-     "foo index exists");
-
-  cs.removeDisplay("foo");
-
-  finishTest();
-}
-
deleted file mode 100644
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_storage_iteration.js
+++ /dev/null
@@ -1,92 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is DevTools test code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  David Dahl <ddahl@mozilla.com>
- *  Patrick Walton <pcwalton@mozilla.com>
- *  Julian Viereck <jviereck@mozilla.com>
- *  Mihai Sucan <mihai.sucan@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// Test that the iterator API of the console message store works.
-
-const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
-
-function test() {
-  addTab(TEST_URI);
-  browser.addEventListener("DOMContentLoaded", testStorageIteration, false);
-}
-
-function testStorageIteration() {
-  browser.removeEventListener("DOMContentLoaded", testStorageIteration,
-                              false);
-
-  openConsole();
-
-  let cs = HUDService.storage;
-
-  // Must have enough entries present to avoid exhausting the iterators below.
-  cs.createDisplay("foo");
-  for (let i = 0; i < 300; i++) {
-    cs.recordEntry("foo", { logLevel: "network", message: "foo" });
-  }
-
-  var id = "foo";
-  var it = cs.displayStore(id);
-  var entry = it.next();
-  var entry2 = it.next();
-
-  let entries = [];
-  for (var i = 0; i < 100; i++) {
-    let _entry = it.next();
-    entries.push(_entry);
-  }
-
-  ok(entries.length == 100, "entries length == 100");
-
-  let entries2 = [];
-
-  for (var i = 0; i < 100; i++){
-    let _entry = it.next();
-    entries2.push(_entry);
-  }
-
-  ok(entries[0].id != entries2[0].id,
-     "two distinct pages of log entries");
-
-  cs.removeDisplay("foo");
-  cs = null;
-  
-  finishTest();
-}
-
deleted file mode 100644
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_storage_record_entry.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is DevTools test code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  David Dahl <ddahl@mozilla.com>
- *  Patrick Walton <pcwalton@mozilla.com>
- *  Julian Viereck <jviereck@mozilla.com>
- *  Mihai Sucan <mihai.sucan@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// Tests that the recordEntry() method of the console store works.
-
-const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
-
-function test() {
-  addTab(TEST_URI);
-  browser.addEventListener("DOMContentLoaded", testStorageRecordEntry,
-                              false);
-}
-
-function testStorageRecordEntry() {
-  browser.removeEventListener("DOMContentLoaded", testStorageRecordEntry,
-                              false);
-  openConsole();
-
-  let cs = HUDService.storage;
-
-  cs.createDisplay("foo");
-
-  var config = {
-    logLevel: "network",
-    message: "HumminaHummina!",
-    activity: {
-      stage: "barStage",
-      data: "bar bar bar bar"
-    }
-  };
-  var entry = cs.recordEntry("foo", config);
-  var res = entry.id;
-  ok(entry.id != null, "Entry.id is: " + res);
-  ok(cs.displayIndexes["foo"].length == 1,
-     "We added one entry.");
-  entry = cs.getEntry(res);
-  ok(entry.id > -1,
-     "We got an entry through the global interface");
-
-  cs.removeDisplay("foo");
-  cs = null;
-  finishTest();
-}
-
deleted file mode 100644
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_storage_record_many_entries.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is DevTools test code.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  David Dahl <ddahl@mozilla.com>
- *  Patrick Walton <pcwalton@mozilla.com>
- *  Julian Viereck <jviereck@mozilla.com>
- *  Mihai Sucan <mihai.sucan@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// Test that the recordManyEntries() method of the console store works.
-
-const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
-
-function test() {
-  addTab(TEST_URI);
-  browser.addEventListener("DOMContentLoaded", testStorageRecordManyEntries,
-                           false);
-}
-
-function testStorageRecordManyEntries() {
-  browser.removeEventListener("DOMContentLoaded",
-                              testStorageRecordManyEntries, false);
-
-  openConsole();
-
-  let cs = HUDService.storage;
-
-  cs.createDisplay("foo");
-
-  var configArr = [];
-
-  for (var i = 0; i < 1000; i++){
-    let config = {
-      logLevel: "network",
-      message: "HumminaHummina!",
-      activity: {
-        stage: "barStage",
-        data: "bar bar bar bar"
-      }
-    };
-    configArr.push(config);
-  }
-
-  cs.recordEntries("foo", configArr);
-  ok(cs.displayIndexes["foo"].length == 1000,
-     "1000 entries in foo now");
-
-  cs.removeDisplay("foo");
-
-  finishTest();
-}
-
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -129,16 +129,17 @@
 @BINPATH@/components/content_htmldoc.xpt
 @BINPATH@/components/content_html.xpt
 @BINPATH@/components/content_xslt.xpt
 @BINPATH@/components/content_xtf.xpt
 @BINPATH@/components/cookie.xpt
 @BINPATH@/components/directory.xpt
 @BINPATH@/components/docshell.xpt
 @BINPATH@/components/dom.xpt
+@BINPATH@/components/dom_apps.xpt
 @BINPATH@/components/dom_base.xpt
 @BINPATH@/components/dom_battery.xpt
 @BINPATH@/components/dom_canvas.xpt
 @BINPATH@/components/dom_core.xpt
 @BINPATH@/components/dom_css.xpt
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_notification.xpt
@@ -370,16 +371,18 @@
 @BINPATH@/components/nsPrompter.manifest
 @BINPATH@/components/nsPrompter.js
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/SyncComponents.manifest
 @BINPATH@/components/Weave.js
 #endif
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
+@BINPATH@/components/Webapps.js
+@BINPATH@/components/Webapps.manifest
 
 ; Modules
 @BINPATH@/modules/*
 
 ; Safe Browsing
 @BINPATH@/components/nsSafebrowsingApplication.manifest
 @BINPATH@/components/nsSafebrowsingApplication.js
 @BINPATH@/components/nsURLClassifier.manifest
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -247,16 +247,17 @@ res/fonts/mathfontCMEX10.properties
 res/fonts/mathfontCMSY10.properties
 res/fonts/mathfontMTExtra.properties
 res/fonts/mathfontMath1.properties
 res/fonts/mathfontMath2.properties
 res/fonts/mathfontMath4.properties
 res/fonts/mathfontPUA.properties
 res/fonts/pangoFontEncoding.properties
 res/forms.css
+res/full-screen-override.css
 res/hiddenWindow.html
 res/html.css
 res/html/gopher-audio.gif
 res/html/gopher-binary.gif
 res/html/gopher-find.gif
 res/html/gopher-image.gif
 res/html/gopher-menu.gif
 res/html/gopher-movie.gif
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -696,19 +696,49 @@
     RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0024-ABCDEFFEDCBA}"
   ${EndIf}
   ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0025-ABCDEFFEDCBA}"
     RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0025-ABCDEFFEDCBA}"
   ${EndIf}
   ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0026-ABCDEFFEDCBA}"
     RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0026-ABCDEFFEDCBA}"
   ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0027-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0027-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0028-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0028-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0029-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0029-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0030-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0030-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0031-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0031-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0032-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0016-0000-0032-ABCDEFFEDCBA}"
+  ${EndIf}
   ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0000-ABCDEFFEDCBA}"
     RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0000-ABCDEFFEDCBA}"
   ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0001-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0001-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0002-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0002-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0003-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0003-ABCDEFFEDCBA}"
+  ${EndIf}
+  ${If} ${FileExists} "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0004-ABCDEFFEDCBA}"
+    RmDir /r /REBOOTOK "$INSTDIR\extensions\{CAFEEFAC-0017-0000-0004-ABCDEFFEDCBA}"
+  ${EndIf}
 !macroend
 !define RemoveDeprecatedFiles "!insertmacro RemoveDeprecatedFiles"
 
 ; Adds a pinned shortcut to Task Bar on update for Windows 7 and above if this
 ; macro has never been called before and the application is default (see
 ; PinToTaskBar for more details).
 !macro MigrateTaskBarShortcut
   ${GetShortcutsLogPath} $0
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -239,28 +239,26 @@ pu.notifyButton.label=Details…
 pu.notifyButton.accesskey=D
 # LOCALIZATION NOTE %S will be replaced by the short name of the application.
 puNotifyText=%S has been updated
 puAlertTitle=%S Updated
 puAlertText=Click here for details
 
 # Geolocation UI
 
-# LOCALIZATION NOTE (geolocation.shareLocation geolocation.dontShareLocation geolocation.alwaysShare geolocation.neverShare): 
+# LOCALIZATION NOTE (geolocation.shareLocation geolocation.alwaysShareLocation geolocation.neverShareLocation):
 #If you're having trouble with the word Share, please use Allow and Block in your language.
 geolocation.shareLocation=Share Location
 geolocation.shareLocation.accesskey=a
-geolocation.dontShareLocation=Don't Share
-geolocation.dontShareLocation.accesskey=o
-geolocation.alwaysShare=Always Share
-geolocation.alwaysShare.accesskey=A
-geolocation.neverShare=Never Share
-geolocation.neverShare.accesskey=N
-geolocation.siteWantsToKnow=%S wants to know your location.
-geolocation.fileWantsToKnow=The file %S wants to know your location.
+geolocation.alwaysShareLocation=Always Share Location
+geolocation.alwaysShareLocation.accesskey=A
+geolocation.neverShareLocation=Never Share Location
+geolocation.neverShareLocation.accesskey=N
+geolocation.shareWithSite=Would you like to share your location with %S?
+geolocation.shareWithFile=Would you like to share your location with the file %S?
 # LOCALIZATION NOTE (geolocation.learnMore): Use the unicode ellipsis char, \u2026,
 # or use "..." if \u2026 doesn't suit traditions in your locale.
 geolocation.learnMore=Learn More…
 
 # Phishing/Malware Notification Bar.
 # LOCALIZATION NOTE (notAForgery, notAnAttack)
 # The two button strings will never be shown at the same time, so
 # it's okay for them to have the same access key
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -30,75 +30,128 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK *****
 
+# Deliberately excluded, since the braces cause some versions of sed to choke, 
+# causing the build to fail (see bug 696498 comment 13):
+# browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile
 add_makefiles "
 browser/Makefile
 browser/app/Makefile
 browser/app/profile/extensions/Makefile
 browser/base/Makefile
 browser/components/Makefile
+browser/components/about/Makefile
 browser/components/build/Makefile
 browser/components/certerror/Makefile
 browser/components/dirprovider/Makefile
 browser/components/feeds/Makefile
 browser/components/feeds/public/Makefile
 browser/components/feeds/src/Makefile
 browser/components/migration/Makefile
 browser/components/migration/public/Makefile
 browser/components/migration/src/Makefile
 browser/components/places/Makefile
 browser/components/places/src/Makefile
 browser/components/preferences/Makefile
 browser/components/privatebrowsing/Makefile
 browser/components/privatebrowsing/src/Makefile
-browser/components/safebrowsing/Makefile
 browser/components/search/Makefile
 browser/components/sessionstore/Makefile
 browser/components/sessionstore/src/Makefile
 browser/components/sidebar/src/Makefile
 browser/components/shell/Makefile
 browser/components/shell/public/Makefile
 browser/components/shell/src/Makefile
-browser/components/wintaskbar/Makefile
+browser/components/tabview/Makefile
+browser/devtools/Makefile
+browser/devtools/highlighter/Makefile
+browser/devtools/shared/Makefile
+browser/devtools/sourceeditor/Makefile
+browser/devtools/styleinspector/Makefile
+browser/devtools/webconsole/Makefile
 browser/fuel/Makefile
 browser/fuel/public/Makefile
 browser/fuel/src/Makefile
 browser/installer/Makefile
-browser/installer/windows/Makefile
 browser/locales/Makefile
 browser/themes/Makefile
-browser/themes/pinstripe/browser/Makefile
-browser/themes/pinstripe/communicator/Makefile
-browser/themes/pinstripe/Makefile
-browser/themes/winstripe/browser/Makefile
-browser/themes/winstripe/communicator/Makefile
-browser/themes/winstripe/Makefile
 $MOZ_BRANDING_DIRECTORY/Makefile
 $MOZ_BRANDING_DIRECTORY/content/Makefile
 $MOZ_BRANDING_DIRECTORY/locales/Makefile
 "
 
+if [ "$MOZ_SAFE_BROWSING" ]; then
+  add_makefiles "
+    browser/components/safebrowsing/Makefile
+  "
+fi
+
+if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
+  add_makefiles "
+    browser/components/wintaskbar/Makefile
+  "
+  if [ "$MOZ_INSTALLER" ]; then
+    add_makefiles "
+      browser/installer/windows/Makefile
+    "
+  fi
+fi
+
+if [ "$MOZ_WIDGET_TOOLKIT" = "gtk2" -o "$MOZ_WIDGET_TOOLKIT" = "qt" ]; then
+  add_makefiles "
+    browser/themes/gnomestripe/Makefile
+    browser/themes/gnomestripe/communicator/Makefile
+  "
+elif [ "$MOZ_WIDGET_TOOLKIT" = "cocoa" ]; then
+  add_makefiles "
+    browser/themes/pinstripe/Makefile
+    browser/themes/pinstripe/communicator/Makefile
+  "
+else
+  add_makefiles "
+    browser/themes/winstripe/Makefile
+    browser/themes/winstripe/communicator/Makefile
+  "
+fi
+
 if [ "$ENABLE_TESTS" ]; then
   add_makefiles "
     browser/base/content/test/Makefile
     browser/components/certerror/test/Makefile
+    browser/components/dirprovider/tests/Makefile
     browser/components/preferences/tests/Makefile
     browser/components/search/test/Makefile
     browser/components/sessionstore/test/browser/Makefile
     browser/components/shell/test/Makefile
     browser/components/feeds/test/Makefile
     browser/components/feeds/test/chrome/Makefile
     browser/components/places/tests/Makefile
     browser/components/places/tests/chrome/Makefile
     browser/components/places/tests/browser/Makefile
     browser/components/privatebrowsing/test/Makefile
     browser/components/privatebrowsing/test/browser/Makefile
-    browser/components/safebrowsing/content/test/Makefile
-    browser/components/wintaskbar/test/Makefile
+    browser/components/tabview/test/Makefile
+    browser/components/test/browser/Makefile
+    browser/devtools/highlighter/test/Makefile
+    browser/devtools/scratchpad/test/Makefile
+    browser/devtools/shared/test/Makefile
+    browser/devtools/sourceeditor/test/Makefile
+    browser/devtools/styleinspector/test/browser/Makefile
+    browser/devtools/webconsole/test/browser/Makefile
     browser/fuel/test/Makefile
   "
+  if [ "$MOZ_SAFE_BROWSING" ]; then
+    add_makefiles "
+      browser/components/safebrowsing/content/test/Makefile
+    "
+  fi
+  if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
+    add_makefiles "
+      browser/components/wintaskbar/test/Makefile
+    "
+  fi
 fi
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1954,17 +1954,17 @@ panel[dimmed="true"] {
   border-left-style: solid;
   border-top-left-radius: .3em;
   margin-left: 1em;
 }
 
 /* Highlighter */
 
 .highlighter-veil {
-  background-color: rgba(0, 0, 0, 0.5);
+  background-color: rgba(25, 25, 25, 0.5);
 }
 
 #highlighter-closebutton {
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
   margin-top: 0;
   margin-bottom: 0;
 }
 
rename from toolkit/themes/gnomestripe/global/webConsole.css
rename to browser/themes/gnomestripe/devtools/webconsole.css
--- a/toolkit/themes/gnomestripe/global/webConsole.css
+++ b/browser/themes/gnomestripe/devtools/webconsole.css
@@ -65,17 +65,17 @@
 
 .webconsole-timestamp {
   color: GrayText;
   margin-top: 0;
   margin-bottom: 0;
 }
 
 .hud-msg-node {
-  list-style-image: url(chrome://global/skin/icons/webconsole.png);
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
   -moz-image-region: rect(0, 1px, 0, 0);
 }
 
 .webconsole-msg-icon {
   margin: 3px 4px;
   width: 8px;
   height: 8px;
 }
@@ -157,17 +157,17 @@
 
 .webconsole-filter-button {
   margin: 0 3px;
 }
 
 .webconsole-filter-button > .toolbarbutton-menubutton-button,
 .webconsole-filter-button:not([type="menu-button"]) {
   -moz-box-orient: horizontal;
-  list-style-image: url("chrome://global/skin/icons/webconsole.png");
+  list-style-image: url("chrome://browser/skin/devtools/webconsole.png");
 }
 
 /* Network styles */
 .webconsole-filter-button[category="net"] {
   -moz-image-region: rect(0, 8px, 8px, 0);
 }
 
 .webconsole-msg-network > .webconsole-msg-icon-container {
rename from toolkit/themes/gnomestripe/global/icons/webconsole.png
rename to browser/themes/gnomestripe/devtools/webconsole.png
rename from toolkit/themes/gnomestripe/global/webConsole_networkPanel.css
rename to browser/themes/gnomestripe/devtools/webconsole_networkpanel.css
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -81,16 +81,19 @@ browser.jar:
   skin/classic/browser/tabview/edit-light.png         (tabview/edit-light.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)
   skin/classic/browser/devtools/arrows.png            (devtools/arrows.png)
   skin/classic/browser/devtools/goto-mdn.png          (devtools/goto-mdn.png)
   skin/classic/browser/devtools/csshtmltree.css       (devtools/csshtmltree.css)
+  skin/classic/browser/devtools/webconsole.css                  (devtools/webconsole.css)
+  skin/classic/browser/devtools/webconsole_networkpanel.css     (devtools/webconsole_networkpanel.css)
+  skin/classic/browser/devtools/webconsole.png                  (devtools/webconsole.png)
   skin/classic/browser/devtools/gcli.css              (devtools/gcli.css)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png              (devtools/breadcrumbs/ltr-end-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png     (devtools/breadcrumbs/ltr-end-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png             (devtools/breadcrumbs/ltr-end-selected.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end.png                      (devtools/breadcrumbs/ltr-end.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-pressed.png           (devtools/breadcrumbs/ltr-middle-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png  (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected.png          (devtools/breadcrumbs/ltr-middle-selected.png)
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -2641,17 +2641,17 @@ panel[dimmed="true"] {
 
 #status-bar > statusbarpanel {
   border-width: 0;
   -moz-appearance: none;
 }
 
 #addonbar-closebutton {
   padding: 0;
-  margin: 0 4px;
+  margin: 0 6px;
   list-style-image: url("chrome://global/skin/icons/close.png");
   border: none;
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
 #addonbar-closebutton:hover {
   -moz-image-region: rect(0, 32px, 16px, 16px);
 }
@@ -2685,17 +2685,17 @@ panel[dimmed="true"] {
   border-top-left-radius: .3em;
   margin-left: 1em;
 }
 
 
 /* Highlighter */
 
 .highlighter-veil {
-  background-color: rgba(0, 0, 0, 0.5);
+  background-color: rgba(25, 25, 25, 0.5);
 }
 
 #highlighter-closebutton {
   list-style-image: url("chrome://browser/skin/devtools/toolbarbutton-close.png");
   -moz-image-region: rect(0, 16px, 16px, 0);
   min-width: 16px;
   width: 16px;
   margin: 0 4px;
rename from toolkit/themes/pinstripe/global/webConsole.css
rename to browser/themes/pinstripe/devtools/webconsole.css
--- a/toolkit/themes/pinstripe/global/webConsole.css
+++ b/browser/themes/pinstripe/devtools/webconsole.css
@@ -32,17 +32,17 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-%include shared.inc
+%include ../shared.inc
 
 .hud-box {
   border-bottom: 1px solid #aaa;
   text-shadow: none;
 }
 
 .hud-box.animated {
   -moz-transition: height 100ms;
@@ -68,17 +68,17 @@
 
 .webconsole-timestamp {
   color: GrayText;
   margin-top: 0;
   margin-bottom: 0;
 }
 
 .hud-msg-node {
-  list-style-image: url(chrome://global/skin/icons/webconsole.png);
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
   -moz-image-region: rect(0, 1px, 0, 0);
 }
 
 .webconsole-msg-icon {
   margin: 3px 4px;
   width: 8px;
   height: 8px;
 }
@@ -182,17 +182,17 @@
   box-shadow: @roundButtonPressedShadow@;
   background: #d0d0d0;
 }
 
 .webconsole-filter-button > .toolbarbutton-menubutton-button {
   -moz-appearance: none;
   margin: 0;
   padding: 1px 0;
-  list-style-image: url("chrome://global/skin/icons/webconsole.png");
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
   -moz-box-orient: horizontal;
 }
 
 .webconsole-filter-button:hover:active,
 .webconsole-clear-console-button:hover:active {
   text-shadow: @loweredShadow@;
   box-shadow: @roundButtonPressedShadow@;
   background: @roundButtonPressedBackground@;
rename from toolkit/themes/pinstripe/global/icons/webconsole.png
rename to browser/themes/pinstripe/devtools/webconsole.png
rename from toolkit/themes/pinstripe/global/webConsole_networkPanel.css
rename to browser/themes/pinstripe/devtools/webconsole_networkpanel.css
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -122,16 +122,19 @@ browser.jar:
   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)
   skin/classic/browser/devtools/arrows.png                  (devtools/arrows.png)
   skin/classic/browser/devtools/goto-mdn.png                (devtools/goto-mdn.png)
   skin/classic/browser/devtools/csshtmltree.css             (devtools/csshtmltree.css)
   skin/classic/browser/devtools/gcli.css                    (devtools/gcli.css)
   skin/classic/browser/devtools/toolbarbutton-close.png     (devtools/toolbarbutton-close.png)
+* skin/classic/browser/devtools/webconsole.css                  (devtools/webconsole.css)
+  skin/classic/browser/devtools/webconsole_networkpanel.css     (devtools/webconsole_networkpanel.css)
+  skin/classic/browser/devtools/webconsole.png                  (devtools/webconsole.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png              (devtools/breadcrumbs/ltr-end-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png     (devtools/breadcrumbs/ltr-end-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png             (devtools/breadcrumbs/ltr-end-selected.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-end.png                      (devtools/breadcrumbs/ltr-end.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-pressed.png           (devtools/breadcrumbs/ltr-middle-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png  (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected.png          (devtools/breadcrumbs/ltr-middle-selected.png)
   skin/classic/browser/devtools/breadcrumbs/ltr-middle.png                   (devtools/breadcrumbs/ltr-middle.png)
--- a/browser/themes/winstripe/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -70,16 +70,21 @@
     border: 0;
     -moz-border-end: 1px solid #A9B7C9;
     min-width: 0;
     width: 3px;
     background-color: transparent;
     -moz-margin-start: -3px;
     position: relative;
   }
+
+  .menu-accel,
+  .menu-iconic-accel {
+    color: graytext;
+  }
 }
 
 @media all and (-moz-windows-compositor) {
   /* These should be hidden w/ glass enabled. Windows draws its own buttons. */
   .titlebar-button {
     display: none;
   }
 
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2620,17 +2620,17 @@ panel[dimmed="true"] {
   border-left-style: solid;
   border-top-left-radius: .3em;
   margin-left: 1em;
 }
 
 /* Highlighter */
 
 .highlighter-veil {
-  background-color: rgba(0, 0, 0, 0.5);
+  background-color: rgba(25, 25, 25, 0.5);
 }
 
 #highlighter-closebutton {
   list-style-image: url("chrome://browser/skin/devtools/toolbarbutton-close.png");
   -moz-image-region: rect(0, 16px, 16px, 0);
   min-width: 16px;
   width: 16px;
   -moz-appearance: none;
rename from toolkit/themes/winstripe/global/webConsole.css
rename to browser/themes/winstripe/devtools/webconsole.css
--- a/toolkit/themes/winstripe/global/webConsole.css
+++ b/browser/themes/winstripe/devtools/webconsole.css
@@ -64,17 +64,17 @@
 
 .webconsole-timestamp {
   color: GrayText;
   margin-top: 0;
   margin-bottom: 0;
 }
 
 .hud-msg-node {
-  list-style-image: url(chrome://global/skin/icons/webconsole.png);
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
   -moz-image-region: rect(0, 1px, 0, 0);
 }
 
 .webconsole-msg-icon {
   margin: 3px 4px;
   width: 8px;
   height: 8px;
 }
@@ -151,17 +151,17 @@
 }
 
 .webconsole-clear-console-button > .toolbarbutton-icon {
   display: none;
 }
 
 .webconsole-filter-button > .toolbarbutton-menubutton-button {
   -moz-box-orient: horizontal;
-  list-style-image: url("chrome://global/skin/icons/webconsole.png");
+  list-style-image: url("chrome://browser/skin/devtools/webconsole.png");
 }
 
 .webconsole-filter-button > .toolbarbutton-menubutton-button,
 .webconsole-filter-button > .toolbarbutton-menubutton-button:hover:active {
   -moz-padding-start: 6px;
   -moz-padding-end: 3px;
 }
 
rename from toolkit/themes/winstripe/global/icons/webconsole.png
rename to browser/themes/winstripe/devtools/webconsole.png
rename from toolkit/themes/winstripe/global/webConsole_networkPanel.css
rename to browser/themes/winstripe/devtools/webconsole_networkpanel.css
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -106,16 +106,19 @@ browser.jar:
         skin/classic/browser/tabview/tabview.png                    (tabview/tabview.png)
         skin/classic/browser/tabview/tabview-inverted.png           (tabview/tabview-inverted.png)
         skin/classic/browser/tabview/tabview.css                    (tabview/tabview.css)
         skin/classic/browser/devtools/arrows.png                    (devtools/arrows.png)
         skin/classic/browser/devtools/goto-mdn.png                  (devtools/goto-mdn.png)
         skin/classic/browser/devtools/csshtmltree.css               (devtools/csshtmltree.css)
         skin/classic/browser/devtools/gcli.css                      (devtools/gcli.css)
         skin/classic/browser/devtools/toolbarbutton-close.png       (devtools/toolbarbutton-close.png)
+        skin/classic/browser/devtools/webconsole.css                  (devtools/webconsole.css)
+        skin/classic/browser/devtools/webconsole_networkpanel.css     (devtools/webconsole_networkpanel.css)
+        skin/classic/browser/devtools/webconsole.png                  (devtools/webconsole.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png              (devtools/breadcrumbs/ltr-end-pressed.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png     (devtools/breadcrumbs/ltr-end-selected-pressed.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png             (devtools/breadcrumbs/ltr-end-selected.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-end.png                      (devtools/breadcrumbs/ltr-end.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-middle-pressed.png           (devtools/breadcrumbs/ltr-middle-pressed.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png  (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-middle-selected.png          (devtools/breadcrumbs/ltr-middle-selected.png)
         skin/classic/browser/devtools/breadcrumbs/ltr-middle.png                   (devtools/breadcrumbs/ltr-middle.png)
@@ -259,16 +262,19 @@ browser.jar:
         skin/classic/aero/browser/tabview/tabview.png                (tabview/tabview.png)
         skin/classic/aero/browser/tabview/tabview-inverted.png       (tabview/tabview-inverted.png)
         skin/classic/aero/browser/tabview/tabview.css                (tabview/tabview.css)
         skin/classic/aero/browser/devtools/arrows.png                (devtools/arrows.png)
         skin/classic/aero/browser/devtools/goto-mdn.png              (devtools/goto-mdn.png)
         skin/classic/aero/browser/devtools/csshtmltree.css           (devtools/csshtmltree.css)
         skin/classic/aero/browser/devtools/gcli.css                  (devtools/gcli.css)
         skin/classic/aero/browser/devtools/toolbarbutton-close.png   (devtools/toolbarbutton-close.png)
+        skin/classic/aero/browser/devtools/webconsole.css                  (devtools/webconsole.css)
+        skin/classic/aero/browser/devtools/webconsole_networkpanel.css     (devtools/webconsole_networkpanel.css)
+        skin/classic/aero/browser/devtools/webconsole.png                  (devtools/webconsole.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-end-pressed.png              (devtools/breadcrumbs/ltr-end-pressed.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png     (devtools/breadcrumbs/ltr-end-selected-pressed.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-end-selected.png             (devtools/breadcrumbs/ltr-end-selected.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-end.png                      (devtools/breadcrumbs/ltr-end.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-middle-pressed.png           (devtools/breadcrumbs/ltr-middle-pressed.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-middle-selected-pressed.png  (devtools/breadcrumbs/ltr-middle-selected-pressed.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-middle-selected.png          (devtools/breadcrumbs/ltr-middle-selected.png)
         skin/classic/aero/browser/devtools/breadcrumbs/ltr-middle.png                   (devtools/breadcrumbs/ltr-middle.png)
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -133,17 +133,18 @@ class ZipFileReader(object):
 
     for name in self._zipfile.namelist():
       self._extractname(name, path)
 
 log = logging.getLogger()
 
 def isURL(thing):
   """Return True if |thing| looks like a URL."""
-  return urlparse(thing).scheme != ''
+  # We want to download URLs like http://... but not Windows paths like c:\...
+  return len(urlparse(thing).scheme) >= 2
 
 def addCommonOptions(parser, defaults={}):
   parser.add_option("--xre-path",
                     action = "store", type = "string", dest = "xrePath",
                     # individual scripts will set a sane default
                     default = None,
                     help = "absolute path to directory containing XRE (probably xulrunner)")
   if 'SYMBOLS_PATH' not in defaults:
@@ -279,17 +280,17 @@ def getDebuggerInfo(directory, debugger,
       "interactive" : getDebuggerInfo("interactive", False),
       "args": getDebuggerInfo("args", "").split()
     }
 
     if debuggerArgs:
       debuggerInfo["args"] = debuggerArgs.split()
     if debuggerInteractive:
       debuggerInfo["interactive"] = debuggerInteractive
-  
+
   return debuggerInfo
 
 
 def dumpLeakLog(leakLogFile, filter = False):
   """Process the leak log, without parsing it.
 
   Use this function if you want the raw log only.
   Use it preferably with the |XPCOM_MEM_LEAK_LOG| environment variable.
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -34,48 +34,43 @@
 #
 # ***** END LICENSE BLOCK *****
 
 mk_add_options MOZ_UNIFY_BDATE=1
 
 mk_add_options MOZ_POSTFLIGHT_ALL+=build/macosx/universal/flight.mk
 
 # Note, the version (10) is used by libffi's configure.
-ac_add_app_options ppc  --target=powerpc-apple-darwin10
 ac_add_app_options i386 --target=i386-apple-darwin10
 ac_add_app_options x86_64 --target=x86_64-apple-darwin10
 
-ac_add_app_options ppc --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
 ac_add_app_options i386 --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
 ac_add_app_options x86_64 --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk
 
 # $MOZ_BUILD_APP is only defined when sourced by configure.  That's not a
 # problem, because the variables it affects only need to be set for
 # configure.
 if test -n "$MOZ_BUILD_APP" ; then
-if test "$MOZ_BUILD_APP" = "i386" -o  "$MOZ_BUILD_APP" = "ppc" -o "$MOZ_BUILD_APP" = "x86_64"; then
+if test "$MOZ_BUILD_APP" = "i386" -o "$MOZ_BUILD_APP" = "x86_64"; then
   TARGET_CPU=$MOZ_BUILD_APP
 
   if test -z "$CC" ; then
      CC=gcc-4.2
   fi
 
   if test -z "$CXX" ; then
      CXX=g++-4.2
   fi
 
   # $HOST_CXX is presently unused.  $HOST_CC will only be used during a cross
   # compile.
   HOST_CC=$CC
   HOST_CXX=$CXX
 
   NATIVE_CPU=`$topsrcdir/build/autoconf/config.guess | cut -f1 -d-`
-  if test "$NATIVE_CPU" = "powerpc" ; then
-    NATIVE_CPU=ppc
-  fi
 
   # It's not strictly necessary to specify -arch during native builds, but it
   # makes the merged about:buildconfig easier to follow, and it reduces
   # conditionalized differences between builds.
   CC="$CC -arch $TARGET_CPU"
   CXX="$CXX -arch $TARGET_CPU"
 
   # These must be set for cross builds, and don't hurt straight builds.
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -261,16 +261,20 @@ class DeviceManagerSUT(DeviceManager):
   # returns:
   #  success: True
   #  failure: False
   def pushFile(self, localname, destname):
     if (os.name == "nt"):
       destname = destname.replace('\\', '/')
 
     if (self.debug >= 3): print "in push file with: " + localname + ", and: " + destname
+    if (self.dirExists(destname)):
+      if (not destname.endswith('/')):
+        destname = destname + '/'
+      destname = destname + os.path.basename(localname)
     if (self.validateFile(destname, localname) == True):
       if (self.debug >= 3): print "files are validated"
       return True
 
     if self.mkDirs(destname) == None:
       print "unable to make dirs: " + destname
       return False
 
@@ -347,17 +351,20 @@ class DeviceManagerSUT(DeviceManager):
   #  success: remoteDir
   #  failure: None
   def pushDir(self, localDir, remoteDir):
     if (self.debug >= 2): print "pushing directory: %s to %s" % (localDir, remoteDir)
     for root, dirs, files in os.walk(localDir):
       parts = root.split(localDir)
       for file in files:
         remoteRoot = remoteDir + '/' + parts[1]
-        remoteName = remoteRoot + '/' + file
+        if (remoteRoot.endswith('/')):
+          remoteName = remoteRoot + file
+        else:
+          remoteName = remoteRoot + '/' + file
         if (parts[1] == ""): remoteRoot = remoteDir
         if (self.pushFile(os.path.join(root, file), remoteName) == False):
           # retry once
           self.removeFile(remoteName)
           if (self.pushFile(os.path.join(root, file), remoteName) == False):
             return None
     return remoteDir
 
--- a/build/unix/Makefile.in
+++ b/build/unix/Makefile.in
@@ -46,20 +46,16 @@ VPATH		= @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE       = build
 
 ifdef USE_ELF_HACK
 DIRS = elfhack
 endif
 
-ifdef ENABLE_TESTS
-  ifeq (,$(filter WINNT OS2,$(OS_ARCH)))
-    DIRS += test
-  endif # WIN
-endif # ENABLE_TESTS
+TEST_DIRS = test
 
 include $(topsrcdir)/config/rules.mk
 
 libs:: $(srcdir)/run-mozilla.sh
 	$(INSTALL) $< $(DIST)/bin
 
 # EOF
--- a/configure.in
+++ b/configure.in
@@ -2666,18 +2666,18 @@ ia64*-hpux*)
             AC_MSG_ERROR([You are targeting i386 but using the 64-bit compiler.])
         fi
 
         if test $_MSC_VER -ge 1400; then
             LDFLAGS="$LDFLAGS -SAFESEH"
         fi
 
         if test -n "$GNU_CC"; then
-            CFLAGS="$CFLAGS -mstackrealign"
-            CXXFLAGS="$CXXFLAGS -mstackrealign"
+            CFLAGS="$CFLAGS -mstackrealign -fno-keep-inline-dllexport"
+            CXXFLAGS="$CXXFLAGS -mstackrealign -fno-keep-inline-dllexport"
         else
             AC_DEFINE(HAVE_STDCALL)
         fi
 
         MOZ_CHECK_HEADERS(mmintrin.h)
     	AC_DEFINE(_X86_)
 	;;
     x86_64-*)
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -75,29 +75,26 @@ nsContentCID.h \
 nsCopySupport.h \
 nsContentCreatorFunctions.h \
 nsDOMFile.h \
 nsLineBreaker.h \
 nsReferencedElement.h \
 nsTreeSanitizer.h \
 nsXMLNameSpaceMap.h \
 nsDOMEventTargetWrapperCache.h \
+nsIXFormsUtilityService.h \
 $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
 		Element.h \
 		FromParser.h \
 		$(NULL)
 
-ifndef DISABLE_XFORMS_HOOKS
-EXPORTS += nsIXFormsUtilityService.h
-endif
-
 SDK_XPIDLSRCS   = \
 		nsISelection.idl  \
 		$(NULL)
 
 XPIDLSRCS	= \
 		nsIContentPolicy.idl        \
 		nsIDocumentEncoder.idl      \
 		nsIDOMFile.idl \
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -46,16 +46,19 @@
 #include "nsJSUtils.h"
 #include "nsNetUtil.h"
 #include "nsScriptLoader.h"
 #include "nsIJSContextStack.h"
 #include "nsIXULRuntime.h"
 #include "nsIScriptError.h"
 #include "nsIConsoleService.h"
 #include "nsIProtocolHandler.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsIJSRuntimeService.h"
+#include "xpcpublic.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 static bool
 IsChromeProcess()
 {
@@ -803,16 +806,68 @@ nsFrameScriptExecutor::LoadFrameScriptIn
         JSPRINCIPALS_DROP(mCx, jsprin);
       }
     } 
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
   }
 }
 
+bool
+nsFrameScriptExecutor::InitTabChildGlobalInternal(nsISupports* aScope)
+{
+  
+  nsCOMPtr<nsIJSRuntimeService> runtimeSvc = 
+    do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
+  NS_ENSURE_TRUE(runtimeSvc, false);
+
+  JSRuntime* rt = nsnull;
+  runtimeSvc->GetRuntime(&rt);
+  NS_ENSURE_TRUE(rt, false);
+
+  JSContext* cx = JS_NewContext(rt, 8192);
+  NS_ENSURE_TRUE(cx, false);
+
+  mCx = cx;
+
+  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
+
+  JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
+
+  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
+  JS_SetVersion(cx, JSVERSION_LATEST);
+  JS_SetErrorReporter(cx, ContentScriptErrorReporter);
+
+  xpc_LocalizeContext(cx);
+
+  JSAutoRequest ar(cx);
+  nsIXPConnect* xpc = nsContentUtils::XPConnect();
+  const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
+                         nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
+
+  
+  JS_SetContextPrivate(cx, aScope);
+
+  nsresult rv =
+    xpc->InitClassesWithNewWrappedGlobal(cx, aScope,
+                                         NS_GET_IID(nsISupports),
+                                         mPrincipal, nsnull,
+                                         flags, getter_AddRefs(mGlobal));
+  NS_ENSURE_SUCCESS(rv, false);
+
+    
+  JSObject* global = nsnull;
+  rv = mGlobal->GetJSObject(&global);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  JS_SetGlobalObject(cx, global);
+  DidCreateCx();
+  return true;
+}
+
 // static
 void
 nsFrameScriptExecutor::Traverse(nsFrameScriptExecutor *tmp,
                                 nsCycleCollectionTraversalCallback &cb)
 {
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGlobal)
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCx");
   nsContentUtils::XPConnect()->NoteJSContext(tmp->mCx, cb);
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -226,16 +226,17 @@ protected:
                             mDelayedCxDestroy(false)
   { MOZ_COUNT_CTOR(nsFrameScriptExecutor); }
   ~nsFrameScriptExecutor()
   { MOZ_COUNT_DTOR(nsFrameScriptExecutor); }
   void DidCreateCx();
   // Call this when you want to destroy mCx.
   void DestroyCx();
   void LoadFrameScriptInternal(const nsAString& aURL);
+  bool InitTabChildGlobalInternal(nsISupports* aScope);
   static void Traverse(nsFrameScriptExecutor *tmp,
                        nsCycleCollectionTraversalCallback &cb);
   nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
   JSContext* mCx;
   PRUint32 mCxStackRefCnt;
   bool mDelayedCxDestroy;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   static nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>* sCachedScripts;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -699,17 +699,16 @@ GK_ATOM(onmousedown, "onmousedown")
 GK_ATOM(onmouseenter, "onmouseenter")
 GK_ATOM(onmouseleave, "onmouseleave")
 GK_ATOM(onmousemove, "onmousemove")
 GK_ATOM(onmouseout, "onmouseout")
 GK_ATOM(onmouseover, "onmouseover")
 GK_ATOM(onMozMouseHittest, "onMozMouseHittest")
 GK_ATOM(onmouseup, "onmouseup")
 GK_ATOM(onMozAfterPaint, "onMozAfterPaint")
-GK_ATOM(onMozBeforePaint, "onMozBeforePaint")
 GK_ATOM(onmozfullscreenchange, "onmozfullscreenchange")
 GK_ATOM(onmozfullscreenerror, "onmozfullscreenerror")
 GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
 GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
 GK_ATOM(ononline, "ononline")
 GK_ATOM(onoffline, "onoffline")
 GK_ATOM(onopen, "onopen")
 GK_ATOM(onoverflow, "onoverflow")
@@ -1667,29 +1666,26 @@ GK_ATOM(vectorproduct_, "vectorproduct")
 GK_ATOM(vector_, "vector")
 GK_ATOM(verythickmathspace_, "verythickmathspace")
 GK_ATOM(verythinmathspace_, "verythinmathspace")
 GK_ATOM(veryverythickmathspace_, "veryverythickmathspace")
 GK_ATOM(veryverythinmathspace_, "veryverythinmathspace")
 GK_ATOM(voffset_, "voffset")
 GK_ATOM(xref_, "xref")
 GK_ATOM(math, "math") // the only one without an underscore
-
-#ifndef DISABLE_XFORMS_HOOKS
 GK_ATOM(avg, "avg")
 GK_ATOM(booleanFromString, "boolean-from-string")
 GK_ATOM(countNonEmpty, "count-non-empty")
 GK_ATOM(daysFromDate, "days-from-date")
 GK_ATOM(init, "init")
 GK_ATOM(instance, "instance")
 GK_ATOM(months, "months")
 GK_ATOM(now, "now")
 GK_ATOM(seconds, "seconds")
 GK_ATOM(secondsFromDateTime, "seconds-from-dateTime")
-#endif
 
 // Simple gestures support
 GK_ATOM(onMozSwipeGesture, "onMozSwipeGesture")
 GK_ATOM(onMozMagnifyGestureStart, "onMozMagnifyGestureStart")
 GK_ATOM(onMozMagnifyGestureUpdate, "onMozMagnifyGestureUpdate")
 GK_ATOM(onMozMagnifyGesture, "onMozMagnifyGesture")
 GK_ATOM(onMozRotateGestureStart, "onMozRotateGestureStart")
 GK_ATOM(onMozRotateGestureUpdate, "onMozRotateGestureUpdate")
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -288,63 +288,20 @@ nsInProcessTabChildGlobal::PreHandleEven
 #endif
 
   return NS_OK;
 }
 
 nsresult
 nsInProcessTabChildGlobal::InitTabChildGlobal()
 {
-  nsCOMPtr<nsIJSRuntimeService> runtimeSvc = 
-    do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
-  NS_ENSURE_STATE(runtimeSvc);
-
-  JSRuntime* rt = nsnull;
-  runtimeSvc->GetRuntime(&rt);
-  NS_ENSURE_STATE(rt);
-
-  JSContext* cx = JS_NewContext(rt, 8192);
-  NS_ENSURE_STATE(cx);
-
-  mCx = cx;
-
-  nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
-  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
-
-  JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
-
-  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
-  JS_SetVersion(cx, JSVERSION_LATEST);
-  JS_SetErrorReporter(cx, ContentScriptErrorReporter);
-
-  xpc_LocalizeContext(cx);
-
-  JSAutoRequest ar(cx);
-  nsIXPConnect* xpc = nsContentUtils::XPConnect();
-  const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
-                         /*nsIXPConnect::OMIT_COMPONENTS_OBJECT ?  |*/
-                         nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
 
   nsISupports* scopeSupports =
     NS_ISUPPORTS_CAST(nsIDOMEventTarget*, this);
-  JS_SetContextPrivate(cx, scopeSupports);
-
-  nsresult rv =
-    xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
-                                         NS_GET_IID(nsISupports),
-                                         GetPrincipal(), nsnull,
-                                         flags, getter_AddRefs(mGlobal));
-  NS_ENSURE_SUCCESS(rv, false);
-
-  JSObject* global = nsnull;
-  rv = mGlobal->GetJSObject(&global);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  JS_SetGlobalObject(cx, global);
-  DidCreateCx();
+  NS_ENSURE_STATE(InitTabChildGlobalInternal(scopeSupports));
   return NS_OK;
 }
 
 class nsAsyncScriptLoad : public nsRunnable
 {
 public:
   nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL)
   : mTabChild(aTabChild), mURL(aURL) {}
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2486,16 +2486,26 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
       if (!charset.IsEmpty()) {
         nsCAutoString specifiedCharset;
         bool haveCharset;
         PRInt32 charsetStart, charsetEnd;
         rv = NS_ExtractCharsetFromContentType(contentType, specifiedCharset,
                                               &haveCharset, &charsetStart,
                                               &charsetEnd);
         if (NS_SUCCEEDED(rv)) {
+          // special case: the extracted charset is quoted with single quotes
+          // -- for the purpose of preserving what was set we want to handle
+          // them as delimiters (although they aren't really)
+          if (specifiedCharset.Length() >= 2 &&
+              specifiedCharset.First() == '\'' &&
+              specifiedCharset.Last() == '\'') {
+            specifiedCharset = Substring(specifiedCharset, 1,
+                                         specifiedCharset.Length() - 2);
+          }
+
           // If the content-type the page set already has a charset parameter,
           // and it's the same charset, up to case, as |charset|, just send the
           // page-set content-type header.  Apparently at least
           // google-web-toolkit is broken and relies on the exact case of its
           // charset parameter, which makes things break if we use |charset|
           // (which is always a fully resolved charset per our charset alias
           // table, hence might be differently cased).
           if (!specifiedCharset.Equals(charset,
--- a/content/events/public/nsEventNameList.h
+++ b/content/events/public/nsEventNameList.h
@@ -676,20 +676,16 @@ NON_IDL_EVENT(repeatEvent,
 NON_IDL_EVENT(MozAudioAvailable,
               NS_MOZAUDIOAVAILABLE,
               EventNameType_None,
               NS_EVENT_NULL)
 NON_IDL_EVENT(MozAfterPaint,
               NS_AFTERPAINT,
               EventNameType_None,
               NS_EVENT)
-NON_IDL_EVENT(MozBeforePaint,
-              NS_BEFOREPAINT,
-              EventNameType_None,
-              NS_EVENT_NULL)
 
 NON_IDL_EVENT(MozScrolledAreaChanged,
               NS_SCROLLEDAREACHANGED,
               EventNameType_None,
               NS_SCROLLAREA_EVENT)
 
 // Simple gesture events
 NON_IDL_EVENT(MozSwipeGesture,
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -88,17 +88,16 @@ static const char* const sEventNames[] =
   "beginEvent", "endEvent", "repeatEvent",
 #ifdef MOZ_MEDIA
   "loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause",
   "loadedmetadata", "loadeddata", "waiting", "playing", "canplay",
   "canplaythrough", "seeking", "seeked", "timeupdate", "ended", "ratechange",
   "durationchange", "volumechange", "MozAudioAvailable",
 #endif // MOZ_MEDIA
   "MozAfterPaint",
-  "MozBeforePaint",
   "MozBeforeResize",
   "mozfullscreenchange",
   "mozfullscreenerror",
   "MozSwipeGesture",
   "MozMagnifyGestureStart",
   "MozMagnifyGestureUpdate",
   "MozMagnifyGesture",
   "MozRotateGestureStart",
@@ -1338,18 +1337,16 @@ const char* nsDOMEvent::GetEventName(PRU
     return sEventNames[eDOMEvents_durationchange];
   case NS_VOLUMECHANGE:
     return sEventNames[eDOMEvents_volumechange];
   case NS_MOZAUDIOAVAILABLE:
     return sEventNames[eDOMEvents_mozaudioavailable];
 #endif
   case NS_AFTERPAINT:
     return sEventNames[eDOMEvents_afterpaint];
-  case NS_BEFOREPAINT:
-    return sEventNames[eDOMEvents_beforepaint];
   case NS_BEFORERESIZE_EVENT:
     return sEventNames[eDOMEvents_beforeresize];
   case NS_SIMPLE_GESTURE_SWIPE:
     return sEventNames[eDOMEvents_MozSwipeGesture];
   case NS_SIMPLE_GESTURE_MAGNIFY_START:
     return sEventNames[eDOMEvents_MozMagnifyGestureStart];
   case NS_SIMPLE_GESTURE_MAGNIFY_UPDATE:
     return sEventNames[eDOMEvents_MozMagnifyGestureUpdate];
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -171,17 +171,16 @@ public:
     eDOMEvents_timeupdate,
     eDOMEvents_ended,
     eDOMEvents_ratechange,
     eDOMEvents_durationchange,
     eDOMEvents_volumechange,
     eDOMEvents_mozaudioavailable,
 #endif
     eDOMEvents_afterpaint,
-    eDOMEvents_beforepaint,
     eDOMEvents_beforeresize,
     eDOMEvents_mozfullscreenchange,
     eDOMEvents_mozfullscreenerror,
     eDOMEvents_MozSwipeGesture,
     eDOMEvents_MozMagnifyGestureStart,
     eDOMEvents_MozMagnifyGestureUpdate,
     eDOMEvents_MozMagnifyGesture,
     eDOMEvents_MozRotateGestureStart,
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1966,16 +1966,20 @@ nsresult nsHTMLMediaElement::InitializeD
 
   return FinishDecoderSetup(decoder);
 }
 
 nsresult nsHTMLMediaElement::FinishDecoderSetup(nsMediaDecoder* aDecoder)
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc set up");
 
+  nsCAutoString src;
+  GetCurrentSpec(src);
+  printf("*** nsHTMLElement::FinishDecoderSetup() mDecoder=%p src=%s\n",
+         aDecoder, src.get());
   mDecoder = aDecoder;
   AddMediaElementToURITable();
 
   // Force a same-origin check before allowing events for this media resource.
   mMediaSecurityVerified = false;
 
   // The new stream has not been suspended by us.
   mPausedForInactiveDocument = false;
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -743,17 +743,21 @@ nsHTMLDocument::StartDocumentLoad(const 
   }
 
   nsCOMPtr<nsICachingChannel> cachingChan = do_QueryInterface(aChannel);
 
   if (needsParser) {
     if (loadAsHtml5) {
       mParser = nsHtml5Module::NewHtml5Parser();
       if (plainText) {
-        mParser->MarkAsNotScriptCreated("plain-text");
+        if (viewSource) {
+          mParser->MarkAsNotScriptCreated("view-source-plain");
+        } else {
+          mParser->MarkAsNotScriptCreated("plain-text");
+        }
       } else if (viewSource && !contentType.EqualsLiteral("text/html")) {
         mParser->MarkAsNotScriptCreated("view-source-xml");
       } else {
         mParser->MarkAsNotScriptCreated(aCommand);
       }
     } else {
       mParser = do_CreateInstance(kCParserCID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -1288,22 +1292,20 @@ nsHTMLDocument::GetURL(nsAString& aURL)
   }
 
   CopyUTF8toUTF16(str, aURL);
 
   return NS_OK;
 }
 
 nsIContent*
-nsHTMLDocument::GetBody(nsresult *aResult)
+nsHTMLDocument::GetBody()
 {
   Element* body = GetBodyElement();
 
-  *aResult = NS_OK;
-
   if (body) {
     // There is a body element, return that as the body.
     return body;
   }
 
   // The document is most likely a frameset document so look for the
   // outer most frameset element
   nsRefPtr<nsContentList> nodeList =
@@ -1312,20 +1314,19 @@ nsHTMLDocument::GetBody(nsresult *aResul
   return nodeList->GetNodeAt(0);
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
 {
   *aBody = nsnull;
 
-  nsresult rv;
-  nsIContent *body = GetBody(&rv);
-
-  return body ? CallQueryInterface(body, aBody) : rv;
+  nsIContent *body = GetBody();
+
+  return body ? CallQueryInterface(body, aBody) : NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
 {
   nsCOMPtr<nsIContent> newBody = do_QueryInterface(aBody);
   Element* root = GetRootElement();
 
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -130,17 +130,18 @@ public:
    * Returns the result of document.all[aID] which can either be a node
    * or a nodelist depending on if there are multiple nodes with the same
    * id.
    */
   nsISupports *GetDocumentAllResult(const nsAString& aID,
                                     nsWrapperCache **aCache,
                                     nsresult *aResult);
 
-  nsIContent *GetBody(nsresult *aResult);
+  nsIContent *GetBody();
+  Element *GetHead() { return GetHeadElement(); }
   already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
   {
     return NS_GetFuncStringContentList(this, MatchNameAttribute, nsnull,
                                        UseExistingNameString, aName);
   }
 
 
   virtual nsresult ResolveName(const nsAString& aName,
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -446,32 +446,39 @@ void nsBuiltinDecoder::MetadataLoaded(PR
   // to fulfill a seek, otherwise we'll get multiple loadedfirstframe events.
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   bool resourceIsLoaded = !mResourceLoaded && mStream &&
     mStream->IsDataCachedToEndOfStream(mDecoderPosition);
   if (mElement && notifyElement) {
     mElement->FirstFrameLoaded(resourceIsLoaded);
   }
 
+  // This can run cache callbacks.
+  mStream->EnsureCacheUpToDate();
+
   // The element can run javascript via events
   // before reaching here, so only change the
   // state if we're still set to the original
   // loading state.
   if (mPlayState == PLAY_STATE_LOADING) {
     if (mRequestedSeekTime >= 0.0) {
       ChangeState(PLAY_STATE_SEEKING);
     }
     else {
       ChangeState(mNextState);
     }
   }
 
   if (resourceIsLoaded) {
     ResourceLoaded();
   }
+
+  // Run NotifySuspendedStatusChanged now to give us a chance to notice
+  // that autoplay should run.
+  NotifySuspendedStatusChanged();
 }
 
 void nsBuiltinDecoder::ResourceLoaded()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
 
   // Don't handle ResourceLoaded if we are shutting down, or if
   // we need to ignore progress data due to seeking (in the case
@@ -632,17 +639,19 @@ void nsBuiltinDecoder::UpdatePlaybackRat
   mStream->SetPlaybackRate(rate);
 }
 
 void nsBuiltinDecoder::NotifySuspendedStatusChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (!mStream)
     return;
-  if (mStream->IsSuspendedByCache() && mElement) {
+  bool suspended = mStream->IsSuspendedByCache();
+  printf("*** nsBuiltinDecoder::NotifySuspendedStatusChanged(%p), suspended=%d\n", this, suspended);
+  if (suspended && mElement) {
     // if this is an autoplay element, we need to kick off its autoplaying
     // now so we consume data and hopefully free up cache space
     mElement->NotifyAutoplayDataReady();
   }
 }
 
 void nsBuiltinDecoder::NotifyBytesDownloaded()
 {
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -1346,16 +1346,17 @@ nsMediaCache::Update()
     nsresult rv = NS_OK;
     switch (actions[i]) {
     case SEEK:
       LOG(PR_LOG_DEBUG, ("Stream %p CacheSeek to %lld (resume=%d)", stream,
            (long long)stream->mChannelOffset, stream->mCacheSuspended));
       rv = stream->mClient->CacheClientSeek(stream->mChannelOffset,
                                             stream->mCacheSuspended);
       stream->mCacheSuspended = false;
+      stream->mChannelEnded = false;
       break;
 
     case RESUME:
       LOG(PR_LOG_DEBUG, ("Stream %p Resumed", stream));
       rv = stream->mClient->CacheClientResume();
       stream->mCacheSuspended = false;
       break;
 
@@ -1364,16 +1365,18 @@ nsMediaCache::Update()
       rv = stream->mClient->CacheClientSuspend();
       stream->mCacheSuspended = true;
       break;
 
     default:
       break;
     }
 
+    stream->mHasHadUpdate = true;
+
     if (NS_FAILED(rv)) {
       // Close the streams that failed due to error. This will cause all
       // client Read and Seek operations on those streams to fail. Blocked
       // Reads will also be woken up.
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
       stream->CloseInternal(mon);
     }
   }
@@ -1847,16 +1850,18 @@ nsMediaCacheStream::NotifyDataEnded(nsre
         stream->mStreamLength = mChannelOffset;
       }
       NS_ASSERTION(!stream->mDidNotifyDataEnded, "Stream already ended!");
       stream->mDidNotifyDataEnded = true;
       stream->mNotifyDataEndedStatus = aStatus;
       stream->mClient->CacheClientNotifyDataEnded(aStatus);
     }
   }
+
+  mChannelEnded = true;
 }
 
 nsMediaCacheStream::~nsMediaCacheStream()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   NS_ASSERTION(!mPinCount, "Unbalanced Pin");
 
   if (gMediaCache) {
@@ -1880,30 +1885,50 @@ nsMediaCacheStream::SetSeekable(bool aIs
 
 bool
 nsMediaCacheStream::IsSeekable()
 {
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   return mIsSeekable;
 }
 
+bool
+nsMediaCacheStream::AreAllStreamsForResourceSuspended()
+{
+  ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
+  nsMediaCache::ResourceStreamIterator iter(mResourceID);
+  while (nsMediaCacheStream* stream = iter.Next()) {
+    if (!stream->mCacheSuspended && !stream->mChannelEnded)
+      return false;
+  }
+  return true;
+}
+
 void
 nsMediaCacheStream::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   CloseInternal(mon);
   // Queue an Update since we may have created more free space. Don't do
   // it from CloseInternal since that gets called by Update() itself
   // sometimes, and we try to not to queue updates from Update().
   gMediaCache->QueueUpdate();
 }
 
 void
+nsMediaCacheStream::EnsureCacheUpdate()
+{
+  if (mHasHadUpdate)
+    return;
+  gMediaCache->Update();
+}
+
+void
 nsMediaCacheStream::CloseInternal(ReentrantMonitorAutoEnter& aReentrantMonitor)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   if (mClosed)
     return;
   mClosed = true;
   gMediaCache->ReleaseStreamBlocks(this);
@@ -2285,16 +2310,17 @@ nsMediaCacheStream::InitAsClone(nsMediaC
 
   mPrincipal = aOriginal->mPrincipal;
   mStreamLength = aOriginal->mStreamLength;
   mIsSeekable = aOriginal->mIsSeekable;
 
   // Cloned streams are initially suspended, since there is no channel open
   // initially for a clone.
   mCacheSuspended = true;
+  mChannelEnded = true;
 
   if (aOriginal->mDidNotifyDataEnded) {
     mNotifyDataEndedStatus = aOriginal->mNotifyDataEndedStatus;
     mDidNotifyDataEnded = true;
     mClient->CacheClientNotifyDataEnded(mNotifyDataEndedStatus);
   }
 
   for (PRUint32 i = 0; i < aOriginal->mBlocks.Length(); ++i) {
--- a/content/media/nsMediaCache.h
+++ b/content/media/nsMediaCache.h
@@ -222,18 +222,19 @@ public:
     MODE_METADATA,
     MODE_PLAYBACK
   };
 
   // aClient provides the underlying transport that cache will use to read
   // data for this stream.
   nsMediaCacheStream(nsMediaChannelStream* aClient)
     : mClient(aClient), mResourceID(0), mInitialized(false),
+      mHasHadUpdate(false),
       mIsSeekable(false), mCacheSuspended(false),
-      mDidNotifyDataEnded(false),
+      mChannelEnded(false), mDidNotifyDataEnded(false),
       mUsingNullPrincipal(false),
       mChannelOffset(0), mStreamLength(-1),  
       mStreamOffset(0), mPlaybackBytesPerSecond(10000),
       mPinCount(0), mCurrentMode(MODE_PLAYBACK),
       mMetadataInPartialBlockBuffer(false),
       mClosed(false) {}
   ~nsMediaCacheStream();
 
@@ -258,16 +259,21 @@ public:
   void SetSeekable(bool aIsSeekable);
   // This must be called (and return) before the nsMediaChannelStream
   // used to create this nsMediaCacheStream is deleted.
   void Close();
   // This returns true when the stream has been closed
   bool IsClosed() const { return mClosed; }
   // Get the principal for this stream.
   nsIPrincipal* GetCurrentPrincipal() { return mPrincipal; }
+  // Ensure a global media cache update has run with this stream present.
+  // This ensures the cache has had a chance to suspend or unsuspend this stream.
+  // Called only on main thread. This can change the state of streams, fire
+  // notifications, etc.
+  void EnsureCacheUpdate();
 
   // These callbacks are called on the main thread by the client
   // when data has been received via the channel.
   // Tells the cache what the server said the data length is going to be.
   // The actual data length may be greater (we receive more data than
   // specified) or smaller (the stream ends before we reach the given
   // length), because servers can lie. The server's reported data length
   // *and* the actual data length can even vary over time because a
@@ -341,16 +347,20 @@ public:
   // This is the client's estimate of the playback rate assuming
   // the media plays continuously. The cache can't guess this itself
   // because it doesn't know when the decoder was paused, buffering, etc.
   // Do not pass zero.
   void SetPlaybackRate(PRUint32 aBytesPerSecond);
   // Returns the last set value of SetSeekable.
   bool IsSeekable();
 
+  // Returns true when all streams for this resource are suspended or their
+  // channel has ended.
+  bool AreAllStreamsForResourceSuspended();
+
   // These methods must be called on a different thread from the main
   // thread. They should always be called on the same thread for a given
   // stream.
   // This can fail when aWhence is NS_SEEK_END and no stream length
   // is known.
   nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
   PRInt64 Tell();
   // *aBytes gets the number of bytes that were actually read. This can
@@ -442,26 +452,31 @@ private:
   nsMediaChannelStream*  mClient;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   // This is a unique ID representing the resource we're loading.
   // All streams with the same mResourceID are loading the same
   // underlying resource and should share data.
   PRInt64                mResourceID;
   // Set to true when Init or InitAsClone has been called
   bool                   mInitialized;
+  // Set to true when nsMediaCache::Update() has finished while this stream
+  // was present.
+  bool                   mHasHadUpdate;
 
   // The following fields are protected by the cache's monitor but are
   // only written on the main thread. 
 
   // The last reported seekability state for the underlying channel
   bool mIsSeekable;
   // True if the cache has suspended our channel because the cache is
   // full and the priority of the data that would be received is lower
   // than the priority of the data already in the cache
   bool mCacheSuspended;
+  // True if the channel ended and we haven't seeked it again.
+  bool mChannelEnded;
   // True if CacheClientNotifyDataEnded has been called for this stream.
   bool mDidNotifyDataEnded;
   // True if mPrincipal is a null principal because we saw data from
   // multiple origins
   bool mUsingNullPrincipal;
   // The offset where the next data from the channel will arrive
   PRInt64      mChannelOffset;
   // The reported or discovered length of the data, or -1 if nothing is
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/nsMediaStream.cpp
@@ -69,17 +69,16 @@ using namespace mozilla;
 
 nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
     nsIChannel* aChannel, nsIURI* aURI)
   : nsMediaStream(aDecoder, aChannel, aURI),
     mOffset(0), mSuspendCount(0),
     mReopenOnError(false), mIgnoreClose(false),
     mCacheStream(this),
     mLock("nsMediaChannelStream.mLock"),
-    mCacheSuspendCount(0),
     mIgnoreResume(false)
 {
 }
 
 nsMediaChannelStream::~nsMediaChannelStream()
 {
   if (mListener) {
     // Kill its reference to us since we're going away
@@ -542,18 +541,19 @@ nsMediaStream* nsMediaChannelStream::Clo
   if (stream) {
     // Initially the clone is treated as suspended by the cache, because
     // we don't have a channel. If the cache needs to read data from the clone
     // it will call CacheClientResume (or CacheClientSeek with aResume true)
     // which will recreate the channel. This way, if all of the media data
     // is already in the cache we don't create an unneccesary HTTP channel
     // and perform a useless HTTP transaction.
     stream->mSuspendCount = 1;
-    stream->mCacheSuspendCount = 1;
     stream->mCacheStream.InitAsClone(&mCacheStream);
+    stream->mChannelStatistics = mChannelStatistics;
+    stream->mChannelStatistics.Stop(TimeStamp::Now());
   }
   return stream;
 }
 
 void nsMediaChannelStream::CloseChannel()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
@@ -746,72 +746,66 @@ public:
 private:
   nsRefPtr<nsMediaDecoder> mDecoder;
   nsresult                 mStatus;
 };
 
 void
 nsMediaChannelStream::CacheClientNotifyDataEnded(nsresult aStatus)
 {
+  printf("*** nsMediaChannelStream::CacheClientNotifyDataEnded() mDecoder=%p\n", mDecoder);
+
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   // NOTE: this can be called with the media cache lock held, so don't
   // block or do anything which might try to acquire a lock!
 
   nsCOMPtr<nsIRunnable> event = new DataEnded(mDecoder, aStatus);
   NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
 }
 
 nsresult
 nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, bool aResume)
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
+  printf("*** nsMediaChannelStream::CacheClientSeek() mDecoder=%p\n", mDecoder);
+
   CloseChannel();
 
   if (aResume) {
     NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
     // No need to mess with the channel, since we're making a new one
     --mSuspendCount;
-    {
-      MutexAutoLock lock(mLock);
-      NS_ASSERTION(mCacheSuspendCount > 0, "CacheClientSeek(aResume=true) without previous CacheClientSuspend!");
-      --mCacheSuspendCount;
-    }
   }
 
   nsresult rv = RecreateChannel();
   if (NS_FAILED(rv))
     return rv;
 
   mOffset = aOffset;
   return OpenChannel(nsnull);
 }
 
 nsresult
 nsMediaChannelStream::CacheClientSuspend()
 {
-  {
-    MutexAutoLock lock(mLock);
-    ++mCacheSuspendCount;
-  }
+  printf("*** nsMediaChannelStream::CacheClientSuspend() mDecoder=%p\n", mDecoder);
+
   Suspend(false);
 
   mDecoder->NotifySuspendedStatusChanged();
   return NS_OK;
 }
 
 nsresult
 nsMediaChannelStream::CacheClientResume()
 {
+  printf("*** nsMediaChannelStream::CacheClientResume() mDecoder=%p\n", mDecoder);
+
   Resume();
-  {
-    MutexAutoLock lock(mLock);
-    NS_ASSERTION(mCacheSuspendCount > 0, "CacheClientResume without previous CacheClientSuspend!");
-    --mCacheSuspendCount;
-  }
 
   mDecoder->NotifySuspendedStatusChanged();
   return NS_OK;
 }
 
 PRInt64
 nsMediaChannelStream::GetNextCachedData(PRInt64 aOffset)
 {
@@ -825,21 +819,26 @@ nsMediaChannelStream::GetCachedDataEnd(P
 }
 
 bool
 nsMediaChannelStream::IsDataCachedToEndOfStream(PRInt64 aOffset)
 {
   return mCacheStream.IsDataCachedToEndOfStream(aOffset);
 }
 
+void
+nsMediaChannelStream::EnsureCacheUpToDate()
+{
+  mCacheStream.EnsureCacheUpdate();
+}
+
 bool
 nsMediaChannelStream::IsSuspendedByCache()
 {
-  MutexAutoLock lock(mLock);
-  return mCacheSuspendCount > 0;
+  return mCacheStream.AreAllStreamsForResourceSuspended();
 }
 
 bool
 nsMediaChannelStream::IsSuspended()
 {
   MutexAutoLock lock(mLock);
   return mSuspendCount > 0;
 }
--- a/content/media/nsMediaStream.h
+++ b/content/media/nsMediaStream.h
@@ -231,16 +231,19 @@ public:
   // is fine for a no-op cancel.
   virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset) = 0;
   // Report the current offset in bytes from the start of the stream.
   virtual PRInt64 Tell() = 0;
   // Moves any existing channel loads into the background, so that they don't
   // block the load event. Any new loads initiated (for example to seek)
   // will also be in the background.
   void MoveLoadsToBackground();
+  // Ensures that the value returned by IsSuspendedByCache below is up to date
+  // (i.e. the cache has examined this stream at least once).
+  virtual void EnsureCacheUpToDate() {}
 
   // These can be called on any thread.
   // Cached blocks associated with this stream will not be evicted
   // while the stream is pinned.
   virtual void Pin() = 0;
   virtual void Unpin() = 0;
   // Get the estimated download rate in bytes per second (assuming no
   // pausing of the channel is requested by Gecko).
@@ -262,16 +265,18 @@ public:
   // Returns true if all the data from aOffset to the end of the stream
   // is in cache. If the end of the stream is not known, we return false.
   virtual bool IsDataCachedToEndOfStream(PRInt64 aOffset) = 0;
   // Returns true if this stream is suspended by the cache because the
   // cache is full. If true then the decoder should try to start consuming
   // data, otherwise we may not be able to make progress.
   // nsMediaDecoder::NotifySuspendedStatusChanged is called when this
   // changes.
+  // For resources using the media cache, this returns true only when all
+  // streams for the same resource are all suspended.
   virtual bool IsSuspendedByCache() = 0;
   // Returns true if this stream has been suspended.
   virtual bool IsSuspended() = 0;
   // Reads only data which is cached in the media cache. If you try to read
   // any data which overlaps uncached data, or if aCount bytes otherwise can't
   // be read, this function will return failure. This function be called from
   // any thread, and it is the only read operation which is safe to call on
   // the main thread, since it's guaranteed to be non blocking.
@@ -377,16 +382,17 @@ public:
   virtual nsresult Close();
   virtual void     Suspend(bool aCloseImmediately);
   virtual void     Resume();
   virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
   // Return true if the stream has been closed.
   bool IsClosed() const { return mCacheStream.IsClosed(); }
   virtual nsMediaStream* CloneData(nsMediaDecoder* aDecoder);
   virtual nsresult ReadFromCache(char* aBuffer, PRInt64 aOffset, PRUint32 aCount);
+  virtual void     EnsureCacheUpToDate();
 
   // Other thread
   virtual void     SetReadMode(nsMediaCacheStream::ReadMode aMode);
   virtual void     SetPlaybackRate(PRUint32 aBytesPerSecond);
   virtual nsresult Read(char* aBuffer, PRUint32 aCount, PRUint32* aBytes);
   virtual nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
   virtual PRInt64  Tell();
 
@@ -470,20 +476,19 @@ protected:
   bool               mReopenOnError;
   // When this flag is set, we should not report the next close of the
   // channel.
   bool               mIgnoreClose;
 
   // Any thread access
   nsMediaCacheStream mCacheStream;
 
-  // This lock protects mChannelStatistics and mCacheSuspendCount
+  // This lock protects mChannelStatistics
   Mutex               mLock;
   nsChannelStatistics mChannelStatistics;
-  PRUint32            mCacheSuspendCount;
 
   // True if we couldn't suspend the stream and we therefore don't want
   // to resume later. This is usually due to the channel not being in the
   // isPending state at the time of the suspend request.
   bool mIgnoreResume;
 };
 
 #endif
--- a/content/media/test/manifest.js
+++ b/content/media/test/manifest.js
@@ -347,31 +347,31 @@ function MediaTestManager() {
     this.nextTest();
   }
   
   // Registers that the test corresponding to 'token' has been started.
   // Don't call more than once per token.
   this.started = function(token) {
     this.tokens.push(token);
     this.numTestsRunning++;
-    is(this.numTestsRunning, this.tokens.length, "[started] Length of array should match number of running tests");
+    is(this.numTestsRunning, this.tokens.length, "[started " + token + "] Length of array should match number of running tests");
   }
   
   // Registers that the test corresponding to 'token' has finished. Call when
   // you've finished your test. If all tests are complete this will finish the
   // run, otherwise it may start up the next run. It's ok to call multiple times
   // per token.
   this.finished = function(token) {
     var i = this.tokens.indexOf(token);
     if (i != -1) {
       // Remove the element from the list of running tests.
       this.tokens.splice(i, 1);
     }
     this.numTestsRunning--;
-    is(this.numTestsRunning, this.tokens.length, "[finished] Length of array should match number of running tests");
+    is(this.numTestsRunning, this.tokens.length, "[finished " + token + "] Length of array should match number of running tests");
     if (this.tokens.length < PARALLEL_TESTS) {
       this.nextTest();
     }
   }
 
   // Starts the next batch of tests, or finishes if they're all done.
   // Don't call this directly, call finished(token) when you're done.
   this.nextTest = function() {
--- a/content/media/test/test_preload_actions.html
+++ b/content/media/test/test_preload_actions.html
@@ -40,51 +40,52 @@ var finished = false;
 addLoadEvent(function() {gotLoadEvent=true;});
 
 function log(m) {
   var l = document.getElementById("log");
   l.innerHTML += m;
 }
 
 function maybeFinish(v, n) {
+  if (v._finished) {
+    return;
+  }
+  v._finished = true;
   log(n + ",");
   if (v.parentNode) {
     v.parentNode.removeChild(v);
   }
   manager.finished(v.token);
 }
 
 function filename(uri) {
   return uri.substr(uri.lastIndexOf("/")+1);
 }
 
-// Every test must have a setup(v) function, and must set _finished field on target v to
-// true when test is complete.
+// Every test must have a setup(v) function, and must call maybeFinish() when test is complete.
 var tests = [
   {
     // 1. Add preload:none video with src to document. Load should halt at NETWORK_IDLE and HAVE_NOTHING,
     // after receiving a suspend event. Should not receive loaded events until after we call load().
     // Note the suspend event is explictly sent by our "stop the load" code, but other tests can't rely
     // on it for the preload:metadata case, as there can be multiple suspend events when loading metadata.
     suspend:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(1) Must get loadstart.");
       is(v._gotLoadedMetaData, false, "(1) Must not get loadedmetadata.");
       is(v.readyState, v.HAVE_NOTHING, "(1) ReadyState must be HAVE_NOTHING");
       is(v.networkState, v.NETWORK_IDLE, "(1) NetworkState must be NETWORK_IDLE");
-      v._finished = true;
       maybeFinish(v, 1);
     },
     
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("suspend", this.suspend, false);
       v.src = test.name;
       document.body.appendChild(v); // Causes implicit load, which will be halted due to preload:none.
     },
   },
@@ -93,50 +94,46 @@ var tests = [
     // after suspend event and after loadedmetadata.
     loadeddata:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(2) Must get loadstart.");
       is(v._gotLoadedMetaData, true, "(2) Must get loadedmetadata.");
       ok(v.readyState >= v.HAVE_CURRENT_DATA, "(2) ReadyState must be >= HAVE_CURRENT_DATA");
       is(v.networkState, v.NETWORK_IDLE, "(2) NetworkState must be NETWORK_IDLE");
-      v._finished = true;
       maybeFinish(v, 2);
     },
     
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "metadata";
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadeddata", this.loadeddata, false);
       v.src = test.name;
       document.body.appendChild(v); // Causes implicit load, which will be halted after
                                      // metadata due to preload:metadata.
     },
   },
   {
     // 3. Add preload:auto to document. Should receive canplaythrough eventually.
     canplaythrough:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(3) Must get loadstart.");
       is(v._gotLoadedMetaData, true, "(3) Must get loadedmetadata.");
-      v._finished = true;
       maybeFinish(v, 3);
     },
     
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "auto";
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("canplaythrough", this.canplaythrough, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },
@@ -154,26 +151,24 @@ var tests = [
       is(v.readyState, v.HAVE_NOTHING, "(4) ReadyState must be HAVE_NOTHING");
       is(v.networkState, v.NETWORK_IDLE, "(4) NetworkState must be NETWORK_IDLE");
       v.play(); // Should load and play through.
     },
     
     ended:
     function(e) {
       ok(true, "(4) Got playback ended");
-      e.target._finished = true;
       maybeFinish(e.target, 4);
     },
       
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
       v._gotSuspend = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("suspend", this.suspend, false);
       v.addEventListener("ended", this.ended, false);
       v.src = test.name;
       document.body.appendChild(v);
     },
@@ -183,25 +178,23 @@ var tests = [
     // preload:none load. Add a src, it shouldn't load.
     suspend:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(5) Must get loadstart.");
       is(v._gotLoadedMetaData, false, "(5) Must not get loadedmetadata.");
       is(v.readyState, v.HAVE_NOTHING, "(5) ReadyState must be HAVE_NOTHING");
       is(v.networkState, v.NETWORK_IDLE, "(5) NetworkState must be NETWORK_IDLE");
-      v._finished = true;
       maybeFinish(v, 5);
     },
       
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("suspend", this.suspend, false);
       document.body.appendChild(v); // Causes implicit load, which will be halted due to no resource.
       v.src = test.name; // Load should start, and halt at preload:none.
     },
   },
@@ -210,25 +203,23 @@ var tests = [
     // preload:none load. Add a source, it shouldn't load.
     suspend:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(6) Must get loadstart.");
       is(v._gotLoadedMetaData, false, "(6) Must not get loadedmetadata.");
       is(v.readyState, v.HAVE_NOTHING, "(6) ReadyState must be HAVE_NOTHING");
       is(v.networkState, v.NETWORK_IDLE, "(6) NetworkState must be NETWORK_IDLE");
-      v._finished = true;
       maybeFinish(v, 6);
     },
       
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("suspend", this.suspend, false);
       document.body.appendChild(v); // Causes implicit load, which will be halted due to no resource.
       var s = document.createElement("source");
       s.src = test.name;
       s.type = test.type;
@@ -250,26 +241,24 @@ var tests = [
       is(v.networkState, v.NETWORK_IDLE, "(7) NetworkState must be NETWORK_IDLE");
       v.play(); // Should load and play through.
     },
 
     ended:
     function(e) {
       ok(true, "(7) Got playback ended");
       var v = e.target;
-      v._finished = true;
       is(v._gotErrorEvent, true, "(7) Should get error event from first source load failure");      
       maybeFinish(v, 7);
     },
       
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v._gotErrorEvent = false;
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("suspend", this.suspend, false);
       v.addEventListener("ended", this.ended, false);
       var s1 = document.createElement("source");
       s1.src = "not-a-real-file.404"
@@ -286,124 +275,112 @@ var tests = [
   {
     // 8. Change preload value from none to metadata should cause metadata to be loaded.
     loadeddata:
     function(e) {
       var v = e.target;
       is(v._gotLoadedMetaData, true, "(8) Must get loadedmetadata.");
       ok(v.readyState >= v.HAVE_CURRENT_DATA, "(8) ReadyState must be >= HAVE_CURRENT_DATA on suspend.");
       is(v.networkState, v.NETWORK_IDLE, "(8) NetworkState must be NETWORK_IDLE when load is halted");
-      v._finished = true;
       maybeFinish(v, 8);
     },
     
     setup:
     function(v) {
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadeddata", this.loadeddata, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },
   /*{
     // 9. Change preload value from metadata to auto should cause entire media to be loaded.
     // For some reason we don't always receive the canplaythrough event, particuarly on this test.
     // We've disabled this test until bug 568402 is fixed.
     canplaythrough:
     function(e) {
       var v = e.target;
-      if (v._finished)
-        return;
       is(v._gotLoadStart, true, "(9) Must get loadstart.");
       is(v._gotLoadedMetaData, true, "(9) Must get loadedmetadata.");
-      v._finished = true;
       maybeFinish(v, 9);
     },
     
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "metadata";
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadeddata", function(){v.preload = "auto"}, false);
       v.addEventListener("canplaythrough", this.canplaythrough, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },*/
   {
     // 10. Change preload value from none to auto should cause entire media to be loaded.
     canplaythrough:
     function(e) {
       var v = e.target;
       is(v._gotLoadedMetaData, true, "(10) Must get loadedmetadata.");
-      v._finished = true;
       maybeFinish(v, 10);
     },
     
     setup:
     function(v) {
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadstart", function(e){v.preload = "auto";}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("canplaythrough", this.canplaythrough, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },
   {
     // 11. Change preload value from none to metadata should cause metadata to load.
     loadeddata:
     function(e) {
       var v = e.target;
       is(v._gotLoadedMetaData, true, "(11) Must get loadedmetadata.");
       ok(v.readyState >= v.HAVE_CURRENT_DATA, "(11) ReadyState must be >= HAVE_CURRENT_DATA.");
       is(v.networkState, v.NETWORK_IDLE, "(11) NetworkState must be NETWORK_IDLE.");
-      v._finished = true;
       maybeFinish(v, 11);
     },
 
     setup:
     function(v) {
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.addEventListener("loadstart", function(e){v.preload = "metadata";}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadeddata", this.loadeddata, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },
   {
     // 12. Change preload value from auto to metadata after load started,
     // should still do full load, should not halt after metadata only.
     canplaythrough:
     function(e) {
       var v = e.target;
       is(v._gotLoadedMetaData, true, "(12) Must get loadedmetadata.");
       is(v._gotLoadStart, true, "(12) Must get loadstart.");
-      v._finished = true;
       maybeFinish(v, 12);
     },
 
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "auto";
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("canplaythrough", this.canplaythrough, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
       v.preload = "metadata";
     },
@@ -414,25 +391,23 @@ var tests = [
     // should still load up to metadata, should not halt immediately.
     loadeddata:
     function(e) {
       var v = e.target;
       is(v._gotLoadStart, true, "(13) Must get loadstart.");
       is(v._gotLoadedMetaData, true, "(13) Must get loadedmetadata.");
       ok(v.readyState >= v.HAVE_CURRENT_DATA, "(13) ReadyState must be >= HAVE_CURRENT_DATA.");
       is(v.networkState, v.NETWORK_IDLE, "(13) NetworkState must be NETWORK_IDLE.");
-      v._finished = true;
       maybeFinish(v, 13);
     },
 
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "metadata";
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("loadeddata", this.loadeddata, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
       v.preload = "none";
     },
@@ -448,114 +423,104 @@ var tests = [
       is(v.networkState, v.NETWORK_IDLE, "(14) NetworkState must be NETWORK_IDLE");
       v.play();
     },
     
     ended:
     function(e) {
       ok(true, "(14) Got playback ended");
       var v = e.target;
-      v._finished = true;
       maybeFinish(v, 14);
     },
 
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "metadata";
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("ended", this.ended, false);
       v.addEventListener("loadeddata", this.loadeddata, false);
       v.src = test.name;
       document.body.appendChild(v); // Causes implicit load, which will be halted after
                                      // metadata due to preload:metadata.
     },
   },
   {
     // 15. Autoplay should override preload:none.
     ended:
     function(e) {
       ok(true, "(15) Got playback ended.");
       var v = e.target;
-      v._finished = true;
       maybeFinish(v, 15);
     },
     
     setup:
     function(v) {
       v._gotLoadStart = false;
       v._gotLoadedMetaData = false;
-      v._finished = false;
       v.preload = "none";
       v.autoplay = true;
       v.addEventListener("loadstart", function(e){v._gotLoadStart = true;}, false);
       v.addEventListener("loadedmetadata", function(e){v._gotLoadedMetaData = true;}, false);
       v.addEventListener("ended", this.ended, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },
   {
     // 16. Autoplay should override preload:metadata.
     ended:
     function(e) {
       ok(true, "(16) Got playback ended.");
       var v = e.target;
-      v._finished = true;
       maybeFinish(v, 16);
     },
     
     setup:
     function(v) {
-      v._finished = false;
       v.preload = "metadata";
       v.autoplay = true;
       v.addEventListener("ended", this.ended, false);
       v.src = test.name; // Causes implicit load.
       document.body.appendChild(v);
     },
   },
   {
     // 17. On a preload:none video, adding autoplay should disable preload none, i.e. don't break autoplay!
     ended:
     function(e) {
       ok(true, "(17) Got playback ended.");
       var v = e.target;
-      v._finished = true;
       maybeFinish(v, 17);
     },
     
     setup:
     function(v) {
       v.addEventListener("ended", this.ended, false);
-      v._finished = false;
       v.preload = "none";
       document.body.appendChild(v); // Causes implicit load, which will be halted due to preload:none.
       v.autoplay = true;
       v.src = test.name;
     },    
   },
   {
     // 18. On a preload='none' video, call play() before load algorithms's sync
     // has run, the play() call should override preload='none'.
     ended:
     function(e) {
       ok(true, "(18) Got playback ended.");
       var v = e.target;
-      v._finished = true;
       maybeFinish(v, 18);
     },
     
     setup:
     function(v) {
       v.addEventListener("ended", this.ended, false);
-      v._finished = false;
       v.preload = "none";
       v.src = test.name; // Schedules async section to continue load algorithm.
       document.body.appendChild(v);
       v.play(); // Should cause preload:none to be overridden.
     },  
     }
 ];
 
--- a/content/smil/nsSMILParserUtils.cpp
+++ b/content/smil/nsSMILParserUtils.cpp
@@ -252,17 +252,18 @@ ParseOptionalOffset(const nsAString& aSp
   if (aSpec.IsEmpty()) {
     aResult.mOffset.SetMillis(0);
     return NS_OK;
   }
 
   if (aSpec.First() != '+' && aSpec.First() != '-')
     return NS_ERROR_FAILURE;
 
-  return nsSMILParserUtils::ParseClockValue(aSpec, &aResult.mOffset, true);
+  return nsSMILParserUtils::ParseClockValue(aSpec, &aResult.mOffset,
+     nsSMILParserUtils::kClockValueAllowSign);
 }
 
 nsresult
 ParseAccessKey(const nsAString& aSpec, nsSMILTimeValueSpecParams& aResult)
 {
   NS_ABORT_IF_FALSE(StringBeginsWith(aSpec, ACCESSKEY_PREFIX_CC) ||
       StringBeginsWith(aSpec, ACCESSKEY_PREFIX_LC),
       "Calling ParseAccessKey on non-accesskey-type spec");
@@ -681,17 +682,18 @@ nsSMILParserUtils::ParseTimeValueSpecPar
   SkipBeginEndWsp(start, end);
   if (start == end)
     return rv;
 
   const nsAString &spec = Substring(start, end);
 
   // offset type
   if (*start == '+' || *start == '-' || NS_IsAsciiDigit(*start)) {
-    rv = ParseClockValue(spec, &aResult.mOffset, true);
+    rv = ParseClockValue(spec, &aResult.mOffset,
+                         nsSMILParserUtils::kClockValueAllowSign);
     if (NS_SUCCEEDED(rv)) {
       aResult.mType = nsSMILTimeValueSpecParams::OFFSET;
     }
   }
 
   // indefinite
   else if (spec.Equals(NS_LITERAL_STRING("indefinite"))) {
     aResult.mType = nsSMILTimeValueSpecParams::INDEFINITE;
@@ -724,16 +726,18 @@ nsSMILParserUtils::ParseClockValue(const
                                    bool* aIsMedia)  // = nsnull
 {
   nsSMILTime offset = 0L;
   double component = 0.0;
 
   PRInt8 sign = 0;
   PRUint8 colonCount = 0;
 
+  // Indicates we have started parsing a clock-value (not including the optional
+  // +/- that precedes the clock-value) or keyword ("media", "indefinite")
   bool started = false;
 
   PRInt32 metricMultiplicand = MSEC_PER_SEC;
 
   bool numIsReal = false;
   bool prevNumCouldBeMin = false;
   bool numCouldBeMin = false;
   bool numCouldBeSec = false;
@@ -744,96 +748,87 @@ nsSMILParserUtils::ParseClockValue(const
   }
 
   NS_ConvertUTF16toUTF8 spec(aSpec);
   const char* start = spec.BeginReading();
   const char* end = spec.EndReading();
 
   while (start != end) {
     if (IsSpace(*start)) {
+      ++start;
       if (started) {
-        ++start;
         break;
       }
-      // else, we haven't started yet, ignore initial whitespace
-      ++start;
-
-    } else if ((aFlags & kClockValueAllowSign)
-               && (*start == '+' || *start == '-')) {
-      // check sign has not already been set
+    } else if (!started && (aFlags & kClockValueAllowSign) &&
+               (*start == '+' || *start == '-')) {
+      // check sign has not already been set (e.g. ++10s)
       if (sign != 0) {
         return NS_ERROR_FAILURE;
       }
 
-      // check sign is not in middle of string
-      if (started) {
-        return NS_ERROR_FAILURE;
-      }
-
       sign = (*start == '+') ? 1 : -1;
       ++start;
     // The NS_IS_DIGIT etc. macros are not locale-specific
     } else if (NS_IS_DIGIT(*start)) {
       prevNumCouldBeMin = numCouldBeMin;
 
       if (!ParseClockComponent(start, end, component, numIsReal, numCouldBeMin,
-                               numCouldBeSec))
+                               numCouldBeSec)) {
         return NS_ERROR_FAILURE;
-
+      }
       started = true;
-    } else if (*start == ':') {
+    } else if (started && *start == ':') {
       ++colonCount;
 
       // Neither minutes nor hours can be reals
       if (numIsReal) {
         return NS_ERROR_FAILURE;
       }
 
-      // Clock value can't start with a ':'
-      if (!started) {
-        return NS_ERROR_FAILURE;
-      }
-
       // Can't have more than two colons
       if (colonCount > 2) {
         return NS_ERROR_FAILURE;
       }
 
       // Multiply the offset by 60 and add the last accumulated component
       offset = offset * 60 + nsSMILTime(component);
 
       component = 0.0;
       ++start;
     } else if (NS_IS_ALPHA(*start)) {
       if (colonCount > 0) {
         return NS_ERROR_FAILURE;
       }
 
-      if ((aFlags & kClockValueAllowIndefinite)
-          && ConsumeSubstring(start, end, "indefinite")) {
+      if (!started && (aFlags & kClockValueAllowIndefinite) &&
+          ConsumeSubstring(start, end, "indefinite")) {
         // We set a separate flag because we don't know what the state of the
         // passed in time value is and we shouldn't change it in the case of a
         // bad input string (so we can't initialise it to 0ms for example).
         isIndefinite = true;
         if (aResult) {
           aResult->SetIndefinite();
         }
-      } else if (aIsMedia && ConsumeSubstring(start, end, "media")) {
+        started = true;
+      } else if (!started && aIsMedia &&
+                 ConsumeSubstring(start, end, "media")) {
         *aIsMedia = true;
+        started = true;
       } else if (!ParseMetricMultiplicand(start, end, metricMultiplicand)) {
         return NS_ERROR_FAILURE;
       }
 
       // Nothing must come after the string except whitespace
       break;
     } else {
       return NS_ERROR_FAILURE;
     }
   }
 
+  // Whitespace/empty string
   if (!started) {
     return NS_ERROR_FAILURE;
   }
 
   // Process remainder of string (if any) to ensure it is only trailing
   // whitespace (embedded whitespace is not allowed)
   SkipBeginWsp(start, end);
   if (start != end) {
@@ -850,17 +845,17 @@ nsSMILParserUtils::ParseClockValue(const
   // latest component must be a correctly formatted second (i.e. two digits
   // before the .)
   if (colonCount > 0 && (!prevNumCouldBeMin || !numCouldBeSec)) {
     return NS_ERROR_FAILURE;
   }
 
   // Tack on the last component
   if (colonCount > 0) {
-    offset = offset * 60 * 1000;
+    offset *= 60 * 1000;
     component *= 1000;
     // rounding
     component = (component >= 0) ? component + 0.5 : component - 0.5;
     offset += nsSMILTime(component);
   } else {
     component *= metricMultiplicand;
     // rounding
     component = (component >= 0) ? component + 0.5 : component - 0.5;
--- a/content/svg/content/src/nsSVGPathElement.cpp
+++ b/content/svg/content/src/nsSVGPathElement.cpp
@@ -434,17 +434,17 @@ nsSVGPathElement::GetPathLengthScale(Pat
   if (mPathLength.IsExplicitlySet()) {
     float authorsPathLengthEstimate = mPathLength.GetAnimValue();
     if (authorsPathLengthEstimate > 0) {
       gfxMatrix matrix;
       if (aFor == eForTextPath) {
         // For textPath, a transform on the referenced path affects the
         // textPath layout, so when calculating the actual path length
         // we need to take that into account.
-        matrix = PrependLocalTransformTo(gfxMatrix());
+        matrix = PrependLocalTransformTo(matrix);
       }
       nsRefPtr<gfxFlattenedPath> path = GetFlattenedPath(matrix);
       if (path) {
         return path->GetLength() / authorsPathLengthEstimate;
       }
     }
   }
   return 1.0;
--- a/docshell/test/browser/browser_bug134911.js
+++ b/docshell/test/browser/browser_bug134911.js
@@ -15,17 +15,17 @@ function test() {
 function afterOpen() {
   gBrowser.selectedBrowser.removeEventListener("load", afterOpen, true);
   gBrowser.selectedBrowser.addEventListener("load", afterChangeCharset, true);
 
   gBrowser.contentDocument.getElementById("testtextarea").value = enteredText1;
   gBrowser.contentDocument.getElementById("testinput").value = enteredText2;
 
   /* Force the page encoding to Shift_JIS */
-  SetForcedCharset("Shift_JIS");
+  BrowserSetForcedCharacterSet("Shift_JIS");
 }
   
 function afterChangeCharset() {
   gBrowser.selectedBrowser.removeEventListener("load", afterChangeCharset, true);
 
   is(gBrowser.contentDocument.getElementById("testpar").innerHTML, rightText,
      "encoding successfully changed");
   is(gBrowser.contentDocument.getElementById("testtextarea").value, enteredText1,
--- a/docshell/test/browser/browser_bug92473.js
+++ b/docshell/test/browser/browser_bug92473.js
@@ -17,17 +17,17 @@ function testContent(text) {
 function afterOpen() {
   gBrowser.selectedBrowser.removeEventListener("load", afterOpen, true);
   gBrowser.selectedBrowser.addEventListener("load", afterChangeCharset, true);
 
   /* Test that the content on load is the expected wrong decoding */
   testContent(wrongText);
 
   /* Force the page encoding to Shift_JIS */
-  SetForcedCharset("Shift_JIS");
+  BrowserSetForcedCharacterSet("Shift_JIS");
 }
   
 function afterChangeCharset() {
   gBrowser.selectedBrowser.removeEventListener("load", afterChangeCharset, true);
 
   /* test that the content is decoded correctly */
   testContent(rightText);
   gBrowser.removeCurrentTab();
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -61,16 +61,17 @@ DIRS = \
   interfaces/xul \
   interfaces/storage \
   interfaces/json \
   interfaces/offline \
   interfaces/geolocation \
   interfaces/notification \
   interfaces/svg \
   interfaces/smil \
+  interfaces/apps \
   $(NULL)
 
 DIRS += \
   base \
   battery \
   sms \
   src \
   locales \
@@ -79,18 +80,14 @@ DIRS += \
   indexedDB \
   system \
   ipc \
   workers \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
-
-# These subdirs rely on GTK libraries and header files, it is not
-#  buildable on other non-GTK unix builds
-
 ifneq (,$(filter gtk2 cocoa windows android qt os2,$(MOZ_WIDGET_TOOLKIT)))
 DIRS += plugins/test
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -47,17 +47,23 @@ LIBRARY_NAME	= jsdombase_s
 LIBXUL_LIBRARY	= 1
 FORCE_STATIC_LIB = 1
 
 EXTRA_PP_COMPONENTS = \
 		ConsoleAPI.js \
 		ConsoleAPI.manifest \
 		$(NULL)
 
+EXTRA_COMPONENTS = \
+	        Webapps.js \
+	        Webapps.manifest \
+		$(NULL)
+
 EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
+                Webapps.jsm \
 		$(NULL)
 
 XPIDLSRCS = \
   nsIEntropyCollector.idl \
   nsIScriptChannel.idl \
   $(NULL)
 
 EXPORTS = \
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -85,38 +85,26 @@ bool Navigator::sDoNotTrackEnabled = fal
 void
 Navigator::Init()
 {
   Preferences::AddBoolVarCache(&sDoNotTrackEnabled,
                                "privacy.donottrackheader.enabled",
                                false);
 }
 
-Navigator::Navigator(nsIDocShell* aDocShell)
-  : mDocShell(aDocShell)
+Navigator::Navigator(nsPIDOMWindow* aWindow)
+  : mWindow(do_GetWeakReference(aWindow))
 {
+  NS_ASSERTION(aWindow->IsInnerWindow(),
+               "Navigator must get an inner window!");
 }
 
 Navigator::~Navigator()
 {
-  if (mMimeTypes) {
-    mMimeTypes->Invalidate();
-  }
-
-  if (mPlugins) {
-    mPlugins->Invalidate();
-  }
-
-  if (mBatteryManager) {
-    mBatteryManager->Shutdown();
-  }
-
-  if (mSmsManager) {
-    mSmsManager->Shutdown();
-  }
+  Invalidate();
 }
 
 NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorBattery)
@@ -124,22 +112,23 @@ NS_INTERFACE_MAP_BEGIN(Navigator)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozNavigatorSms)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(Navigator)
 NS_IMPL_RELEASE(Navigator)
 
 void
-Navigator::SetDocShell(nsIDocShell* aDocShell)
+Navigator::Invalidate()
 {
-  mDocShell = aDocShell;
+  mWindow = nsnull;
 
   if (mPlugins) {
-    mPlugins->SetDocShell(aDocShell);
+    mPlugins->Invalidate();
+    mPlugins = nsnull;
   }
 
   // If there is a page transition, make sure delete the geolocation object.
   if (mGeolocation) {
     mGeolocation->Shutdown();
     mGeolocation = nsnull;
   }
 
@@ -154,16 +143,25 @@ Navigator::SetDocShell(nsIDocShell* aDoc
   }
 
   if (mSmsManager) {
     mSmsManager->Shutdown();
     mSmsManager = nsnull;
   }
 }
 
+nsPIDOMWindow *
+Navigator::GetWindow()
+{
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  return win;
+}
+
+
 //*****************************************************************************
 //    Navigator::nsIDOMNavigator
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetUserAgent(nsAString& aUserAgent)
 {
   return NS_GetNavigatorUserAgent(aUserAgent);
@@ -361,17 +359,19 @@ Navigator::GetMimeTypes(nsIDOMMimeTypeAr
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Navigator::GetPlugins(nsIDOMPluginArray** aPlugins)
 {
   if (!mPlugins) {
-    mPlugins = new nsPluginArray(this, mDocShell);
+    nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+    mPlugins = new nsPluginArray(this, win ? win->GetDocShell() : nsnull);
   }
 
   NS_ADDREF(*aPlugins = mPlugins);
 
   return NS_OK;
 }
 
 // Values for the network.cookie.cookieBehavior pref are documented in
@@ -383,17 +383,23 @@ Navigator::GetCookieEnabled(bool* aCooki
 {
   *aCookieEnabled =
     (Preferences::GetInt("network.cookie.cookieBehavior",
                          COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
 
   // Check whether an exception overrides the global cookie behavior
   // Note that the code for getting the URI here matches that in
   // nsHTMLDocument::SetCookie.
-  nsCOMPtr<nsIDocument> doc = do_GetInterface(mDocShell);
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetDocShell()) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
   if (!doc) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> codebaseURI;
   doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
 
   if (!codebaseURI) {
@@ -503,60 +509,21 @@ Navigator::JavaEnabled(bool* aReturn)
       break;
     }
   }
 
   return NS_OK;
 }
 
 void
-Navigator::LoadingNewDocument()
-{
-  // Release these so that they will be recreated for the
-  // new document (if requested).  The plugins or mime types
-  // arrays may have changed.  See bug 150087.
-  if (mMimeTypes) {
-    mMimeTypes->Invalidate();
-    mMimeTypes = nsnull;
-  }
-
-  if (mPlugins) {
-    mPlugins->Invalidate();
-    mPlugins = nsnull;
-  }
-
-  if (mGeolocation) {
-    mGeolocation->Shutdown();
-    mGeolocation = nsnull;
-  }
-
-  if (mNotification) {
-    mNotification->Shutdown();
-    mNotification = nsnull;
-  }
-
-  if (mBatteryManager) {
-    mBatteryManager->Shutdown();
-    mBatteryManager = nsnull;
-  }
-
-  if (mSmsManager) {
-    mSmsManager->Shutdown();
-    mSmsManager = nsnull;
-  }
-}
-
-nsresult
 Navigator::RefreshMIMEArray()
 {
   if (mMimeTypes) {
-    return mMimeTypes->Refresh();
+    mMimeTypes->Refresh();
   }
-
-  return NS_OK;
 }
 
 bool
 Navigator::HasDesktopNotificationSupport()
 {
   return Preferences::GetBool("notification.feature.enabled", false);
 }
 
@@ -564,57 +531,51 @@ Navigator::HasDesktopNotificationSupport
 //    Navigator::nsIDOMClientInformation
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::RegisterContentHandler(const nsAString& aMIMEType,
                                   const nsAString& aURI,
                                   const nsAString& aTitle)
 {
-  if (!mDocShell) {
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
     do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
   if (!registrar) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMWindow> contentDOMWindow = do_GetInterface(mDocShell);
-  if (!contentDOMWindow) {
-    return NS_OK;
-  }
-
   return registrar->RegisterContentHandler(aMIMEType, aURI, aTitle,
-                                           contentDOMWindow);
+                                           win->GetOuterWindow());
 }
 
 NS_IMETHODIMP
 Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
                                    const nsAString& aURI,
                                    const nsAString& aTitle)
 {
-  if (!mDocShell) {
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
     do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
   if (!registrar) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMWindow> contentDOMWindow = do_GetInterface(mDocShell);
-  if (!contentDOMWindow) {
-    return NS_OK;
-  }
-
   return registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle,
-                                            contentDOMWindow);
+                                            win->GetOuterWindow());
 }
 
 NS_IMETHODIMP
 Navigator::MozIsLocallyAvailable(const nsAString &aURI,
                                  bool aWhenOffline,
                                  bool* aIsAvailable)
 {
   nsCOMPtr<nsIURI> uri;
@@ -697,31 +658,28 @@ NS_IMETHODIMP Navigator::GetGeolocation(
     return NS_OK;
   }
 
   if (mGeolocation) {
     NS_ADDREF(*_retval = mGeolocation);
     return NS_OK;
   }
 
-  if (!mDocShell) {
-    return NS_ERROR_FAILURE;
-  }
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
 
-  nsCOMPtr<nsIDOMWindow> contentDOMWindow = do_GetInterface(mDocShell);
-  if (!contentDOMWindow) {
+  if (!win || !win->GetOuterWindow() || !win->GetDocShell()) {
     return NS_ERROR_FAILURE;
   }
 
   mGeolocation = new nsGeolocation();
   if (!mGeolocation) {
     return NS_ERROR_FAILURE;
   }
 
-  if (NS_FAILED(mGeolocation->Init(contentDOMWindow))) {
+  if (NS_FAILED(mGeolocation->Init(win->GetOuterWindow()))) {
     mGeolocation = nsnull;
     return NS_ERROR_FAILURE;
   }
 
   NS_ADDREF(*_retval = mGeolocation);
   return NS_OK;
 }
 
@@ -734,59 +692,48 @@ NS_IMETHODIMP Navigator::GetMozNotificat
   NS_ENSURE_ARG_POINTER(aRetVal);
   *aRetVal = nsnull;
 
   if (mNotification) {
     NS_ADDREF(*aRetVal = mNotification);
     return NS_OK;
   }
 
-  nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
-  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
-
-  nsCOMPtr<nsIDocument> document = do_GetInterface(mDocShell);
-  NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
-
-  nsIScriptGlobalObject* sgo = document->GetScopeObject();
-  NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+  nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(win));
+  NS_ENSURE_TRUE(sgo && win->GetDocShell(), NS_ERROR_FAILURE);
 
   nsIScriptContext* scx = sgo->GetContext();
   NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
 
-  mNotification = new nsDesktopNotificationCenter(window->GetCurrentInnerWindow(),
-                                                  scx);
+  mNotification = new nsDesktopNotificationCenter(win, scx);
 
   NS_ADDREF(*aRetVal = mNotification);
   return NS_OK;
 }
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorBattery
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
 {
   if (!mBatteryManager) {
     *aBattery = nsnull;
 
-    nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(window, NS_OK);
-
-    nsCOMPtr<nsIDocument> document = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(document, NS_OK);
-
-    nsIScriptGlobalObject* sgo = document->GetScopeObject();
-    NS_ENSURE_TRUE(sgo, NS_OK);
+    nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+    nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(win));
+    NS_ENSURE_TRUE(sgo && win->GetDocShell(), NS_OK);
 
     nsIScriptContext* scx = sgo->GetContext();
     NS_ENSURE_TRUE(scx, NS_OK);
 
     mBatteryManager = new battery::BatteryManager();
-    mBatteryManager->Init(window->GetCurrentInnerWindow(), scx);
+    mBatteryManager->Init(win, scx);
   }
 
   NS_ADDREF(*aBattery = mBatteryManager);
 
   return NS_OK;
 }
 
 //*****************************************************************************
@@ -804,17 +751,23 @@ Navigator::IsSmsAllowed() const
   }
 
   // In addition of having 'dom.sms.enabled' set to true, we require the
   // website to be whitelisted. This is a temporary 'security model'.
   // 'dom.sms.whitelist' has to contain comma-separated values of URI prepath.
   // For local files, "file://" must be listed.
   // For data-urls: "moz-nullprincipal:".
   // Chrome files also have to be whitelisted for the moment.
-  nsCOMPtr<nsIDocument> doc = do_GetInterface(mDocShell);
+  nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
+
+  if (!win || !win->GetDocShell()) {
+    return defaultSmsPermission;
+  }
+
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
   if (!doc) {
     return defaultSmsPermission;
   }
 
   nsCOMPtr<nsIURI> uri;
   doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
 
   if (!uri) {
@@ -859,30 +812,27 @@ Navigator::GetMozSms(nsIDOMMozSmsManager
 {
   *aSmsManager = nsnull;
 
   if (!mSmsManager) {
     if (!IsSmsSupported() || !IsSmsAllowed()) {
       return NS_OK;
     }
 
-    nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(window, NS_OK);
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+    NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
 
-    nsCOMPtr<nsIDocument> document = do_GetInterface(mDocShell);
-    NS_ENSURE_TRUE(document, NS_OK);
-
-    nsIScriptGlobalObject* sgo = document->GetScopeObject();
+    nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
     NS_ENSURE_TRUE(sgo, NS_OK);
 
     nsIScriptContext* scx = sgo->GetContext();
     NS_ENSURE_TRUE(scx, NS_OK);
 
     mSmsManager = new sms::SmsManager();
-    mSmsManager->Init(window->GetCurrentInnerWindow(), scx);
+    mSmsManager->Init(window, scx);
   }
 
   NS_ADDREF(*aSmsManager = mSmsManager);
 
   return NS_OK;
 }
 
 PRInt64
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -45,22 +45,23 @@
 
 #include "nsIDOMNavigator.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "nsIDOMNavigatorDesktopNotification.h"
 #include "nsIDOMClientInformation.h"
 #include "nsIDOMNavigatorBattery.h"
 #include "nsIDOMNavigatorSms.h"
 #include "nsAutoPtr.h"
+#include "nsWeakReference.h"
 
 class nsPluginArray;
 class nsMimeTypeArray;
 class nsGeolocation;
 class nsDesktopNotificationCenter;
-class nsIDocShell;
+class nsPIDOMWindow;
 
 //*****************************************************************************
 // Navigator: Script "navigator" object
 //*****************************************************************************
 
 namespace mozilla {
 namespace dom {
 
@@ -75,37 +76,33 @@ class SmsManager;
 class Navigator : public nsIDOMNavigator,
                   public nsIDOMClientInformation,
                   public nsIDOMNavigatorGeolocation,
                   public nsIDOMNavigatorDesktopNotification,
                   public nsIDOMMozNavigatorBattery,
                   public nsIDOMMozNavigatorSms
 {
 public:
-  Navigator(nsIDocShell *aDocShell);
+  Navigator(nsPIDOMWindow *aInnerWindow);
   virtual ~Navigator();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMNAVIGATOR
   NS_DECL_NSIDOMCLIENTINFORMATION
   NS_DECL_NSIDOMNAVIGATORGEOLOCATION
   NS_DECL_NSIDOMNAVIGATORDESKTOPNOTIFICATION
   NS_DECL_NSIDOMMOZNAVIGATORBATTERY
   NS_DECL_NSIDOMMOZNAVIGATORSMS
 
   static void Init();
 
-  void SetDocShell(nsIDocShell *aDocShell);
-  nsIDocShell *GetDocShell()
-  {
-    return mDocShell;
-  }
+  void Invalidate();
+  nsPIDOMWindow *GetWindow();
 
-  void LoadingNewDocument();
-  nsresult RefreshMIMEArray();
+  void RefreshMIMEArray();
 
   static bool HasDesktopNotificationSupport();
 
   PRInt64 SizeOf() const;
 
 private:
   bool IsSmsAllowed() const;
   bool IsSmsSupported() const;
@@ -113,17 +110,17 @@ private:
   static bool sDoNotTrackEnabled;
 
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
-  nsIDocShell* mDocShell; // weak reference
+  nsWeakPtr mWindow;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent);
 nsresult NS_GetNavigatorPlatform(nsAString& aPlatform);
 nsresult NS_GetNavigatorAppVersion(nsAString& aAppVersion);
new file mode 100644
--- /dev/null
+++ b/dom/base/Webapps.js
@@ -0,0 +1,346 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Open Web Apps.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Fabrice Desré <fabrice@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+const Cr = Components.results;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+function WebappsRegistry() {
+  this.messages = ["Webapps:Install:Return:OK", "Webapps:Install:Return:KO",
+                   "Webapps:Uninstall:Return:OK", "Webapps:Uninstall:Return:KO",
+                   "Webapps:Enumerate:Return:OK", "Webapps:Enumerate:Return:KO"];
+
+  this.mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+
+  this.messages.forEach((function(msgName) {
+    this.mm.addMessageListener(msgName, this);
+  }).bind(this));
+
+  this._window = null;
+  this._id = this._getRandomId();
+  this._callbacks = [];
+}
+
+WebappsRegistry.prototype = {
+  _onerror: null,
+  _oninstall: null,
+  _onuninstall: null,
+
+  /** from https://developer.mozilla.org/en/OpenWebApps/The_Manifest
+   * only the name property is mandatory
+   */
+  checkManifest: function(aManifest, aInstallOrigin) {
+    // TODO : check for install_allowed_from
+    if (aManifest.name == undefined)
+      return false;
+    
+    if (aManifest.installs_allowed_from) {
+      ok = false;
+      aManifest.installs_allowed_from.forEach(function(aOrigin) {
+        if (aOrigin == "*" || aOrigin == aInstallOrigin)
+          ok = true;
+      });
+      return ok;
+    }
+    return true;
+  },
+  
+  getCallbackId: function(aCallback) {
+    let id = "id" + this._getRandomId();
+    this._callbacks[id] = aCallback;
+    return id;
+  },
+  
+  getCallback: function(aId) {
+    return this._callbacks[aId];
+  },
+
+  removeCallback: function(aId) {
+    if (this._callbacks[aId])
+      delete this._callbacks[aId];
+  },
+  
+  _getRandomId: function() {
+    return Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString();
+  },
+
+  _convertAppsArray: function(aApps) {
+    let apps = new Array();
+    for (let i = 0; i < aApps.length; i++) {
+      let app = aApps[i];
+      apps.push(new WebappsApplication(app.origin, app.manifest, app.receipt, app.installOrigin, app.installTime));
+    }
+    return apps;
+  },
+
+  set oninstall(aCallback) {
+    if (this.hasPrivileges)
+      this._oninstall = aCallback;
+    else
+      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+  },
+  
+  set onuninstall(aCallback) {
+    if (this.hasPrivileges)
+      this._onuninstall = aCallback;
+    else
+      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+  },
+
+  set onerror(aCallback) {
+    this._onerror = aCallback;
+  },
+
+  receiveMessage: function(aMessage) {
+    let msg = aMessage.json;
+    if (!(msg.oid == this._id || aMessage.name == "Webapps:Install:Return:OK" || aMessage.name == "Webapps:Uninstall:Return:OK"))
+      return
+    let app = msg.app;
+    let cb;
+    switch (aMessage.name) {
+      case "Webapps:Install:Return:OK":
+        if (this._oninstall)
+          this._oninstall.handleEvent(new WebappsApplication(app.origin, app.manifest, app.receipt,
+                                                app.installOrigin, app.installTime));
+        break;
+      case "Webapps:Install:Return:KO":
+        if (this._onerror)
+          this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.DENIED));
+        break;
+      case "Webapps:Uninstall:Return:OK":
+        if (this._onuninstall)
+          this._onuninstall.handleEvent(new WebappsApplication(msg.origin, null, null, null, 0));
+        break;
+      case "Webapps:Uninstall:Return:KO":
+        if (this._onerror)
+          this._onerror.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
+        break;
+      case "Webapps:Enumerate:Return:OK":
+        cb = this.getCallback(msg.callbackID);
+        if (cb.success) {
+          let apps = this._convertAppsArray(msg.apps);
+          cb.success.handleEvent(apps, apps.length);
+        }
+        break;
+      case "Webapps:Enumerate:Return:KO":
+        cb = this.getCallback(msg.callbackID);
+        if (cb.error)
+          cb.error.handleEvent(new RegistryError(Ci.mozIDOMApplicationRegistryError.PERMISSION_DENIED));
+        break;
+    }
+    this.removeCallback(msg.callbackID);
+  },
+  
+  _fireError: function(aCode) {
+    if (!this._onerror)
+      return;
+    this._onerror.handleEvent(new RegistryError(aCode));
+  },
+
+  _getOrigin: function(aURL) {
+    let uri = Services.io.newURI(aURL, null, null);
+    return uri.prePath; 
+  },
+
+  // mozIDOMApplicationRegistry implementation
+  
+  install: function(aURL, aReceipt) {
+    let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
+    xhr.open("GET", aURL, true);
+
+    xhr.addEventListener("load", (function() {
+      if (xhr.status == 200) {
+        try {
+          let installOrigin = this._getOrigin(this._window.location.href);
+          let manifest = JSON.parse(xhr.responseText, installOrigin);
+          if (!this.checkManifest(manifest, installOrigin)) {
+            this._fireError(Ci.mozIDOMApplicationRegistryError.INVALID_MANIFEST);
+          } else {
+            this.mm.sendAsyncMessage("Webapps:Install", { app: { installOrigin: installOrigin,
+                                                          origin: this._getOrigin(aURL),
+                                                          manifest: manifest,
+                                                          receipt: aReceipt },
+                                                          from: this._window.location.href,
+                                                          oid: this._id });
+          }
+        } catch(e) {
+          this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_PARSE_ERROR);
+        }
+      }
+      else {
+        this._fireError(Ci.mozIDOMApplicationRegistryError.MANIFEST_URL_ERROR);
+      }      
+    }).bind(this), false);
+
+    xhr.addEventListener("error", (function() {
+      this._fireError(Ci.mozIDOMApplicationRegistryError.NETWORK_ERROR);
+    }).bind(this), false);
+
+    xhr.send(null);
+  },
+
+  uninstall: function(aOrigin) {
+    if (this.hasPrivileges)
+      this.mm.sendAsyncMessage("Webapps:Uninstall", { from: this._window.location.href,
+                                                      origin: aOrigin,
+                                                      oid: this._id });
+    else
+      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+  },
+
+  launch: function(aOrigin) {
+    this.mm.sendAsyncMessage("Webapps:Launch", { origin: aOrigin,
+                                                 from: this._window.location.href});
+  },
+  
+  enumerate: function(aSuccess, aError) {
+    this.mm.sendAsyncMessage("Webapps:Enumerate", { from: this._window.location.href,
+                                                    origin: this._getOrigin(this._window.location.href),
+                                                    oid: this._id,
+                                                    callbackID:  this.getCallbackId({ success: aSuccess, error: aError }) });
+  },
+
+  handleEvent: function(aEvent) {
+    if (aEvent.type == "unload") {
+      // remove all callbacks and event handlers so we don't call anything on a cleared scope
+      try {
+        this._oninstall = null;
+        this._onuninstall = null;
+        this._onerror = null;
+        this._callbacks = [];
+      } catch(e) {
+        dump("WebappsRegistry error:" + e + "\n");
+      }
+    }
+  },
+  
+  // nsIDOMGlobalPropertyInitializer implementation
+  init: function(aWindow) {
+    dump("DOMApplicationRegistry::init() " + aWindow + "\n");
+    this._window = aWindow;
+    this._window.addEventListener("unload", this, false);
+    this._window.appId = this._id;
+    let from = Services.io.newURI(this._window.location.href, null, null);
+    let perm = Services.perms.testExactPermission(from, "webapps-manage");
+
+    //only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
+    this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
+  },
+  
+  classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistry, Ci.nsIDOMGlobalPropertyInitializer]),
+  
+  classInfo: XPCOMUtils.generateCI({classID: Components.ID("{fff440b3-fae2-45c1-bf03-3b5a2e432270}"),
+                                    contractID: "@mozilla.org/webapps;1",
+                                    interfaces: [Ci.mozIDOMApplicationRegistry],
+                                    flags: Ci.nsIClassInfo.DOM_OBJECT,
+                                    classDescription: "Webapps Registry"})
+}
+
+function WebappsApplication(aOrigin, aManifest, aReceipt, aInstallOrigin, aInstallTime) {
+  this._origin = aOrigin;
+  this._manifest = aManifest;
+  this._receipt = aReceipt;
+  this._installOrigin = aInstallOrigin;
+  this._installTime = aInstallTime;
+}
+
+WebappsApplication.prototype = {
+  _origin: null,
+  _manifest: null,
+  _receipt: null,
+  _installOrigin: null,
+  _installTime: 0,
+
+  get origin() {
+    return this._origin;
+  },
+
+  get manifest() {
+    return this._manifest;
+  },
+
+  get receipt() {
+    return this._receipt;
+  },
+
+  get installOrigin() {
+    return this._installOrigin;
+  },
+  
+  get installTime() {
+    return this._installTime;
+  },
+
+  classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplication]),
+
+  classInfo: XPCOMUtils.generateCI({classID: Components.ID("{723ed303-7757-4fb0-b261-4f78b1f6bd22}"),
+                                    contractID: "@mozilla.org/webapps/application;1",
+                                    interfaces: [Ci.mozIDOMApplication],
+                                    flags: Ci.nsIClassInfo.DOM_OBJECT,
+                                    classDescription: "Webapps Application"})
+}
+
+function RegistryError(aCode) {
+  this._code = aCode;
+}
+
+RegistryError.prototype = {
+  _code: null,
+  
+  get code() {
+    return this._code;
+  },
+  
+  classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.mozIDOMApplicationRegistryError]),
+
+  classInfo: XPCOMUtils.generateCI({classID: Components.ID("{b4937718-11a3-400b-a69f-ab442a418569}"),
+                                    contractID: "@mozilla.org/webapps/error;1",
+                                    interfaces: [Ci.mozIDOMApplicationRegistryError],
+                                    flags: Ci.nsIClassInfo.DOM_OBJECT,
+                                    classDescription: "Webapps Registry Error"})
+}
+
+const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry, WebappsApplication, RegistryError]);
new file mode 100644
--- /dev/null
+++ b/dom/base/Webapps.jsm
@@ -0,0 +1,380 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Mobile Browser.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Fabrice Desré <fabrice@mozilla.com>
+ *   Mark Finkle <mfinkle@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cu = Components.utils; 
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+let EXPORTED_SYMBOLS = ["DOMApplicationRegistry", "DOMApplicationManifest"];
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
+  Cu.import("resource://gre/modules/NetUtil.jsm");
+  return NetUtil;
+});
+
+let DOMApplicationRegistry = {
+  appsDir: null,
+  appsFile: null,
+  webapps: { },
+
+  init: function() {
+    this.mm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIFrameMessageManager);
+    let messages = ["Webapps:Install", "Webapps:Uninstall",
+                    "Webapps:Enumerate", "Webapps:Launch"];
+
+    messages.forEach((function(msgName) {
+      this.mm.addMessageListener(msgName, this);
+    }).bind(this));
+
+    let file =  Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
+    file.append("webapps");
+    if (!file.exists() || !file.isDirectory()) {
+      file.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
+    }
+    this.appsDir = file;
+    this.appsFile = file.clone();
+    this.appsFile.append("webapps.json");
+    if (!this.appsFile.exists())
+      return;
+    
+    try {
+      let channel = NetUtil.newChannel(this.appsFile);
+      channel.contentType = "application/json";
+      let self = this;
+      NetUtil.asyncFetch(channel, function(aStream, aResult) {
+        if (!Components.isSuccessCode(aResult)) {
+          Cu.reportError("DOMApplicationRegistry: Could not read from json file " + this.appsFile.path);
+          return;
+        }
+
+        // Read json file into a string
+        let data = null;
+        try {
+          self.webapps = JSON.parse(NetUtil.readInputStreamToString(aStream, aStream.available()) || "");
+          aStream.close();
+        } catch (ex) {
+          Cu.reportError("DOMApplicationRegistry: Could not parse JSON: " + ex);
+        }
+      });
+    } catch (ex) {
+      Cu.reportError("DOMApplicationRegistry: Could not read from " + aFile.path + " : " + ex);
+    }
+  },
+
+  receiveMessage: function(aMessage) {
+    let msg = aMessage.json;
+    let from = Services.io.newURI(msg.from, null, null);
+    let perm = Services.perms.testExactPermission(from, "webapps-manage");
+
+    //only pages with perm set and chrome or about pages can uninstall, enumerate all set oninstall an onuninstall
+    let hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome") || from.schemeIs("about");
+
+    switch (aMessage.name) {
+      case "Webapps:Install":
+        // always ask for UI to install
+        Services.obs.notifyObservers(this, "webapps-ask-install", JSON.stringify(msg));
+        break;
+      case "Webapps:Uninstall":
+        if (hasPrivileges)
+          this.uninstall(msg);
+        break;
+      case "Webapps:Launch":
+        Services.obs.notifyObservers(this, "webapps-launch", JSON.stringify(msg));
+        break;
+      case "Webapps:Enumerate":
+        if (hasPrivileges)
+          this.enumerateAll(msg)
+        else
+          this.enumerate(msg);
+        break;
+    }
+  },
+
+  _writeFile: function ss_writeFile(aFile, aData, aCallbak) {
+    // Initialize the file output stream.
+    let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
+    ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
+
+    // Obtain a converter to convert our data to a UTF-8 encoded input stream.
+    let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
+    converter.charset = "UTF-8";
+
+    // Asynchronously copy the data to the file.
+    let istream = converter.convertToInputStream(aData);
+    NetUtil.asyncCopy(istream, ostream, function(rc) {
+      if (aCallbak)
+        aCallbak();
+    });
+  },
+  
+  // clones a app object, without the manifest
+  _cloneAppObject: function(aApp) {
+    let clone = {
+      installOrigin: aApp.installOrigin,
+      origin: aApp.origin,
+      receipt: aApp.receipt,
+      installTime: aApp.installTime
+    };
+    return clone;
+  },
+  
+  denyInstall: function(aData) {
+    this.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
+  },
+  
+  confirmInstall: function(aData) {
+    let app = aData.app;
+    let id = this._appId(app.origin);
+
+    // install an application again is considered as an update
+    if (id) {
+      let dir = this.appsDir.clone();
+      dir.append(id);
+      try {
+        dir.remove(true);
+      } catch(e) {
+      }
+    }
+    else {
+      let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+      id = uuidGenerator.generateUUID().toString();
+    }
+
+    let dir = this.appsDir.clone();
+    dir.append(id);
+    dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0700);
+    
+    let manFile = dir.clone();
+    manFile.append("manifest.json");
+    this._writeFile(manFile, JSON.stringify(app.manifest));
+
+    this.webapps[id] = this._cloneAppObject(app);
+    delete this.webapps[id].manifest;
+    this.webapps[id].installTime = (new Date()).getTime()
+
+    this._writeFile(this.appsFile, JSON.stringify(this.webapps), (function() {
+      this.mm.sendAsyncMessage("Webapps:Install:Return:OK", aData);
+    }).bind(this));
+  },
+ 
+  _appId: function(aURI) {
+    for (let id in this.webapps) {
+      if (this.webapps[id].origin == aURI)
+        return id;
+    }
+    return null;
+  },
+
+  _readManifest: function(aId) {
+    let file = this.appsDir.clone();
+    file.append(aId);
+    file.append("manifest.json");
+    let data = "";  
+    let fstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
+    var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);
+    fstream.init(file, -1, 0, 0);
+    cstream.init(fstream, "UTF-8", 0, 0);
+    let (str = {}) {  
+      let read = 0;  
+      do {   
+        read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value  
+        data += str.value;  
+      } while (read != 0);  
+    }  
+    cstream.close(); // this closes fstream  
+    try {
+      return JSON.parse(data);
+    } catch(e) {
+      return null;
+    }
+  },
+  
+  uninstall: function(aData) {
+    for (let id in this.webapps) {
+      let app = this.webapps[id];
+      if (app.origin == aData.origin) {
+        delete this.webapps[id];
+        this._writeFile(this.appsFile, JSON.stringify(this.webapps));
+        let dir = this.appsDir.clone();
+        dir.append(id);
+        try {
+          dir.remove(true);
+        } catch (e) {
+        }
+        this.mm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
+      }
+    }
+  },
+  
+  enumerate: function(aData) {
+    aData.apps = [];
+
+    let id = this._appId(aData.origin);
+    // if it's an app, add itself to the result
+    if (id) {
+      let app = this._cloneAppObject(this.webapps[id]);
+      app.manifest = this._readManifest(id);
+      aData.apps.push(app);
+    }
+
+    // check if it's a store.
+    let isStore = false;
+    for (id in this.webapps) {
+      let app = this._cloneAppObject(this.webapps[id]);
+      if (app.installOrigin == aData.origin) {
+        isStore = true;
+        break;
+      }
+    }
+
+    // add all the apps from this store
+    if (isStore) {
+      for (id in this.webapps) {
+        let app = this._cloneAppObject(this.webapps[id]);
+        if (app.installOrigin == aData.origin) {
+          app.manifest = this._readManifest(id);
+          aData.apps.push(app);
+        }
+      }
+    }
+
+    this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
+  },
+
+  denyEnumerate: function(aData) {
+    this.mm.sendAsyncMessage("Webapps:Enumerate:Return:KO", aData);
+  },
+
+  enumerateAll: function(aData) {
+    aData.apps = [];
+
+    for (id in this.webapps) {
+      let app = this._cloneAppObject(this.webapps[id]);
+      app.manifest = this._readManifest(id);
+      aData.apps.push(app);
+    }
+
+    this.mm.sendAsyncMessage("Webapps:Enumerate:Return:OK", aData);
+  },
+
+  getManifestFor: function(aOrigin) {
+    let id = this._appId(aOrigin);
+    if (!id)
+      return null;
+    return this._readManifest(id);
+  }
+};
+
+/**
+ * Helper object to access manifest information with locale support
+ */
+DOMApplicationManifest = function(aManifest, aOrigin) {
+  this._origin = Services.io.newURI(aOrigin, null, null);
+  this._manifest = aManifest;
+  let chrome = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry)
+                                                          .QueryInterface(Ci.nsIToolkitChromeRegistry);
+  let locale = chrome.getSelectedLocale("browser").toLowerCase();
+  this._localeRoot = this._manifest;
+  
+  if (this._manifest.locales && this._manifest.locales[locale]) {
+    this._localeRoot = this._manifest.locales[locale];
+  }
+  else if (this._manifest.locales) {
+    // try with the language part of the locale ("en" for en-GB) only
+    let lang = locale.split('-')[0];
+    if (land != locale && this._manifest.locales[lang])
+      this._localeRoot = this._manifest.locales[lang];
+  }
+}
+
+DOMApplicationManifest.prototype = {
+  _localeProp: function(aProp) {
+    if (this._localeRoot[aProp] != undefined)
+      return this._localeRoot[aProp];
+    return this._manifest[aProp];
+  },
+
+  get name() {
+    return this._localeProp("name");
+  },
+  
+  get description() {
+    return this._localeProp("description");
+  },
+  
+  get version() {
+    return this._localeProp("version");
+  },
+  
+  get launch_path() {
+    return this._localeProp("launch_path");
+  },
+  
+  get developer() {
+    return this._localeProp("developer");
+  },
+  
+  get icons() {
+    return this._localeProp("icons");
+  },
+  
+  iconURLForSize: function(aSize) {
+    let icons = this._localeProp("icons");
+    if (!icons)
+      return null;
+    let dist = 100000;
+    let icon = null;
+    for (let size in icons) {
+      let iSize = parseInt(size);
+      if (Math.abs(iSize - aSize) < dist) {
+        icon = this._origin.resolve(icons[size]);
+        dist = Math.abs(iSize - aSize);
+      }
+    }
+    return icon;
+  },
+  
+  fullLaunchPath: function() {
+    let launchPath = this._localeProp("launch_path");
+    return this._origin.resolve(launchPath ? launchPath : "");
+  }
+}
+
+DOMApplicationRegistry.init();
new file mode 100644
--- /dev/null
+++ b/dom/base/Webapps.manifest
@@ -0,0 +1,10 @@
+# Webapps.js
+component {fff440b3-fae2-45c1-bf03-3b5a2e432270} Webapps.js
+contract @mozilla.org/webapps;1 {fff440b3-fae2-45c1-bf03-3b5a2e432270}
+category JavaScript-navigator-property mozApps @mozilla.org/webapps;1
+
+component {723ed303-7757-4fb0-b261-4f78b1f6bd22} Webapps.js
+contract @mozilla.org/webapps/application;1 {723ed303-7757-4fb0-b261-4f78b1f6bd22}
+
+component {b4937718-11a3-400b-a69f-ab442a418569} Webapps.js
+contract @mozilla.org/webapps/error;1 {b4937718-11a3-400b-a69f-ab442a418569}
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -6817,16 +6817,18 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       NS_ENSURE_SUCCESS(rv, rv);
 
       jsval v;
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), true,
                       &v, getter_AddRefs(holder));
       NS_ENSURE_SUCCESS(rv, rv);
 
+      // Hold on to the navigator object as a global property so we
+      // don't need to worry about losing expando properties etc.
       if (!::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull,
                                    JSPROP_READONLY | JSPROP_PERMANENT |
                                    JSPROP_ENUMERATE)) {
         return NS_ERROR_FAILURE;
       }
       *objp = obj;
 
       return NS_OK;
@@ -7149,46 +7151,41 @@ nsNavigatorSH::NewResolve(nsIXPConnectWr
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 // static
 nsresult
 nsNavigatorSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                          JSObject *globalObj, JSObject **parentObj)
 {
-  // window.navigator is persisted across document transitions if
-  // we're loading a page from the same origin. Because of that we
-  // need to parent the navigator wrapper at the outer window to avoid
-  // holding on to the inner window where the navigator was initially
-  // created too long.
+  // window.navigator can hold expandos and thus we need to only ever
+  // create one wrapper per navigator object so that expandos are
+  // visible independently of who's looking it up.
   *parentObj = globalObj;
 
   nsCOMPtr<nsIDOMNavigator> safeNav(do_QueryInterface(nativeObj));
   if (!safeNav) {
     // Oops, this wasn't really a navigator object. This can happen if someone
     // tries to use our scriptable helper as a real object and tries to wrap
     // it, see bug 319296.
     return NS_OK;
   }
 
   Navigator *nav = static_cast<Navigator*>(safeNav.get());
-  nsIDocShell *ds = nav->GetDocShell();
-  if (!ds) {
+  nsGlobalWindow *win = static_cast<nsGlobalWindow*>(nav->GetWindow());
+  if (!win) {
     NS_WARNING("Refusing to create a navigator in the wrong scope");
+
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds);
-
-  if (sgo) {
-    JSObject *global = sgo->GetGlobalJSObject();
-
-    if (global) {
-      *parentObj = global;
-    }
+  JSObject *global = win->GetGlobalJSObject();
+
+  if (global) {
+    *parentObj = global;
   }
 
   return NS_OK;
 }
 
 // DOM Node helper
 
 template<nsresult (*func)(JSContext *cx, JSObject *obj, jsval *vp)>
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1267,16 +1267,21 @@ nsGlobalWindow::ClearScopeWhenAllScripts
   }
 }
 
 void
 nsGlobalWindow::FreeInnerObjects(bool aClearScope)
 {
   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
 
+  // Make sure that this is called before we null out the document and
+  // other members that the window destroyed observers could
+  // re-create.
+  NotifyDOMWindowDestroyed(this);
+
   // Kill all of the workers for this window.
   nsIScriptContext *scx = GetContextInternal();
   JSContext *cx = scx ? scx->GetNativeContext() : nsnull;
   mozilla::dom::workers::CancelWorkersForWindow(cx, this);
 
   // Close all IndexedDB databases for this window.
   indexedDB::IndexedDatabaseManager* idbManager =
     indexedDB::IndexedDatabaseManager::Get();
@@ -1291,31 +1296,33 @@ nsGlobalWindow::FreeInnerObjects(bool aC
   if (mListenerManager) {
     mListenerManager->Disconnect();
     mListenerManager = nsnull;
   }
 
   mLocation = nsnull;
   mHistory = nsnull;
 
+  if (mNavigator) {
+    mNavigator->Invalidate();
+    mNavigator = nsnull;
+  }
+
   if (mDocument) {
     NS_ASSERTION(mDoc, "Why is mDoc null?");
 
     // Remember the document's principal.
     mDocumentPrincipal = mDoc->NodePrincipal();
   }
 
 #ifdef DEBUG
   if (mDocument)
     nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr<nsISupports>(do_QueryInterface(mDocument)));
 #endif
 
-  // Make sure that this is called before we null out the document.
-  NotifyDOMWindowDestroyed(this);
-
   // Remove our reference to the document and the document principal.
   mDocument = nsnull;
   mDoc = nsnull;
 
   if (mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
     mApplicationCache = nsnull;
   }
@@ -1728,59 +1735,53 @@ nsGlobalWindow::GetPopupControlState() c
 class WindowStateHolder : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID)
   NS_DECL_ISUPPORTS
 
   WindowStateHolder(nsGlobalWindow *aWindow,
                     nsIXPConnectJSObjectHolder *aHolder,
-                    Navigator *aNavigator,
                     nsIXPConnectJSObjectHolder *aOuterProto,
                     nsIXPConnectJSObjectHolder *aOuterRealProto);
 
   nsGlobalWindow* GetInnerWindow() { return mInnerWindow; }
   nsIXPConnectJSObjectHolder *GetInnerWindowHolder()
   { return mInnerWindowHolder; }
 
-  Navigator* GetNavigator() { return mNavigator; }
   nsIXPConnectJSObjectHolder* GetOuterProto() { return mOuterProto; }
   nsIXPConnectJSObjectHolder* GetOuterRealProto() { return mOuterRealProto; }
 
   void DidRestoreWindow()
   {
     mInnerWindow = nsnull;
 
     mInnerWindowHolder = nsnull;
-    mNavigator = nsnull;
     mOuterProto = nsnull;
     mOuterRealProto = nsnull;
   }
 
 protected:
   ~WindowStateHolder();
 
   nsGlobalWindow *mInnerWindow;
   // We hold onto this to make sure the inner window doesn't go away. The outer
   // window ends up recalculating it anyway.
   nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
-  nsRefPtr<Navigator> mNavigator;
   nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterProto;
   nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterRealProto;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)
 
 WindowStateHolder::WindowStateHolder(nsGlobalWindow *aWindow,
                                      nsIXPConnectJSObjectHolder *aHolder,
-                                     Navigator *aNavigator,
                                      nsIXPConnectJSObjectHolder *aOuterProto,
                                      nsIXPConnectJSObjectHolder *aOuterRealProto)
   : mInnerWindow(aWindow),
-    mNavigator(aNavigator),
     mOuterProto(aOuterProto),
     mOuterRealProto(aOuterRealProto)
 {
   NS_PRECONDITION(aWindow, "null window");
   NS_PRECONDITION(aWindow->IsInnerWindow(), "Saving an outer window");
 
   mInnerWindowHolder = aHolder;
 
@@ -1925,42 +1926,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   // Remember the old document's principal.
   nsIPrincipal *oldPrincipal = nsnull;
   if (oldDoc) {
     oldPrincipal = oldDoc->NodePrincipal();
   }
 
   nsresult rv = NS_OK;
 
-  // Drop our reference to the navigator object unless we're reusing
-  // the existing inner window or the new document is from the same
-  // origin as the old document.
-  if (!reUseInnerWindow && mNavigator && oldPrincipal) {
-    bool equal;
-    rv = oldPrincipal->Equals(aDocument->NodePrincipal(), &equal);
-
-    if (NS_FAILED(rv) || !equal) {
-      // Different origins.  Release the navigator object so it gets
-      // recreated for the new document.  The plugins or mime types
-      // arrays may have changed. See bug 150087.
-      mNavigator->SetDocShell(nsnull);
-
-      mNavigator = nsnull;
-    }
-  }
-
-  if (mNavigator && aDocument != oldDoc) {
-    // We didn't drop our reference to our old navigator object and
-    // we're loading a new document. Notify the navigator object about
-    // the new document load so that it can make sure it is ready for
-    // the new document.
-
-    mNavigator->LoadingNewDocument();
-  }
-
   // Set mDocument even if this is an outer window to avoid
   // having to *always* reach into the inner window to find the
   // document.
   mDocument = do_QueryInterface(aDocument);
   mDoc = aDocument;
 
 #ifdef DEBUG
   mLastOpenedURI = aDocument->GetDocumentURI();
@@ -1968,18 +1943,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
   mContext->WillInitializeContext();
 
   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
 
   nsRefPtr<nsGlobalWindow> newInnerWindow;
 
   bool thisChrome = IsChromeWindow();
-  nsCOMPtr<nsIXPConnectJSObjectHolder> navigatorHolder;
-  jsval nav;
 
   bool isChrome = false;
 
   nsCxPusher cxPusher;
   if (!cxPusher.Push(cx)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -1989,21 +1962,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
 
   // Make sure to clear scope on the outer window *before* we
   // initialize the new inner window. If we don't, things
   // (Object.prototype etc) could leak from the old outer to the new
   // inner scope.
   mContext->ClearScope(mJSObject, false);
 
-  // This code should not be called during shutdown any more (now that
-  // we don't ever call SetNewDocument(nsnull), so no need to null
-  // check xpc here.
-  nsIXPConnect *xpc = nsContentUtils::XPConnect();
-  nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
   if (reUseInnerWindow) {
     // We're reusing the current inner window.
     NS_ASSERTION(!currentInner->IsFrozen(),
                  "We should never be reusing a shared inner window");
     newInnerWindow = currentInner;
 
     if (aDocument != oldDoc) {
       nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
@@ -2018,49 +1986,25 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       return NS_ERROR_FAILURE;
     }
   } else {
     if (aState) {
       newInnerWindow = wsh->GetInnerWindow();
       mInnerWindowHolder = wsh->GetInnerWindowHolder();
       
       NS_ASSERTION(newInnerWindow, "Got a state without inner window");
-
-      // These assignments addref.
-      mNavigator = wsh->GetNavigator();
-
-      if (mNavigator) {
-        // Update mNavigator's docshell pointer now.
-        mNavigator->SetDocShell(mDocShell);
-        mNavigator->LoadingNewDocument();
-      }
     } else if (thisChrome) {
       newInnerWindow = new nsGlobalChromeWindow(this);
       isChrome = true;
     } else if (mIsModalContentWindow) {
       newInnerWindow = new nsGlobalModalWindow(this);
     } else {
       newInnerWindow = new nsGlobalWindow(this);
     }
 
-    if (currentInner && currentInner->mJSObject) {
-      if (mNavigator && !aState) {
-        // Hold on to the navigator wrapper so that we can set
-        // window.navigator in the new window to point to the same
-        // object (assuming we didn't change origins etc). See bug
-        // 163645 for more on why we need this.
-
-        nsIDOMNavigator* navigator =
-          static_cast<nsIDOMNavigator*>(mNavigator.get());
-        nsContentUtils::WrapNative(cx, currentInner->mJSObject, navigator,
-                                   &NS_GET_IID(nsIDOMNavigator), &nav,
-                                   getter_AddRefs(navigatorHolder));
-      }
-    }
-
     if (!aState) {
       // This is redundant if we're restoring from a previous inner window.
       nsIScriptGlobalObject *sgo =
         (nsIScriptGlobalObject *)newInnerWindow.get();
 
       // Freeze the outer window and null out the inner window so
       // that initializing classes on the new inner doesn't end up
       // reaching into the old inner window for classes etc.
@@ -2284,43 +2228,16 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       }
     } else {
       rv = newInnerWindow->InnerSetNewDocument(aDocument);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // Initialize DOM classes etc on the inner window.
       rv = mContext->InitClasses(newInnerWindow->mJSObject);
       NS_ENSURE_SUCCESS(rv, rv);
-
-      if (navigatorHolder) {
-        JS_ASSERT(JSVAL_IS_OBJECT(nav));
-
-        if (js::GetObjectCompartment(JSVAL_TO_OBJECT(nav)) ==
-            js::GetObjectCompartment(newInnerWindow->mJSObject)) {
-          // Restore window.navigator onto the new inner window.
-
-          ::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
-                              nav, nsnull, nsnull,
-                              JSPROP_ENUMERATE | JSPROP_PERMANENT |
-                              JSPROP_READONLY);
-
-          // The Navigator's prototype object keeps a reference to the
-          // window in which it was first created and can thus cause that
-          // window to stay alive for too long. Reparenting it here allows
-          // the window to be collected sooner.
-          nsIDOMNavigator* navigator =
-            static_cast<nsIDOMNavigator*>(mNavigator);
-
-          xpc->
-            ReparentWrappedNativeIfFound(cx, JSVAL_TO_OBJECT(nav),
-                                         newInnerWindow->mJSObject,
-                                         navigator,
-                                         getter_AddRefs(navigatorHolder));
-        }
-      }
     }
 
     if (mArguments) {
       newInnerWindow->DefineArgumentsProperty(mArguments);
       newInnerWindow->mArguments = mArguments;
       newInnerWindow->mArgumentsOrigin = mArgumentsOrigin;
 
       mArguments = nsnull;
@@ -2497,18 +2414,18 @@ nsGlobalWindow::SetDocShell(nsIDocShell*
 #ifdef DEBUG
     nsCycleCollector_DEBUG_shouldBeFreed(mContext);
     nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
 #endif
   }
 
   mDocShell = aDocShell;        // Weak Reference
 
-  if (mNavigator)
-    mNavigator->SetDocShell(aDocShell);
+  NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
+
   if (mFrames)
     mFrames->SetDocShell(aDocShell);
   if (mScreen)
     mScreen->SetDocShell(aDocShell);
 
   if (!mDocShell) {
     MaybeForgiveSpamCount();
     CleanUp(false);
@@ -2994,22 +2911,22 @@ nsGlobalWindow::GetSelf(nsIDOMWindow** a
   *aWindow = static_cast<nsIDOMWindow*>(this);
   NS_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator)
 {
-  FORWARD_TO_OUTER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
+  FORWARD_TO_INNER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
 
   *aNavigator = nsnull;
 
   if (!mNavigator) {
-    mNavigator = new Navigator(mDocShell);
+    mNavigator = new Navigator(this);
   }
 
   NS_ADDREF(*aNavigator = mNavigator);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -9955,17 +9872,16 @@ nsGlobalWindow::SaveWindowState(nsISuppo
   nsCOMPtr<nsIXPConnectJSObjectHolder> realProtoHolder;
   if (realProto) {
     rv = xpc->HoldObject(cx, realProto, getter_AddRefs(realProtoHolder));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsISupports> state = new WindowStateHolder(inner,
                                                       mInnerWindowHolder,
-                                                      mNavigator,
                                                       proto,
                                                       realProtoHolder);
   NS_ENSURE_TRUE(state, NS_ERROR_OUT_OF_MEMORY);
 
   JSObject *wnProto;
   proto->GetJSObject(&wnProto);
   if (!JS_SetPrototype(cx, mJSObject, wnProto)) {
     return NS_ERROR_FAILURE;
--- a/dom/base/nsMimeTypeArray.cpp
+++ b/dom/base/nsMimeTypeArray.cpp
@@ -205,30 +205,33 @@ nsMimeTypeArray::NamedItem(const nsAStri
 {
   nsresult rv;
 
   NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
 
   return rv;
 }
 
-void  nsMimeTypeArray::Clear()
+void
+nsMimeTypeArray::Clear()
 {
   mInited = false;
   mMimeTypeArray.Clear();
   mPluginMimeTypeCount = 0;
 }
 
-nsresult nsMimeTypeArray::Refresh()
+void
+nsMimeTypeArray::Refresh()
 {
   Clear();
-  return GetMimeTypes();
+  GetMimeTypes();
 }
 
-nsresult nsMimeTypeArray::GetMimeTypes()
+nsresult
+nsMimeTypeArray::GetMimeTypes()
 {
   NS_PRECONDITION(!mInited && mPluginMimeTypeCount==0,
                       "already initialized");
 
   if (!mNavigator) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
--- a/dom/base/nsMimeTypeArray.h
+++ b/dom/base/nsMimeTypeArray.h
@@ -53,17 +53,17 @@ class nsMimeTypeArray : public nsIDOMMim
 {
 public:
   nsMimeTypeArray(nsIDOMNavigator* navigator);
   virtual ~nsMimeTypeArray();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMIMETYPEARRAY
 
-  nsresult Refresh();
+  void Refresh();
 
   nsIDOMMimeType* GetItemAt(PRUint32 aIndex, nsresult* aResult);
   nsIDOMMimeType* GetNamedItem(const nsAString& aName, nsresult* aResult);
 
   static nsMimeTypeArray* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
--- a/dom/base/nsPluginArray.cpp
+++ b/dom/base/nsPluginArray.cpp
@@ -50,23 +50,22 @@
 #include "nsContentUtils.h"
 #include "nsPluginHost.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsPluginArray::nsPluginArray(Navigator* navigator,
                              nsIDocShell *aDocShell)
+  : mNavigator(navigator),
+    mPluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID)),
+    mPluginCount(0),
+    mPluginArray(nsnull),
+    mDocShell(do_GetWeakReference(aDocShell))
 {
-  nsresult rv;
-  mNavigator = navigator; // don't ADDREF here, needed for parent of script object.
-  mPluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv);
-  mPluginCount = 0;
-  mPluginArray = nsnull;
-  mDocShell = aDocShell;
 }
 
 nsPluginArray::~nsPluginArray()
 {
   if (mPluginArray != nsnull) {
     for (PRUint32 i = 0; i < mPluginCount; i++) {
       NS_IF_RELEASE(mPluginArray[i]);
     }
@@ -96,18 +95,20 @@ nsPluginArray::GetLength(PRUint32* aLeng
   *aLength = 0;
   return NS_OK;
 }
 
 bool
 nsPluginArray::AllowPlugins()
 {
   bool allowPlugins = false;
-  if (mDocShell)
-    if (NS_FAILED(mDocShell->GetAllowPlugins(&allowPlugins)))
+  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell);
+
+  if (docShell)
+    if (NS_FAILED(docShell->GetAllowPlugins(&allowPlugins)))
       allowPlugins = false;
 
   return allowPlugins;
 }
 
 nsIDOMPlugin*
 nsPluginArray::GetItemAt(PRUint32 aIndex, nsresult* aResult)
 {
@@ -189,22 +190,16 @@ nsPluginArray::GetPluginHost(nsIPluginHo
 
   *aPluginHost = mPluginHost;
   NS_IF_ADDREF(*aPluginHost);
 
   return rv;
 }
 
 void
-nsPluginArray::SetDocShell(nsIDocShell *aDocShell)
-{
-  mDocShell = aDocShell;
-}
-
-void
 nsPluginArray::Invalidate()
 {
   mDocShell = nsnull;
   mNavigator = nsnull;
 }
 
 NS_IMETHODIMP
 nsPluginArray::Refresh(bool aReloadDocuments)
@@ -227,17 +222,17 @@ nsPluginArray::Refresh(bool aReloadDocum
   if(mPluginHost)
     pluginsNotChanged = (NS_ERROR_PLUGINS_PLUGINSNOTCHANGED == mPluginHost->ReloadPlugins(aReloadDocuments));
 
   // no need to reload the page if plugins have not been changed
   // in fact, if we do reload we can hit recursive load problem, see bug 93351
   if(pluginsNotChanged)
     return res;
 
-  nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mDocShell);
+  nsCOMPtr<nsIWebNavigation> webNav = do_QueryReferent(mDocShell);
 
   if (mPluginArray != nsnull) {
     for (PRUint32 i = 0; i < mPluginCount; i++) 
       NS_IF_RELEASE(mPluginArray[i]);
 
     delete[] mPluginArray;
   }
 
--- a/dom/base/nsPluginArray.h
+++ b/dom/base/nsPluginArray.h
@@ -38,16 +38,17 @@
 #ifndef nsPluginArray_h___
 #define nsPluginArray_h___
 
 #include "nsCOMPtr.h"
 #include "nsIDOMPluginArray.h"
 #include "nsIDOMPlugin.h"
 #include "nsIPluginHost.h"
 #include "nsIURL.h"
+#include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
 class Navigator;
 } // namespace dom
 } // namespace mozilla
 
 class nsIDocShell;
@@ -87,25 +88,24 @@ public:
     return static_cast<nsPluginArray*>(aSupports);
   }
 
 private:
   nsresult GetPlugins();
   bool AllowPlugins();
 
 public:
-  void SetDocShell(nsIDocShell *aDocShell);
   void Invalidate();
 
 protected:
   mozilla::dom::Navigator* mNavigator;
   nsCOMPtr<nsIPluginHost> mPluginHost;
   PRUint32 mPluginCount;
   nsIDOMPlugin** mPluginArray;
-  nsIDocShell* mDocShell; // weak reference
+  nsWeakPtr mDocShell;
 };
 
 class nsPluginElement : public nsIDOMPlugin
 {
 public:
   nsPluginElement(nsIDOMPlugin* plugin);
   virtual ~nsPluginElement();
 
--- a/dom/battery/BatteryManager.cpp
+++ b/dom/battery/BatteryManager.cpp
@@ -82,17 +82,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
 
 NS_IMPL_ADDREF_INHERITED(BatteryManager, nsDOMEventTargetWrapperCache)
 NS_IMPL_RELEASE_INHERITED(BatteryManager, nsDOMEventTargetWrapperCache)
 
 BatteryManager::BatteryManager()
   : mLevel(kDefaultLevel)
   , mCharging(kDefaultCharging)
-  , mRemainingTime(kUnknownRemainingTime)
+  , mRemainingTime(kDefaultRemainingTime)
 {
 }
 
 BatteryManager::~BatteryManager()
 {
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
@@ -186,16 +186,24 @@ BatteryManager::DispatchTrustedEventToSe
 }
 
 void
 BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
 {
   mLevel = aBatteryInfo.level();
   mCharging = aBatteryInfo.charging();
   mRemainingTime = aBatteryInfo.remainingTime();
+
+  // Add some guards to make sure the values are coherent.
+  if (mLevel == 1.0 && mCharging == true &&
+      mRemainingTime != kDefaultRemainingTime) {
+    mRemainingTime = kDefaultRemainingTime;
+    NS_ERROR("Battery API: When charging and level at 1.0, remaining time "
+             "should be 0. Please fix your backend!");
+  }
 }
 
 void
 BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo)
 {
   double previousLevel = mLevel;
   bool previousCharging = mCharging;
   double previousRemainingTime = mRemainingTime;
--- a/dom/battery/Constants.h
+++ b/dom/battery/Constants.h
@@ -43,15 +43,16 @@
  * It's not part of BatteryManager.h to prevent those backends to include it.
  */
 namespace mozilla {
 namespace dom {
 namespace battery {
 
   static const double kDefaultLevel         = 1.0;
   static const bool   kDefaultCharging      = true;
+  static const double kDefaultRemainingTime = 0;
   static const double kUnknownRemainingTime = -1;
 
 } // namespace battery
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_battery_Constants_h__
--- a/dom/battery/test/test_battery_basics.html
+++ b/dom/battery/test/test_battery_basics.html
@@ -21,14 +21,14 @@ ok(!("BatteryManager" in window), "Batte
 ok(("MozBatteryManager" in window), "MozBatteryManager should be visible");
 
 ok('mozBattery' in navigator, "navigator.mozBattery should exist");
 
 var battery = navigator.mozBattery;
 is(battery.level, 1.0, "Default battery level should be 1.0");
 is(battery.charging, true, "Default charging value should be true");
 is(battery.dischargingTime, Infinity, "Default dischargingTime should be Inifinity");
-is(battery.chargingTime, Infinity, "Default chargingTime should be Inifinity");
+is(battery.chargingTime, 0, "Default chargingTime should be 0");
 
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/apps/Makefile.in
@@ -0,0 +1,53 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is web apps.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2011
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Andreas Gal <gal@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+
+DEPTH          = ../../..
+topsrcdir      = @top_srcdir@
+srcdir         = @srcdir@
+VPATH          = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE         = dom
+XPIDL_MODULE   = dom_apps
+GRE_MODULE     = 1
+
+XPIDLSRCS =                               \
+            nsIDOMApplicationRegistry.idl \
+            $(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/apps/nsIDOMApplicationRegistry.idl
@@ -0,0 +1,89 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is web apps.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Andreas Gal <gal@mozilla.com>  (Original Author)
+ *  Fabrice Desré <fabrice@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+[scriptable, uuid(e0c271cb-266b-48c9-a7e4-96590b445c26)]
+interface mozIDOMApplicationRegistryError : nsISupports
+{
+  const unsigned short DENIED = 1;
+  const unsigned short PERMISSION_DENIED = 2;
+  const unsigned short MANIFEST_URL_ERROR = 3;
+  const unsigned short NETWORK_ERROR = 4;
+  const unsigned short MANIFEST_PARSE_ERROR = 5;
+  const unsigned short INVALID_MANIFEST = 6;
+
+  readonly attribute short code;
+};
+
+[scriptable, uuid(a6856a3d-dece-43ce-89b9-72dba07f4246)]
+interface mozIDOMApplication : nsISupports
+{
+  readonly attribute jsval manifest;
+  readonly attribute DOMString receipt;
+  readonly attribute DOMString origin;
+  readonly attribute DOMString installOrigin;
+  readonly attribute unsigned long installTime;
+};
+
+[scriptable, function, uuid(be170df5-9154-463b-9197-10a6195eba52)]
+interface mozIDOMApplicationRegistryEnumerateCallback : nsISupports
+{
+  void handleEvent([array, size_is(count)] in mozIDOMApplication apps,
+                    in unsigned long count);
+};
+
+[scriptable, function, uuid(ae0ed33d-35cf-443a-837b-a6cebf16bd49)]
+interface mozIDOMApplicationRegistryErrorCallback : nsISupports
+{
+  void handleEvent(in mozIDOMApplicationRegistryError error);
+};
+
+[scriptable, uuid(4070ea6f-dca1-4052-8bc6-7a9bcfc314ac)]
+interface mozIDOMApplicationRegistry : nsISupports
+{
+  void install(in DOMString manifestUrl,
+	       [optional] in DOMString receipt);
+  void uninstall(in DOMString origin);
+  void enumerate(in mozIDOMApplicationRegistryEnumerateCallback success,
+		 [optional] in mozIDOMApplicationRegistryErrorCallback error);
+  void launch(in DOMString origin);
+
+  attribute nsIDOMEventListener oninstall;
+  attribute nsIDOMEventListener onuninstall;
+  attribute nsIDOMEventListener onerror;
+};
--- a/dom/interfaces/base/Makefile.in
+++ b/dom/interfaces/base/Makefile.in
@@ -52,17 +52,17 @@ SDK_XPIDLSRCS =                         
 	nsIDOMWindow.idl			\
 	nsIDOMWindowCollection.idl		\
 	nsIDOMWindowUtils.idl			\
 	$(NULL)
 
 XPIDLSRCS =					\
 	nsIFrameRequestCallback.idl             \
 	nsIBrowserDOMWindow.idl			\
-    nsIContentPermissionPrompt.idl  \
+	nsIContentPermissionPrompt.idl  \
 	nsIContentPrefService.idl		\
 	nsIContentURIGrouper.idl		\
 	nsIDOMClientInformation.idl		\
 	nsIDOMConstructor.idl			\
 	nsIDOMCRMFObject.idl			\
 	nsIDOMCrypto.idl			\
 	nsIDOMHistory.idl			\
 	nsIDOMLocation.idl			\
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -892,72 +892,29 @@ TabChild::InitTabChildGlobal()
     return true;
 
   nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(mWebNav);
   NS_ENSURE_TRUE(window, false);
   nsCOMPtr<nsIDOMEventTarget> chromeHandler =
     do_QueryInterface(window->GetChromeEventHandler());
   NS_ENSURE_TRUE(chromeHandler, false);
 
-  nsCOMPtr<nsIJSRuntimeService> runtimeSvc = 
-    do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
-  NS_ENSURE_TRUE(runtimeSvc, false);
-
-  JSRuntime* rt = nsnull;
-  runtimeSvc->GetRuntime(&rt);
-  NS_ENSURE_TRUE(rt, false);
-
-  JSContext* cx = JS_NewContext(rt, 8192);
-  NS_ENSURE_TRUE(cx, false);
-
-  mCx = cx;
-
-  nsContentUtils::XPConnect()->SetSecurityManagerForJSContext(cx, nsContentUtils::GetSecurityManager(), 0);
-  nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(mPrincipal));
-
-  JS_SetNativeStackQuota(cx, 128 * sizeof(size_t) * 1024);
-
-  JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_PRIVATE_IS_NSISUPPORTS);
-  JS_SetVersion(cx, JSVERSION_LATEST);
-  JS_SetErrorReporter(cx, ContentScriptErrorReporter);
-
-  xpc_LocalizeContext(cx);
-
-  JSAutoRequest ar(cx);
-  nsIXPConnect* xpc = nsContentUtils::XPConnect();
-  const PRUint32 flags = nsIXPConnect::INIT_JS_STANDARD_CLASSES |
-                         /*nsIXPConnect::OMIT_COMPONENTS_OBJECT ?  |*/
-                         nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
-
   nsRefPtr<TabChildGlobal> scope = new TabChildGlobal(this);
   NS_ENSURE_TRUE(scope, false);
 
   mTabChildGlobal = scope;
 
   nsISupports* scopeSupports =
     NS_ISUPPORTS_CAST(nsIDOMEventTarget*, scope);
-  JS_SetContextPrivate(cx, scopeSupports);
-
-  nsresult rv =
-    xpc->InitClassesWithNewWrappedGlobal(cx, scopeSupports,
-                                         NS_GET_IID(nsISupports),
-                                         scope->GetPrincipal(), nsnull,
-                                         flags, getter_AddRefs(mGlobal));
-  NS_ENSURE_SUCCESS(rv, false);
+  
+  NS_ENSURE_TRUE(InitTabChildGlobalInternal(scopeSupports), false); 
 
   nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
   NS_ENSURE_TRUE(root, false);
   root->SetParentTarget(scope);
-  
-  JSObject* global = nsnull;
-  rv = mGlobal->GetJSObject(&global);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  JS_SetGlobalObject(cx, global);
-  DidCreateCx();
   return true;
 }
 
 bool
 TabChild::InitWidget(const nsIntSize& size)
 {
     NS_ABORT_IF_FALSE(!mWidget && !mRemoteFrame, "CreateWidget twice?");
 
--- a/dom/plugins/base/Makefile.in
+++ b/dom/plugins/base/Makefile.in
@@ -128,17 +128,20 @@ else
 	CPPSRCS += nsPluginNativeWindow.cpp
 endif
 endif
 endif
 endif
 endif
 
 LOCAL_INCLUDES += \
+  -DSK_BUILD_FOR_ANDROID_NDK \
   -I$(topsrcdir)/xpcom/base/ \
+  -I$(topsrcdir)/gfx/skia/include/core \
+  -I$(topsrcdir)/gfx/skia/include/config \
   $(MOZ_CAIRO_CFLAGS) \
   $(NULL)
 
 include $(topsrcdir)/dom/dom-config.mk
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/plugins/base/android/ANPBase.h
+++ b/dom/plugins/base/android/ANPBase.h
@@ -34,59 +34,34 @@
  * 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 "android_npapi.h"
 #include <stdlib.h>
 #include "nsAutoPtr.h"
-#include "gfxFont.h"
 #include "nsISupportsImpl.h"
 
 #define NOT_IMPLEMENTED_FATAL() do {                                    \
     __android_log_print(ANDROID_LOG_ERROR, "GeckoPlugins",              \
                         "%s not implemented %s, %d",                    \
                         __PRETTY_FUNCTION__, __FILE__, __LINE__);       \
     abort();                                                            \
   } while(0)
 
 #define NOT_IMPLEMENTED()                                               \
     __android_log_print(ANDROID_LOG_ERROR, "GeckoPlugins",              \
                         "!!!!!!!!!!!!!!  %s not implemented %s, %d",    \
                         __PRETTY_FUNCTION__, __FILE__, __LINE__);       \
 
-class gfxFont;
-
 void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i);
 void InitBitmapInterface(ANPBitmapInterfaceV0 *i);
 void InitCanvasInterface(ANPCanvasInterfaceV0 *i);
 void InitEventInterface(ANPEventInterfaceV0 *i);
 void InitLogInterface(ANPLogInterfaceV0 *i);
 void InitMatrixInterface(ANPMatrixInterfaceV0 *i);
 void InitPaintInterface(ANPPaintInterfaceV0 *i);
 void InitPathInterface(ANPPathInterfaceV0 *i);
 void InitSurfaceInterface(ANPSurfaceInterfaceV0 *i);
 void InitSystemInterface(ANPSystemInterfaceV0 *i);
 void InitTypeFaceInterface(ANPTypefaceInterfaceV0 *i);
 void InitWindowInterface(ANPWindowInterfaceV0 *i);
-
-struct ANPTypeface {
-  gfxFont* mFont;
-  nsAutoRefCnt mRefCnt;
-};
-
-
-typedef struct {
-  ANPMatrixFlag flags;
-  ANPColor color;
-  ANPPaintStyle style;
-  float strokeWidth;
-  float strokeMiter;
-  ANPPaintCap paintCap;
-  ANPPaintJoin paintJoin;
-  ANPTextEncoding textEncoding;
-  ANPPaintAlign paintAlign;
-  float textSize;
-  float textScaleX;
-  float textSkewX;
-  ANPTypeface typeface;
-} ANPPaintPrivate;
--- a/dom/plugins/base/android/ANPCanvas.cpp
+++ b/dom/plugins/base/android/ANPCanvas.cpp
@@ -1,373 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Android NPAPI support code
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Doug Turner <dougt@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "assert.h"
-#include "ANPBase.h"
-#include <android/log.h>
-
-#include "cairo.h"
-#include "gfxPlatform.h"
-#include "gfxASurface.h"
-#include "gfxImageSurface.h"
-#include "gfxUtils.h"
-#include "gfxContext.h"
-
-#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
-#define ASSIGN(obj, name)   (obj)->name = anp_canvas_##name
-
-
-ANPCanvas*
-anp_canvas_newCanvas(const ANPBitmap* bitmap)
-{
-  PRUint32 stride;
-  gfxASurface::gfxImageFormat  format;
-
-  if (bitmap->format == kRGBA_8888_ANPBitmapFormat) {
-    stride = bitmap->width * 4;
-    format = gfxImageSurface::ImageFormatARGB32;
-  }
-  else if (bitmap->format == kRGB_565_ANPBitmapFormat) {
-    stride = bitmap->width * 2;
-    format = gfxImageSurface::ImageFormatRGB16_565;
-  }
-  else {
-    LOG("%s -- Unknown format", __PRETTY_FUNCTION__);
-    return nsnull;
-  }
-
-  gfxImageSurface* pluginSurface = new gfxImageSurface(static_cast<unsigned char*>(bitmap->baseAddr),
-                                                       gfxIntSize(bitmap->width,  bitmap->height), 
-                                                       stride,
-                                                       format);
-  if (pluginSurface->CairoStatus()) {
-    LOG("%s -- %d x %d FAILED to create gfxImageSurface", __PRETTY_FUNCTION__, bitmap->width, bitmap->height);
-    return nsnull;
-  }
-
-  gfxContext *pluginContext = new gfxContext(pluginSurface);
-  NS_ADDREF(pluginContext);
-  return (ANPCanvas*) pluginContext;
-}
-
-void
-anp_canvas_deleteCanvas(ANPCanvas* canvas)
-{
-  if (!canvas)
-    return;
-  gfxContext *ctx = (gfxContext*)canvas;
-  NS_RELEASE( ctx );
-}
-
-void
-anp_canvas_save(ANPCanvas* canvas)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->Save();
-}
-
-void
-anp_canvas_restore(ANPCanvas* canvas)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->Restore();
-}
-
-void
-anp_canvas_translate(ANPCanvas* canvas, float tx, float ty)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->Translate(gfxPoint(tx,ty));
-}
-
-void
-anp_canvas_scale(ANPCanvas* canvas, float sx, float sy)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->Scale(sx, sy);
-}
-
-void
-anp_canvas_rotate(ANPCanvas* canvas, float degrees)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->Rotate(degrees);
-}
-
-void
-anp_canvas_skew(ANPCanvas* canvas, float kx, float ky)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_concat(ANPCanvas* canvas, const ANPMatrix*)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_clipRect(ANPCanvas* canvas, const ANPRectF* r)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->Clip(gfxRect(r->left,
-                    r->top,
-                    r->right - r->left,
-                    r->bottom - r->top));
-}
-
-void
-anp_canvas_clipPath(ANPCanvas* canvas, const ANPPath*)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_getTotalMatrix(ANPCanvas* canvas, ANPMatrix*)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-bool
-anp_canvas_getLocalClipBounds(ANPCanvas* canvas, ANPRectF* bounds, bool aa)
-{
-  if (!canvas)
-    return false;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-  return false;
-}
-
-bool
-anp_canvas_getDeviceClipBounds(ANPCanvas* canvas, ANPRectI* bounds)
-{
-  if (!canvas)
-    return false;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-  return false;
-}
-
-void
-anp_canvas_drawColor(ANPCanvas* canvas, ANPColor c)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->SetDeviceColor(gfxRGBA(c, gfxRGBA::PACKED_ARGB));
-  LOG("returning from %s", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_drawPaint(ANPCanvas* canvas, const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s", "                    **************   NOT IMPLEMENTED!!!");
-}
-
-void
-anp_canvas_drawLine(ANPCanvas* canvas, float x0, float y0, float x1, float y1,
-                    const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  ctx->NewPath();
-  ctx->SetColor(((ANPPaintPrivate*)paint)->color);
-  ctx->Line(gfxPoint(x0, y0), gfxPoint(x1, y1));
-  ctx->Fill();
-}
-
-void
-anp_canvas_drawRect(ANPCanvas* canvas, const ANPRectF* r, const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-
-  ctx->NewPath();
-  ctx->SetColor(((ANPPaintPrivate*)paint)->color);
-  ctx->Rectangle(gfxRect(r->left,
-                         r->top,
-                         r->right - r->left,
-                         r->bottom - r->top));
-  ctx->Fill();
-}
-
-void
-anp_canvas_drawOval(ANPCanvas* canvas, const ANPRectF* r, const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-   
-  ctx->NewPath();
-  ctx->SetColor(((ANPPaintPrivate*)paint)->color);
-
-  float sizeX = (r->right   - r->left);
-  float sizeY = (r->bottom  - r->top);
-
-  ctx->Ellipse(gfxPoint(r->left + ( sizeX / 2), r->top  + ( sizeY  / 2)),
-               gfxSize(sizeX, sizeY));
-  ctx->Fill();
-}
-
-void
-anp_canvas_drawPath(ANPCanvas* canvas, const ANPPath*, const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_drawText(ANPCanvas* canvas, const void* text, uint32_t byteLength,
-                                float x, float y, const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_drawPosText(ANPCanvas* canvas, const void* text, uint32_t byteLength,
-                       const float xy[], const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_drawBitmap(ANPCanvas* canvas, const ANPBitmap*, float x, float y,
-                      const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void
-anp_canvas_drawBitmapRect(ANPCanvas* canvas, const ANPBitmap*,
-                          const ANPRectI* src, const ANPRectF* dst,
-                          const ANPPaint* paint)
-{
-  if (!canvas)
-    return;
-
-  gfxContext* ctx = (gfxContext*)canvas;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-void InitCanvasInterface(ANPCanvasInterfaceV0 *i) {
-  _assert(i->inSize == sizeof(*i));
-  ASSIGN(i, newCanvas);
-  ASSIGN(i, deleteCanvas);
-  ASSIGN(i, save);
-  ASSIGN(i, restore);
-  ASSIGN(i, translate);
-  ASSIGN(i, scale);
-  ASSIGN(i, rotate);
-  ASSIGN(i, skew);
-  ASSIGN(i, concat);
-  ASSIGN(i, clipRect);
-  ASSIGN(i, clipPath);
-  ASSIGN(i, getTotalMatrix);
-  ASSIGN(i, getLocalClipBounds);
-  ASSIGN(i, getDeviceClipBounds);
-  ASSIGN(i, drawColor);
-  ASSIGN(i, drawPaint);
-  ASSIGN(i, drawLine);
-  ASSIGN(i, drawRect);
-  ASSIGN(i, drawOval);
-  ASSIGN(i, drawPath);
-  ASSIGN(i, drawText);
-  ASSIGN(i, drawPosText);
-  ASSIGN(i, drawBitmap);
-  ASSIGN(i, drawBitmapRect);
-}
--- a/dom/plugins/base/android/ANPPaint.cpp
+++ b/dom/plugins/base/android/ANPPaint.cpp
@@ -1,454 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Android NPAPI support code
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Doug Turner <dougt@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include <stdlib.h>
-#include <assert.h>
-#include <android/log.h>
-#include "ANPBase.h"
-
-#define LOG(args...)  
-//__android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
-#define ASSIGN(obj, name)   (obj)->name = anp_paint_##name
-
-ANPPaint*
-anp_paint_newPaint()
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) calloc(1, sizeof(ANPPaintPrivate));
-  return (ANPPaint*) p;
-}
-
-void
-anp_paint_deletePaint(ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  free((void*)p);
-}
-
-
-ANPPaintFlags
-anp_paint_getFlags(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return kAntiAlias_ANPPaintFlag;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->flags;
-}
-
-void
-anp_paint_setFlags(ANPPaint* paint, ANPPaintFlags flags)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;  
-  p->flags = flags;
-}
-
-
-ANPColor
-anp_paint_getColor(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return ANP_MAKE_COLOR(1, 255, 255, 255);
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->color;
-}
-
-void
-anp_paint_setColor(ANPPaint* paint, ANPColor color)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->color = color;
-}
-
-
-ANPPaintStyle
-anp_paint_getStyle(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return kFill_ANPPaintStyle;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->style;
-}
-
-void
-anp_paint_setStyle(ANPPaint* paint, ANPPaintStyle style)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->style = style;
-}
-
-float
-anp_paint_getStrokeWidth(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->strokeWidth;
-}
-
-float
-anp_paint_getStrokeMiter(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->strokeMiter;
-}
-
-ANPPaintCap
-anp_paint_getStrokeCap(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return kButt_ANPPaintCap;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->paintCap;
-}
-
-ANPPaintJoin
-anp_paint_getStrokeJoin(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return kMiter_ANPPaintJoin;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->paintJoin;
-}
-
-void
-anp_paint_setStrokeWidth(ANPPaint* paint, float width)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->strokeWidth = width;
-}
-
-void
-anp_paint_setStrokeMiter(ANPPaint* paint, float miter)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->strokeMiter = miter;
-}
-
-void
-anp_paint_setStrokeCap(ANPPaint* paint, ANPPaintCap cap)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->paintCap = cap;
-}
-
-void
-anp_paint_setStrokeJoin(ANPPaint* paint, ANPPaintJoin join)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->paintJoin = join;
-}
-
-
-ANPTextEncoding
-anp_paint_getTextEncoding(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return kUTF8_ANPTextEncoding;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->textEncoding;
-}
-
-ANPPaintAlign
-anp_paint_getTextAlign(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return kLeft_ANPPaintAlign;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->paintAlign;
-}
-
-float
-anp_paint_getTextSize(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->textSize;
-}
-
-float
-anp_paint_getTextScaleX(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->textScaleX;
-}
-
-float
-anp_paint_getTextSkewX(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return p->textSkewX;
-}
-
-void
-anp_paint_setTextEncoding(ANPPaint* paint, ANPTextEncoding encoding)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->textEncoding = encoding;
-}
-
-void
-anp_paint_setTextAlign(ANPPaint* paint, ANPPaintAlign align)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->paintAlign = align;  
-}
-
-void
-anp_paint_setTextSize(ANPPaint* paint, float size)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->textSize = size;
-}
-
-void
-anp_paint_setTextScaleX(ANPPaint* paint, float scale)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->textScaleX = scale;
-}
-
-void
-anp_paint_setTextSkewX(ANPPaint* paint, float skew)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  p->textSkewX = skew;
-}
-
-
-/** Return the typeface in paint, or null if there is none. This does not
-    modify the owner count of the returned typeface.
-*/
-ANPTypeface*
-anp_paint_getTypeface(const ANPPaint* paint)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return NULL;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  return &p->typeface;
-}
-
-
-/** Set the paint's typeface. If the paint already had a non-null typeface,
-    its owner count is decremented. If the new typeface is non-null, its
-    owner count is incremented.
-*/
-void
-anp_paint_setTypeface(ANPPaint* paint, ANPTypeface* typeface)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-}
-
-/** Return the width of the text. If bounds is not null, return the bounds
-    of the text in that rectangle.
-*/
-float
-anp_paint_measureText(ANPPaint* paint, const void* text, uint32_t byteLength,
-                      ANPRectF* bounds)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-  return 0;
-}
-
-
-/** Return the number of unichars specifed by the text.
-    If widths is not null, returns the array of advance widths for each
-    unichar.
-    If bounds is not null, returns the array of bounds for each unichar.
-*/
-int
-anp_paint_getTextWidths(ANPPaint* paint, const void* text, uint32_t byteLength,
-                        float widths[], ANPRectF bounds[])
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-  return 0;
-}
-
-
-/** Return in metrics the spacing values for text, respecting the paint's
-    typeface and pointsize, and return the spacing between lines
-    (descent - ascent + leading). If metrics is NULL, it will be ignored.
-*/
-float
-anp_paint_getFontMetrics(ANPPaint* paint, ANPFontMetrics* metrics)
-{
-  LOG("%s", __PRETTY_FUNCTION__);
-  if (!paint)
-    return 0;
-
-  ANPPaintPrivate* p = (ANPPaintPrivate*) paint;
-  LOG("%s is not impl.", __PRETTY_FUNCTION__);
-  return 0;
-}
-
-
-void InitPaintInterface(ANPPaintInterfaceV0 *i) {
-  _assert(i->inSize == sizeof(*i));
-  ASSIGN(i, newPaint);
-  ASSIGN(i, deletePaint);
-  ASSIGN(i, getFlags);
-  ASSIGN(i, setFlags);
-  ASSIGN(i, getColor);
-  ASSIGN(i, setColor);
-  ASSIGN(i, getStyle);
-  ASSIGN(i, setStyle);
-  ASSIGN(i, getStrokeWidth);
-  ASSIGN(i, getStrokeMiter);
-  ASSIGN(i, getStrokeCap);
-  ASSIGN(i, getStrokeJoin);
-  ASSIGN(i, setStrokeWidth);
-  ASSIGN(i, setStrokeMiter);
-  ASSIGN(i, setStrokeCap);
-  ASSIGN(i, setStrokeJoin);
-  ASSIGN(i, getTextEncoding);
-  ASSIGN(i, getTextAlign);
-  ASSIGN(i, getTextSize);
-  ASSIGN(i, getTextScaleX);
-  ASSIGN(i, getTextSkewX);
-  ASSIGN(i, setTextEncoding);
-  ASSIGN(i, setTextAlign);
-  ASSIGN(i, setTextSize);
-  ASSIGN(i, setTextScaleX);
-  ASSIGN(i, setTextSkewX);
-  ASSIGN(i, getTypeface);
-  ASSIGN(i, setTypeface);
-  ASSIGN(i, measureText);
-  ASSIGN(i, getTextWidths);
-  ASSIGN(i, getFontMetrics);
-}
--- a/dom/plugins/base/android/ANPPath.cpp
+++ b/dom/plugins/base/android/ANPPath.cpp
@@ -1,171 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Android NPAPI support code
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Doug Turner <dougt@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "assert.h"
-#include "ANPBase.h"
-#include <android/log.h>
-
-#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
-#define ASSIGN(obj, name)   (obj)->name = anp_path_##name
-
-
-// maybe this should store a list of actions (lineTo,
-// moveTo), and when canvas_drawPath() we apply all of these
-// actions to the gfxContext.
-
-ANPPath*
-anp_path_newPath()
-{
-  LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__);
-  return 0;
-}
-
-
-void
-anp_path_deletePath(ANPPath* p)
-{
-  LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__);
-}
-
-
-void
-anp_path_copy(ANPPath* dst, const ANPPath* src)
-{
-  LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__);
-}
-
-
-bool
-anp_path_equal(const ANPPath* path0, const ANPPath* path1)
-{
-  LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__);
-  return false;
-}
-
-
-void
-anp_path_reset(ANPPath* p)