Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Wed, 01 Feb 2012 14:12:11 -0800
changeset 106056 523fad03a5c43fd40cbb0643dffab36b9129f79a
parent 106055 835388761e17353e932161fe2f9cff332589b907 (current diff)
parent 86041 5b0900b3e71cd926ceb375eba0e29410fe07e3fc (diff)
child 106057 d283b00c1f730456431659c6888bcb1c86638365
child 106058 f6a781c960e27a5db007b8cb76b77d3cd5fd6375
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone13.0a1
Merge from mozilla-central.
.hgtags
accessible/src/atk/nsAccessibleWrap.cpp
accessible/src/atk/nsAccessibleWrap.h
accessible/src/base/NotificationController.cpp
accessible/src/base/nsARIAGridAccessible.cpp
accessible/src/base/nsARIAGridAccessible.h
accessible/src/base/nsAccUtils.cpp
accessible/src/base/nsAccUtils.h
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessNode.h
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsAccessibilityService.h
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsAccessible.h
accessible/src/base/nsBaseWidgetAccessible.h
accessible/src/base/nsDocAccessible.cpp
accessible/src/base/nsDocAccessible.h
accessible/src/base/nsFormControlAccessible.cpp
accessible/src/base/nsFormControlAccessible.h
accessible/src/base/nsOuterDocAccessible.cpp
accessible/src/base/nsOuterDocAccessible.h
accessible/src/base/nsRootAccessible.cpp
accessible/src/html/nsHTMLFormControlAccessible.cpp
accessible/src/html/nsHTMLFormControlAccessible.h
accessible/src/html/nsHTMLImageAccessible.cpp
accessible/src/html/nsHTMLImageAccessible.h
accessible/src/html/nsHTMLImageMapAccessible.cpp
accessible/src/html/nsHTMLLinkAccessible.cpp
accessible/src/html/nsHTMLLinkAccessible.h
accessible/src/html/nsHTMLSelectAccessible.cpp
accessible/src/html/nsHTMLSelectAccessible.h
accessible/src/html/nsHTMLTableAccessible.cpp
accessible/src/html/nsHTMLTableAccessible.h
accessible/src/html/nsHyperTextAccessible.cpp
accessible/src/html/nsHyperTextAccessible.h
accessible/src/mac/nsAccessibleWrap.h
accessible/src/mac/nsAccessibleWrap.mm
accessible/src/msaa/nsAccessNodeWrap.cpp
accessible/src/msaa/nsAccessNodeWrap.h
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/src/msaa/nsHyperTextAccessibleWrap.h
accessible/src/msaa/nsTextAccessibleWrap.cpp
accessible/src/msaa/nsTextAccessibleWrap.h
accessible/src/xforms/nsXFormsAccessible.cpp
accessible/src/xforms/nsXFormsAccessible.h
accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
accessible/src/xforms/nsXFormsFormControlsAccessible.h
accessible/src/xforms/nsXFormsWidgetsAccessible.cpp
accessible/src/xul/nsXULAlertAccessible.cpp
accessible/src/xul/nsXULAlertAccessible.h
accessible/src/xul/nsXULColorPickerAccessible.cpp
accessible/src/xul/nsXULColorPickerAccessible.h
accessible/src/xul/nsXULComboboxAccessible.cpp
accessible/src/xul/nsXULComboboxAccessible.h
accessible/src/xul/nsXULFormControlAccessible.cpp
accessible/src/xul/nsXULFormControlAccessible.h
accessible/src/xul/nsXULListboxAccessible.cpp
accessible/src/xul/nsXULListboxAccessible.h
accessible/src/xul/nsXULMenuAccessible.cpp
accessible/src/xul/nsXULMenuAccessible.h
accessible/src/xul/nsXULSliderAccessible.cpp
accessible/src/xul/nsXULSliderAccessible.h
accessible/src/xul/nsXULTabAccessible.cpp
accessible/src/xul/nsXULTreeAccessible.cpp
accessible/src/xul/nsXULTreeAccessible.h
accessible/src/xul/nsXULTreeGridAccessible.cpp
accessible/src/xul/nsXULTreeGridAccessible.h
b2g/installer/package-manifest.in
browser/app/profile/firefox.js
config/system-headers
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsNodeUtils.cpp
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsObjectLoadingContent.h
content/html/document/src/PluginDocument.cpp
content/media/nsBuiltinDecoder.h
content/media/nsBuiltinDecoderReader.h
content/media/nsBuiltinDecoderStateMachine.cpp
content/media/nsBuiltinDecoderStateMachine.h
content/media/nsMediaDecoder.h
content/media/webm/nsWebMReader.cpp
content/media/webm/nsWebMReader.h
dom/Makefile.in
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoClasses.h
dom/base/nsGlobalWindow.cpp
dom/base/nsJSEnvironment.cpp
dom/dom-config.mk
dom/interfaces/base/domstubs.idl
dom/plugins/base/android/ANPBase.h
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginHost.cpp
dom/plugins/base/nsPluginHost.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/base/nsPluginStreamListenerPeer.cpp
dom/plugins/base/nsPluginStreamListenerPeer.h
dom/plugins/test/reftest/reftest.list
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/html/nsHTMLAbsPosition.cpp
editor/libeditor/html/nsHTMLCSSUtils.cpp
editor/libeditor/html/nsHTMLCSSUtils.h
editor/libeditor/html/nsHTMLEditRules.cpp
editor/libeditor/html/nsHTMLEditUtils.cpp
editor/libeditor/html/nsHTMLEditUtils.h
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
editor/libeditor/html/nsHTMLEditorStyle.cpp
editor/libeditor/html/nsHTMLObjectResizer.cpp
editor/libeditor/text/nsPlaintextEditor.cpp
editor/libeditor/text/nsPlaintextEditor.h
editor/libeditor/text/nsTextEditRules.cpp
embedding/android/Makefile.in
js/src/config/system-headers
js/src/frontend/BytecodeEmitter.cpp
js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
js/src/jsanalyze.cpp
js/src/jsclass.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsopcode.cpp
js/src/jsopcode.h
js/src/jsopcode.tbl
js/src/jsproxy.cpp
js/src/jsscript.cpp
js/src/jsxdrapi.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/InvokeHelpers.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/String.cpp
js/xpconnect/src/XPCComponents.cpp
layout/base/nsPresShell.cpp
layout/build/Makefile.in
layout/build/nsLayoutModule.cpp
layout/generic/nsIObjectFrame.h
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
layout/generic/nsPluginUtilsOSX.mm
layout/generic/nsSelection.cpp
layout/style/nsCSSParser.cpp
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
netwerk/protocol/device/Makefile.in
netwerk/protocol/device/nsDeviceChannel.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
parser/htmlparser/src/nsParserModule.cpp
security/manager/ssl/src/SSLServerCertVerification.cpp
security/manager/ssl/src/nsNSSCallbacks.cpp
security/manager/ssl/src/nsNSSIOLayer.cpp
security/manager/ssl/src/nsNSSIOLayer.h
toolkit/mozapps/extensions/AddonRepository.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/nsWindow.cpp
widget/nsIWidget.h
widget/xpwidgets/GfxInfoX11.cpp
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
xpcom/base/nsCycleCollector.cpp
xpcom/components/nsComponentManager.cpp
--- a/.hgtags
+++ b/.hgtags
@@ -71,8 +71,10 @@ 41b84b87c816403e1b74963d8094cff0406c989e
 c0983049bcaa9551e5f276d5a77ce154c151e0b0 AURORA_BASE_20110927
 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R15
 54bfd8bf682e295ffd7f22fa921ca343957b6c1c AURORA_BASE_20111108
 a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220
 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 0000000000000000000000000000000000000000 AURORA_BASE_20120131
+0000000000000000000000000000000000000000 AURORA_BASE_20120131
+bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -157,16 +157,17 @@
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
+@BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_views.xpt
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -60,16 +60,17 @@ pref("extensions.strictCompatibility", f
 // Specifies a minimum maxVersion an addon needs to say it's compatible with
 // for it to be compatible by default.
 pref("extensions.minCompatibleAppVersion", "4.0");
 
 // Preferences for AMO integration
 pref("extensions.getAddons.cache.enabled", true);
 pref("extensions.getAddons.maxResults", 15);
 pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%");
+pref("extensions.getAddons.getWithPerformance.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
 pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%");
 pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%/%COMPATIBILITY_MODE%?src=firefox");
 pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%/%COMPATIBILITY_MODE%");
 
 // Blocklist preferences
 pref("extensions.blocklist.enabled", true);
 pref("extensions.blocklist.interval", 86400);
 // Controls what level the blocklist switches from warning about items to forcibly
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -397,16 +397,17 @@ user_pref("browser.safebrowsing.provider
 user_pref("extensions.update.url", "http://%(server)s/extensions-dummy/updateURL");
 user_pref("extensions.blocklist.url", "http://%(server)s/extensions-dummy/blocklistURL");
 user_pref("extensions.hotfix.url", "http://%(server)s/extensions-dummy/hotfixURL");
 // Make sure opening about:addons won't hit the network
 user_pref("extensions.webservice.discoverURL", "http://%(server)s/extensions-dummy/discoveryURL");
 // Make sure AddonRepository won't hit the network
 user_pref("extensions.getAddons.maxResults", 0);
 user_pref("extensions.getAddons.get.url", "http://%(server)s/extensions-dummy/repositoryGetURL");
+user_pref("extensions.getAddons.getWithPerformance.url", "http://%(server)s/extensions-dummy/repositoryGetWithPerformanceURL");
 user_pref("extensions.getAddons.search.browseURL", "http://%(server)s/extensions-dummy/repositoryBrowseURL");
 user_pref("extensions.getAddons.search.url", "http://%(server)s/extensions-dummy/repositorySearchURL");
 """ % { "server" : self.webServer + ":" + str(self.httpPort) }
     prefs.append(part)
 
     if useServerLocations == False:
       part = """
 user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect");
--- a/config/system-headers
+++ b/config/system-headers
@@ -724,16 +724,17 @@ sys/poll.h
 sys/ppc.h
 sys/prctl.h
 sys/priv.h
 sys/procfs.h
 sys/pstat.h
 sys/ptrace.h
 sys/queue.h
 sys/quota.h
+sys/reboot.h
 sys/reg.h
 sys/regset.h
 sys/resource.h
 sys/sched.h
 sys/select.h
 sys/sem.h
 sys/sendfile.h
 sys/shm.h
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1708,16 +1708,23 @@ public:
    * Utility method for getElementsByClassName.  aRootNode is the node (either
    * document or element), which getElementsByClassName was called on.
    */
   static nsresult GetElementsByClassName(nsINode* aRootNode,
                                          const nsAString& aClasses,
                                          nsIDOMNodeList** aReturn);
 
   /**
+   * Returns the widget for this document if there is one. Looks at all ancestor
+   * documents to try to find a widget, so for example this can still find a
+   * widget for documents in display:none frames that have no presentation.
+   */
+  static nsIWidget *WidgetForDocument(nsIDocument *aDoc);
+
+  /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager.
    *
    * @param aDoc the document for which to return a layer manager.
    * @param aAllowRetaining an outparam that states whether the returned
    * layer manager should be used for retained layers
--- a/content/base/public/nsIObjectLoadingContent.idl
+++ b/content/base/public/nsIObjectLoadingContent.idl
@@ -46,17 +46,17 @@ interface nsIDOMClientRect;
 %{C++
 #include "nsNPAPIPluginInstance.h"
 %}
 [ptr] native nsNPAPIPluginInstancePtr(nsNPAPIPluginInstance);
 
 /**
  * This interface represents a content node that loads objects.
  */
-[scriptable, uuid(e5330f90-91a3-41d7-b29e-af38a23a6602)]
+[scriptable, uuid(6D8914C7-0E22-4452-8962-11B69BBE84D7)]
 interface nsIObjectLoadingContent : nsISupports
 {
   const unsigned long TYPE_LOADING  = 0;
   const unsigned long TYPE_IMAGE    = 1;
   const unsigned long TYPE_PLUGIN   = 2;
   const unsigned long TYPE_DOCUMENT = 3;
   const unsigned long TYPE_NULL     = 4;
 
@@ -82,42 +82,26 @@ interface nsIObjectLoadingContent : nsIS
   /**
    * Returns the plugin instance if it has already been instantiated. This
    * will never instantiate the plugin and so is safe to call even when
    * content script must not execute.
    */
   [noscript] readonly attribute nsNPAPIPluginInstancePtr pluginInstance;
 
   /**
-   * Makes sure that a frame for this object exists, and that the plugin is
-   * instantiated. This method does nothing if the type is not #TYPE_PLUGIN.
-   * There is no guarantee that there will be a frame after this method is
-   * called; for example, the node may have a display:none style. If plugin
-   * instantiation is possible, it will be done synchronously by this method,
-   * and the plugin instance will be returned. A success return value does not
-   * necessarily mean that the instance is nonnull.
-   *
-   * This is a noscript method because it is internal and will go away once
-   * plugin loading moves to content.
-   *
-   * @note If there is an error instantiating the plugin, this method will
-   * trigger fallback to replacement content, and the type will change (and
-   * this method will return a failure code)
-   */
-  [noscript] nsNPAPIPluginInstancePtr ensureInstantiation();
-
-  /**
    * Tells the content about an associated object frame.
    * This can be called multiple times for different frames.
    *
    * This is noscript because this is an internal method that will go away, and
    * because nsIObjectFrame is unscriptable.
    */
   [noscript] void hasNewFrame(in nsIObjectFrame aFrame);
 
+  [noscript] void disconnectFrame();
+
   /**
    * If this object is in going to be printed, this method
    * returns the nsIObjectFrame object which should be used when
    * printing the plugin. The returned nsIFrame is in the original document,
    * not in the static clone.
    */
   [noscript] nsIFrame getPrintFrame();
 
@@ -126,9 +110,14 @@ interface nsIObjectLoadingContent : nsIS
                                 in AString browserDumpID,
                                 in boolean submittedCrashReport);
 
   /**
    * This method will play a plugin that has been stopped by the
    * click-to-play plugins feature.
    */
   void playPlugin();
+
+  [noscript] void stopPluginInstance();
+
+  [noscript] void syncStartPluginInstance();
+  [noscript] void asyncStartPluginInstance();
 };
--- a/content/base/public/nsISelection.idl
+++ b/content/base/public/nsISelection.idl
@@ -36,16 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 /* THIS IS A PUBLIC INTERFACE */
 
 interface nsIDOMNode;
 interface nsIDOMRange;
+interface nsINode;
 
 /**
  * Interface for manipulating and querying the current selected range
  * of nodes within the document.
  *
  * @version 1.0
  */
 
@@ -90,17 +91,17 @@ interface nsISelection : nsISupports
     /**
      * Collapses the selection to a single point, at the specified offset
      * in the given DOM node. When the selection is collapsed, and the content
      * is focused and editable, the caret will blink there.
      * @param parentNode      The given dom node where the selection will be set
      * @param offset          Where in given dom node to place the selection (the offset into the given node)
      */
     void collapse(in nsIDOMNode parentNode, in long offset);
-
+    [noscript] void collapseNative(in nsINode parentNode, in long offset);
 
     /**
      * Extends the selection by moving the selection end to the specified node and offset,
      * preserving the selection begin position. The new selection end result will always
      * be from the anchorNode to the new focusNode, regardless of direction.
      * @param parentNode      The node where the selection will be extended to
      * @param offset          Where in node to place the offset in the new selection end
      */
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -5840,19 +5840,18 @@ nsContentUtils::PlatformToDOMLineBreaks(
                              NS_LITERAL_STRING("\n").get());
 
     // Mac linebreaks: Map any remaining CR to LF:
     aString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
                              NS_LITERAL_STRING("\n").get());
   }
 }
 
-static already_AddRefed<LayerManager>
-LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
-                                bool* aAllowRetaining)
+nsIWidget *
+nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
 {
   nsIDocument* doc = aDoc;
   nsIDocument* displayDoc = doc->GetDisplayDocument();
   if (displayDoc) {
     doc = displayDoc;
   }
 
   nsIPresShell* shell = doc->GetShell();
@@ -5877,33 +5876,41 @@ LayerManagerForDocumentInternal(nsIDocum
 
   if (shell) {
     nsIViewManager* VM = shell->GetViewManager();
     if (VM) {
       nsIView* rootView = VM->GetRootView();
       if (rootView) {
         nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
         if (displayRoot) {
-          nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
-          if (widget) {
-            nsRefPtr<LayerManager> manager =
-              widget->
-                GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT : 
-                                                     nsIWidget::LAYER_MANAGER_CURRENT,
-                                aAllowRetaining);
-            return manager.forget();
-          }
+          return displayRoot->GetNearestWidget(nsnull);
         }
       }
     }
   }
 
   return nsnull;
 }
 
+static already_AddRefed<LayerManager>
+LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
+                                bool* aAllowRetaining)
+{
+  nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
+  if (widget) {
+    nsRefPtr<LayerManager> manager =
+      widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT : 
+                              nsIWidget::LAYER_MANAGER_CURRENT,
+                              aAllowRetaining);
+    return manager.forget();
+  }
+
+  return nsnull;
+}
+
 already_AddRefed<LayerManager>
 nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
 {
   return LayerManagerForDocumentInternal(aDoc, false, aAllowRetaining);
 }
 
 already_AddRefed<LayerManager>
 nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -171,16 +171,17 @@
 #include "nsIXMLContentSink.h"
 #include "nsContentErrors.h"
 #include "nsIXULDocument.h"
 #include "nsIPrompt.h"
 #include "nsIPropertyBag2.h"
 #include "nsIDOMPageTransitionEvent.h"
 #include "nsFrameLoader.h"
 #include "nsEscape.h"
+#include "nsObjectLoadingContent.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif // MOZ_MEDIA
 
 #include "mozAutoDocUpdate.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "nsDOMNavigationTiming.h"
@@ -3750,16 +3751,21 @@ NotifyActivityChanged(nsIContent *aConte
 {
 #ifdef MOZ_MEDIA
   nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
   if (domMediaElem) {
     nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aContent);
     mediaElem->NotifyOwnerDocumentActivityChanged();
   }
 #endif
+  nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aContent));
+  if (objectLoadingContent) {
+    nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
+    olc->NotifyOwnerDocumentActivityChanged();
+  }
 }
 
 void
 nsIDocument::SetContainer(nsISupports* aContainer)
 {
   mDocumentContainer = do_GetWeakReference(aContainer);
   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
 }
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -60,16 +60,17 @@
 #include "nsBindingManager.h"
 #include "nsGenericHTMLElement.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif // MOZ_MEDIA
 #include "nsImageLoadingContent.h"
 #include "jsgc.h"
 #include "nsWrapperCacheInlines.h"
+#include "nsObjectLoadingContent.h"
 
 using namespace mozilla::dom;
 
 // This macro expects the ownerDocument of content_ to be in scope as
 // |nsIDocument* doc|
 // NOTE: AttributeChildRemoved doesn't use this macro but has a very similar use.
 // If you change how this macro behave please update AttributeChildRemoved.
 #define IMPL_MUTATION_NOTIFICATION(func_, content_, params_)      \
@@ -561,25 +562,30 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
           }
           if (elm->MayHaveMouseEnterLeaveEventListener()) {
             window->SetHasMouseEnterLeaveEventListeners();
           }
         }
       }
     }
 
+    if (wasRegistered && oldDoc != newDoc) {
 #ifdef MOZ_MEDIA
-    if (wasRegistered && oldDoc != newDoc) {
       nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
       if (domMediaElem) {
         nsHTMLMediaElement* mediaElem = static_cast<nsHTMLMediaElement*>(aNode);
         mediaElem->NotifyOwnerDocumentActivityChanged();
       }
+#endif
+      nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent(do_QueryInterface(aNode));
+      if (objectLoadingContent) {
+        nsObjectLoadingContent* olc = static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
+        olc->NotifyOwnerDocumentActivityChanged();
+      }
     }
-#endif
 
     // nsImageLoadingContent needs to know when its document changes
     if (oldDoc != newDoc) {
       nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aNode));
       if (imageContent)
         imageContent->NotifyOwnerDocumentChanged(oldDoc);
     }
 
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -64,16 +64,17 @@
 #include "nsIStreamConverterService.h"
 #include "nsIURILoader.h"
 #include "nsIURL.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebNavigationInfo.h"
 #include "nsIScriptChannel.h"
 #include "nsIBlocklistService.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
+#include "nsIAppShell.h"
 
 #include "nsPluginError.h"
 
 // Util headers
 #include "prlog.h"
 
 #include "nsAutoPtr.h"
 #include "nsCURILoader.h"
@@ -93,93 +94,88 @@
 
 #include "nsObjectLoadingContent.h"
 #include "mozAutoDocUpdate.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "mozilla/dom/Element.h"
 #include "sampler.h"
+#include "nsObjectFrame.h"
+#include "nsDOMClassInfo.h"
+
+#include "nsWidgetsCID.h"
+#include "nsContentCID.h"
+static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
 #endif
 
 #define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
 
 #include "mozilla/Preferences.h"
 
 class nsAsyncInstantiateEvent : public nsRunnable {
 public:
-  // This stores both the content and the frame so that Instantiate calls can be
-  // avoided if the frame changed in the meantime.
   nsObjectLoadingContent *mContent;
-  nsWeakFrame             mFrame;
-  nsCString               mContentType;
-  nsCOMPtr<nsIURI>        mURI;
-
-  nsAsyncInstantiateEvent(nsObjectLoadingContent* aContent,
-                          nsIFrame* aFrame,
-                          const nsCString& aType,
-                          nsIURI* aURI)
-    : mContent(aContent), mFrame(aFrame), mContentType(aType), mURI(aURI)
+  nsAsyncInstantiateEvent(nsObjectLoadingContent* aContent)
+  : mContent(aContent)
   {
     static_cast<nsIObjectLoadingContent *>(mContent)->AddRef();
   }
 
   ~nsAsyncInstantiateEvent()
   {
     static_cast<nsIObjectLoadingContent *>(mContent)->Release();
   }
 
   NS_IMETHOD Run();
 };
 
 NS_IMETHODIMP
 nsAsyncInstantiateEvent::Run()
 {
-  // Check if we've been "revoked"
-  if (mContent->mPendingInstantiateEvent != this)
+  // do nothing if we've been revoked
+  if (mContent->mPendingInstantiateEvent != this) {
     return NS_OK;
+  }
   mContent->mPendingInstantiateEvent = nsnull;
 
-  // Make sure that we still have the right frame (NOTE: we don't need to check
-  // the type here - GetExistingFrame() only returns object frames, and that
-  // means we're a plugin)
-  // Also make sure that we still refer to the same data.
-  nsIObjectFrame* frame = mContent->
-    GetExistingFrame(nsObjectLoadingContent::eFlushContent);
+  return mContent->SyncStartPluginInstance();
+}
 
-  nsIFrame* objectFrame = nsnull;
-  if (frame) {
-    objectFrame = do_QueryFrame(frame);
+// Checks to see if the content for a plugin instance has a parent.
+// The plugin instance is stopped if there is no parent.
+class InDocCheckEvent : public nsRunnable {
+public:
+  nsCOMPtr<nsIContent> mContent;
+
+  InDocCheckEvent(nsIContent* aContent)
+  : mContent(aContent)
+  {
   }
 
-  if (objectFrame &&
-      mFrame.GetFrame() == objectFrame &&
-      mContent->mURI == mURI &&
-      mContent->mContentType.Equals(mContentType)) {
-    if (LOG_ENABLED()) {
-      nsCAutoString spec;
-      if (mURI) {
-        mURI->GetSpec(spec);
-      }
-      LOG(("OBJLC [%p]: Handling Instantiate event: Type=<%s> URI=%p<%s>\n",
-           mContent, mContentType.get(), mURI.get(), spec.get()));
-    }
-
-    nsresult rv = mContent->Instantiate(frame, mContentType, mURI);
-    if (NS_FAILED(rv)) {
-      mContent->Fallback(true);
-    }
-  } else {
-    LOG(("OBJLC [%p]: Discarding event, data changed\n", mContent));
+  ~InDocCheckEvent()
+  {
   }
 
+  NS_IMETHOD Run();
+};
+
+NS_IMETHODIMP
+InDocCheckEvent::Run()
+{
+  if (!mContent->IsInDoc()) {
+    nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(mContent);
+    if (olc) {
+      olc->StopPluginInstance();
+    }
+  }
   return NS_OK;
 }
 
 /**
  * A task for firing PluginNotFound and PluginBlocklisted DOM Events.
  */
 class nsPluginErrorEvent : public nsRunnable {
 public:
@@ -331,16 +327,79 @@ nsPluginCrashedEvent::Run()
   }
   variant->SetAsBool(mSubmittedCrashReport);
   containerEvent->SetData(NS_LITERAL_STRING("submittedCrashReport"), variant);
 
   nsEventDispatcher::DispatchDOMEvent(mContent, nsnull, event, nsnull, nsnull);
   return NS_OK;
 }
 
+class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  nsStopPluginRunnable(nsPluginInstanceOwner *aInstanceOwner)
+  : mInstanceOwner(aInstanceOwner)
+  {
+    NS_ASSERTION(aInstanceOwner, "need an owner");
+  }
+
+  // nsRunnable
+  NS_IMETHOD Run();
+
+  // nsITimerCallback
+  NS_IMETHOD Notify(nsITimer *timer);
+
+private:
+  nsCOMPtr<nsITimer> mTimer;
+  nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
+};
+
+NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
+
+NS_IMETHODIMP
+nsStopPluginRunnable::Notify(nsITimer *aTimer)
+{
+  return Run();
+}
+
+NS_IMETHODIMP
+nsStopPluginRunnable::Run()
+{
+  // InitWithCallback calls Release before AddRef so we need to hold a
+  // strong ref on 'this' since we fall through to this scope if it fails.
+  nsCOMPtr<nsITimerCallback> kungFuDeathGrip = this;
+  nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
+  if (appShell) {
+    PRUint32 currentLevel = 0;
+    appShell->GetEventloopNestingLevel(&currentLevel);
+    if (currentLevel > mInstanceOwner->GetLastEventloopNestingLevel()) {
+      if (!mTimer)
+        mTimer = do_CreateInstance("@mozilla.org/timer;1");
+      if (mTimer) {
+        // Fire 100ms timer to try to tear down this plugin as quickly as
+        // possible once the nesting level comes back down.
+        nsresult rv = mTimer->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT);
+        if (NS_SUCCEEDED(rv)) {
+          return rv;
+        }
+      }
+      NS_ERROR("Failed to setup a timer to stop the plugin later (at a safe "
+               "time). Stopping the plugin now, this might crash.");
+    }
+  }
+
+  mTimer = nsnull;
+
+  nsObjectLoadingContent::DoStopPlugin(mInstanceOwner, false);
+
+  return NS_OK;
+}
+
 class AutoNotifier {
   public:
     AutoNotifier(nsObjectLoadingContent* aContent, bool aNotify) :
       mContent(aContent), mNotify(aNotify) {
         mOldType = aContent->Type();
         mOldState = aContent->ObjectState();
     }
     ~AutoNotifier() {
@@ -488,34 +547,155 @@ nsObjectLoadingContent::nsObjectLoadingC
   , mChannel(nsnull)
   , mType(eType_Loading)
   , mInstantiating(false)
   , mUserDisabled(false)
   , mSuppressed(false)
   , mNetworkCreated(true)
   // If plugins.click_to_play is false, plugins should always play
   , mShouldPlay(!mozilla::Preferences::GetBool("plugins.click_to_play", false))
+  , mSrcStreamLoadInitiated(false)
   , mFallbackReason(ePluginOtherState)
 {
 }
 
 nsObjectLoadingContent::~nsObjectLoadingContent()
 {
   DestroyImageLoadingContent();
   if (mFrameLoader) {
     mFrameLoader->Destroy();
   }
 }
 
+nsresult
+nsObjectLoadingContent::InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI)
+{
+  // Don't do anything if we already have an active instance.
+  if (mInstanceOwner) {
+    return NS_OK;
+  }
+
+  // Don't allow re-entry into initialization code.
+  if (mInstantiating) {
+    return NS_OK;
+  }
+  mInstantiating = true;
+  AutoSetInstantiatingToFalse autoInstantiating(this);
+
+  // Instantiating an instance can result in script execution, which
+  // can destroy this DOM object. Don't allow that for the scope
+  // of this method.
+  nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this;
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+
+  nsCString typeToUse(aMimeType);
+  if (typeToUse.IsEmpty() && aURI) {
+    IsPluginEnabledByExtension(aURI, typeToUse, mShouldPlay);
+  }
+
+  nsCOMPtr<nsIURI> baseURI;
+  if (!aURI) {
+    // We need some URI. If we have nothing else, use the base URI.
+    // XXX(biesi): The code used to do this. Not sure why this is correct...
+    GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
+    aURI = baseURI;
+  }
+
+  // Flush layout so that the plugin is initialized with the latest information.
+  nsIDocument* doc = thisContent->GetCurrentDoc();
+  if (!doc) {
+    return NS_ERROR_FAILURE;
+  }
+  doc->FlushPendingNotifications(Flush_Layout);
+
+  nsresult rv = NS_ERROR_FAILURE;
+  nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
+  nsPluginHost* pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // If you add early return(s), be sure to balance this call to
+  // appShell->SuspendNative() with additional call(s) to
+  // appShell->ReturnNative().
+  nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
+  if (appShell) {
+    appShell->SuspendNative();
+  }
+
+  nsCOMPtr<nsIPluginDocument> pDoc(do_QueryInterface(doc));
+  bool fullPageMode = false;
+  if (pDoc) {
+    pDoc->GetWillHandleInstantiation(&fullPageMode);
+  }
+
+  if (fullPageMode) {
+    nsCOMPtr<nsIStreamListener> stream;
+    rv = pluginHost->InstantiateFullPagePlugin(aMimeType, aURI, this, getter_AddRefs(mInstanceOwner), getter_AddRefs(stream));
+    if (NS_SUCCEEDED(rv)) {
+      pDoc->SetStreamListener(stream);
+    }
+  } else {
+    rv = pluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI, this, getter_AddRefs(mInstanceOwner));
+  }
+
+  if (appShell) {
+    appShell->ResumeNative();
+  }
+
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Set up scripting interfaces.
+  NotifyContentObjectWrapper();
+
+  nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
+  GetPluginInstance(getter_AddRefs(pluginInstance));
+  if (pluginInstance) {
+    nsCOMPtr<nsIPluginTag> pluginTag;
+    pluginHost->GetPluginTagForInstance(pluginInstance, getter_AddRefs(pluginTag));
+    
+    nsCOMPtr<nsIBlocklistService> blocklist =
+    do_GetService("@mozilla.org/extensions/blocklist;1");
+    if (blocklist) {
+      PRUint32 blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
+      blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
+                                         EmptyString(), &blockState);
+      if (blockState == nsIBlocklistService::STATE_OUTDATED)
+        FirePluginError(thisContent, ePluginOutdated);
+    }
+  }
+
+  return NS_OK;
+}
+
+void
+nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged()
+{
+  if (!mInstanceOwner) {
+    return;
+  }
+
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  nsIDocument* ownerDoc = thisContent->OwnerDoc();
+  if (!ownerDoc->IsActive()) {
+    StopPluginInstance();
+  }
+}
+
 // nsIRequestObserver
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
                                        nsISupports *aContext)
 {
   SAMPLE_LABEL("nsObjectLoadingContent", "OnStartRequest");
+
+  mSrcStreamLoadInitiated = true;
+
   if (aRequest != mChannel || !aRequest) {
     // This is a bit of an edge case - happens when a new load starts before the
     // previous one got here
     return NS_BINDING_ABORTED;
   }
 
   AutoNotifier notifier(this, true);
 
@@ -537,35 +717,32 @@ nsObjectLoadingContent::OnStartRequest(n
   rv = chan->GetContentType(channelType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (channelType.EqualsASCII(APPLICATION_GUESS_FROM_EXT)) {
     channelType = APPLICATION_OCTET_STREAM;
     chan->SetContentType(channelType);
   }
 
-  // We want to use the channel type unless one of the following is
-  // true:
+  // We want to use the channel type unless one of the following is true:
   //
   // 1) The channel type is application/octet-stream and we have a
   //    type hint and the type hint is not a document type.
   // 2) Our type hint is a type that we support with a plugin.
-
   if ((channelType.EqualsASCII(APPLICATION_OCTET_STREAM) && 
        !mContentType.IsEmpty() &&
        GetTypeOfContent(mContentType) != eType_Document) ||
       // Need to check IsSupportedPlugin() in addition to GetTypeOfContent()
       // because otherwise the default plug-in's catch-all behavior would
       // confuse things.
       (IsSupportedPlugin(mContentType, mShouldPlay) && 
        GetTypeOfContent(mContentType) == eType_Plugin)) {
     // Set the type we'll use for dispatch on the channel.  Otherwise we could
     // end up trying to dispatch to a nsFrameLoader, which will complain that
     // it couldn't find a way to handle application/octet-stream
-
     nsCAutoString typeHint, dummy;
     NS_ParseContentType(mContentType, typeHint, dummy);
     if (!typeHint.IsEmpty()) {
       chan->SetContentType(typeHint);
     }
   } else {
     mContentType = channelType;
   }
@@ -688,53 +865,28 @@ nsObjectLoadingContent::OnStartRequest(n
 
       nsCOMPtr<nsIURILoader>
         uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID, &rv));
       NS_ENSURE_SUCCESS(rv, rv);
       rv = uriLoader->OpenChannel(chan, nsIURILoader::DONT_RETARGET, req,
                                   getter_AddRefs(mFinalListener));
       break;
     }
-    case eType_Plugin:
-      mInstantiating = true;
-      if (mType != newType) {
-        // This can go away once plugin loading moves to content (bug 90268)
-        mType = newType;
-        notifier.Notify();
-      }
-      nsIObjectFrame* frame;
-      frame = GetExistingFrame(eFlushLayout);
-      if (!frame) {
-        // Do nothing in this case: This is probably due to a display:none
-        // frame. If we ever get a frame, HasNewFrame will do the right thing.
-        // Abort the load though, we have no use for the data.
-        mInstantiating = false;
-        return NS_BINDING_ABORTED;
+    case eType_Plugin: {
+      nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
+      nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
+      if (!pluginHost) {
+        return NS_ERROR_NOT_AVAILABLE;
       }
-
-      {
-        nsIFrame *nsiframe = do_QueryFrame(frame);
-
-        nsWeakFrame weakFrame(nsiframe);
-
-        rv = frame->Instantiate(chan, getter_AddRefs(mFinalListener));
-
-        mInstantiating = false;
-
-        if (!weakFrame.IsAlive()) {
-          // The frame was destroyed while instantiating. Abort the load.
-          return NS_BINDING_ABORTED;
-        }
-      }
-
+      pluginHost->InstantiatePluginForChannel(chan, this, getter_AddRefs(mFinalListener));
       break;
+    }
     case eType_Loading:
       NS_NOTREACHED("Should not have a loading type here!");
     case eType_Null:
-      LOG(("OBJLC [%p]: Unsupported type, falling back\n", this));
       // Need to fallback here (instead of using the case below), so that we can
       // set mFallbackReason without it being overwritten. This is also why we
       // return early.
       Fallback(false);
 
       PluginSupportState pluginState = GetPluginSupportState(thisContent,
                                                              mContentType);
       // Do nothing, but fire the plugin not found event if needed
@@ -744,41 +896,31 @@ nsObjectLoadingContent::OnStartRequest(n
       }
       return NS_BINDING_ABORTED;
   }
 
   if (mFinalListener) {
     mType = newType;
     rv = mFinalListener->OnStartRequest(aRequest, aContext);
     if (NS_FAILED(rv)) {
-      LOG(("OBJLC [%p]: mFinalListener->OnStartRequest failed (%08x), falling back\n",
-           this, rv));
 #ifdef XP_MACOSX
       // Shockwave on Mac is special and returns an error here even when it
       // handles the content
       if (mContentType.EqualsLiteral("application/x-director")) {
-        LOG(("OBJLC [%p]: (ignoring)\n", this));
         rv = NS_OK; // otherwise, the AutoFallback will make us fall back
         return NS_BINDING_ABORTED;
       }
 #endif
       Fallback(false);
     } else if (mType == eType_Plugin) {
-      nsIObjectFrame* frame = GetExistingFrame(eFlushContent);
-      if (frame) {
-        // We have to notify the wrapper here instead of right after
-        // Instantiate because the plugin only gets instantiated by
-        // OnStartRequest, not by Instantiate.
-        frame->TryNotifyContentObjectWrapper();
-      }
+      NotifyContentObjectWrapper();
     }
     return rv;
   }
 
-  LOG(("OBJLC [%p]: Found no listener, falling back\n", this));
   Fallback(false);
   return NS_BINDING_ABORTED;
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStopRequest(nsIRequest *aRequest,
                                       nsISupports *aContext,
                                       nsresult aStatusCode)
@@ -855,174 +997,59 @@ nsObjectLoadingContent::GetActualType(ns
 
 NS_IMETHODIMP
 nsObjectLoadingContent::GetDisplayedType(PRUint32* aType)
 {
   *aType = mType;
   return NS_OK;
 }
 
-
 NS_IMETHODIMP
-nsObjectLoadingContent::EnsureInstantiation(nsNPAPIPluginInstance** aInstance)
+nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
 {
-  // Must set our out parameter to null as we have various early returns with
-  // an NS_OK result.
-  *aInstance = nsnull;
-
-  if (mType != eType_Plugin) {
+  // Not having an instance yet is OK, but try to start one now that
+  // we have a frame.
+  if (!mInstanceOwner) {
+    AsyncStartPluginInstance();
     return NS_OK;
   }
 
-  nsIObjectFrame* frame = GetExistingFrame(eFlushContent);
-  if (frame) {
-    // If we have a frame, we may have pending instantiate events; revoke
-    // them.
-    if (mPendingInstantiateEvent) {
-      LOG(("OBJLC [%p]: Revoking pending instantiate event\n", this));
-      mPendingInstantiateEvent = nsnull;
-    }
-  } else {
-    // mInstantiating is true if we're in LoadObject; we shouldn't
-    // recreate frames in that case, we'd confuse that function.
-    if (mInstantiating) {
-      return NS_OK;
-    }
-
-    // Trigger frame construction
-    mInstantiating = true;
-
-    nsCOMPtr<nsIContent> thisContent = 
-      do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
-    NS_ASSERTION(thisContent, "must be a content");
-
-    nsIDocument* doc = thisContent->GetCurrentDoc();
-    if (!doc) {
-      // Nothing we can do while plugin loading is done in layout...
-      mInstantiating = false;
-      return NS_OK;
-    }
-
-    doc->FlushPendingNotifications(Flush_Frames);
-
-    mInstantiating = false;
+  // Disconnect any existing frame
+  DisconnectFrame();
 
-    frame = GetExistingFrame(eFlushContent);
-    if (!frame) {
-      return NS_OK;
-    }
-  }
-
-  nsIFrame *nsiframe = do_QueryFrame(frame);
-
-  if (nsiframe->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
-    // A frame for this plugin element already exists now, but it has
-    // not been reflowed yet. Force a reflow now so that we don't end
-    // up initializing a plugin before knowing its size. Also re-fetch
-    // the frame, as flushing can cause the frame to be deleted.
-    frame = GetExistingFrame(eFlushLayout);
+  // Set up relationship between instance owner and frame.
+  nsObjectFrame *objFrame = static_cast<nsObjectFrame*>(aFrame);
+  mInstanceOwner->SetFrame(objFrame);
 
-    if (!frame) {
-      return NS_OK;
-    }
-
-    nsiframe = do_QueryFrame(frame);
-  }
-
-  nsWeakFrame weakFrame(nsiframe);
+  // Set up new frame to draw.
+  objFrame->FixupWindow(objFrame->GetContentRectRelativeToSelf().Size());
+  objFrame->Invalidate(objFrame->GetContentRectRelativeToSelf());
 
-  // We may have a plugin instance already; if so, do nothing
-  nsresult rv = frame->GetPluginInstance(aInstance);
-  if (!*aInstance && weakFrame.IsAlive()) {
-    rv = Instantiate(frame, mContentType, mURI);
-    if (NS_SUCCEEDED(rv) && weakFrame.IsAlive()) {
-      rv = frame->GetPluginInstance(aInstance);
-    } else {
-      Fallback(true);
-    }
-  }
-  return rv;
+  return NS_OK;
 }
 
 NS_IMETHODIMP
-nsObjectLoadingContent::HasNewFrame(nsIObjectFrame* aFrame)
+nsObjectLoadingContent::DisconnectFrame()
 {
-  LOG(("OBJLC [%p]: Got frame %p (mInstantiating=%i)\n", this, aFrame,
-       mInstantiating));
-
-  nsCOMPtr<nsIContent> thisContent = 
-    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
-  NS_ASSERTION(thisContent, "must be a content");
-  nsIDocument* doc = thisContent->OwnerDoc();
-  if (doc->IsStaticDocument() || doc->IsBeingUsedAsImage()) {
-    return NS_OK;
-  }
-
-  // "revoke" any existing instantiate event as it likely has out of
-  // date data (frame pointer etc).
-  mPendingInstantiateEvent = nsnull;
-
-  nsRefPtr<nsNPAPIPluginInstance> instance;
-  aFrame->GetPluginInstance(getter_AddRefs(instance));
-
-  if (instance) {
-    // The frame already has a plugin instance, that means the plugin
-    // has already been instantiated.
-
-    return NS_OK;
-  }
-
-  if (!mInstantiating && mType == eType_Plugin) {
-    // Asynchronously call Instantiate
-    // This can go away once plugin loading moves to content
-    // This must be done asynchronously to ensure that the frame is correctly
-    // initialized (has a view etc)
-
-    // When in a plugin document, the document will take care of calling
-    // instantiate
-    nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(GetOurDocument()));
-    if (pDoc) {
-      bool willHandleInstantiation;
-      pDoc->GetWillHandleInstantiation(&willHandleInstantiation);
-      if (willHandleInstantiation) {
-        return NS_OK;
-      }
-    }
-
-    nsIFrame* frame = do_QueryFrame(aFrame);
-    nsCOMPtr<nsIRunnable> event =
-      new nsAsyncInstantiateEvent(this, frame, mContentType, mURI);
-    if (!event) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    LOG(("                 dispatching event\n"));
-    nsresult rv = NS_DispatchToCurrentThread(event);
-    if (NS_FAILED(rv)) {
-      NS_ERROR("failed to dispatch nsAsyncInstantiateEvent");
-    } else {
-      // Remember this event.  This is a weak reference that will be cleared
-      // when the event runs.
-      mPendingInstantiateEvent = event;
-    }
+  if (mInstanceOwner) {
+    mInstanceOwner->SetFrame(nsnull);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::GetPluginInstance(nsNPAPIPluginInstance** aInstance)
 {
   *aInstance = nsnull;
 
-  nsIObjectFrame* objFrame = GetExistingFrame(eDontFlush);
-  if (!objFrame) {
+  if (!mInstanceOwner) {
     return NS_OK;
   }
 
-  return objFrame->GetPluginInstance(aInstance);
+  return mInstanceOwner->GetInstance(aInstance);
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::GetContentTypeForMIMEType(const nsACString& aMIMEType,
                                                   PRUint32* aType)
 {
   *aType = GetTypeOfContent(PromiseFlatCString(aMIMEType));
   return NS_OK;
@@ -1114,18 +1141,16 @@ nsresult
 nsObjectLoadingContent::LoadObject(const nsAString& aURI,
                                    bool aNotify,
                                    const nsCString& aTypeHint,
                                    bool aForceLoad)
 {
   LOG(("OBJLC [%p]: Loading object: URI string=<%s> notify=%i type=<%s> forceload=%i\n",
        this, NS_ConvertUTF16toUTF8(aURI).get(), aNotify, aTypeHint.get(), aForceLoad));
 
-  NS_ASSERTION(!mInstantiating, "LoadObject was reentered?");
-
   // Avoid StringToURI in order to use the codebase attribute as base URI
   nsCOMPtr<nsIContent> thisContent = 
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "must be a content");
 
   nsIDocument* doc = thisContent->OwnerDoc();
   nsCOMPtr<nsIURI> baseURI;
   GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
@@ -1160,43 +1185,36 @@ nsObjectLoadingContent::UpdateFallbackSt
 }
 
 nsresult
 nsObjectLoadingContent::LoadObject(nsIURI* aURI,
                                    bool aNotify,
                                    const nsCString& aTypeHint,
                                    bool aForceLoad)
 {
-  LOG(("OBJLC [%p]: Loading object: URI=<%p> notify=%i type=<%s> forceload=%i\n",
-       this, aURI, aNotify, aTypeHint.get(), aForceLoad));
-
-  if (mURI && aURI && !aForceLoad) {
-    bool equal;
-    nsresult rv = mURI->Equals(aURI, &equal);
-    if (NS_SUCCEEDED(rv) && equal) {
-      // URI didn't change, do nothing
-      return NS_OK;
+  // Only do a URI equality check for things that aren't stopped plugins.
+  // This is because we still need to load again if the plugin has been stopped.
+  if (mType == eType_Document || mType == eType_Image || mInstanceOwner) {
+    if (mURI && aURI && !aForceLoad) {
+      bool equal;
+      nsresult rv = mURI->Equals(aURI, &equal);
+      if (NS_SUCCEEDED(rv) && equal) {
+        // URI didn't change, do nothing
+        return NS_OK;
+      }
     }
   }
 
   // Need to revoke any potentially pending instantiate events
   if (mType == eType_Plugin && mPendingInstantiateEvent) {
-    LOG(("OBJLC [%p]: Revoking pending instantiate event\n", this));
     mPendingInstantiateEvent = nsnull;
   }
 
   AutoNotifier notifier(this, aNotify);
 
-  // AutoSetInstantiatingToFalse is instantiated after AutoNotifier, so that if
-  // the AutoNotifier triggers frame construction, events can be posted as
-  // appropriate.
-  NS_ASSERTION(!mInstantiating, "LoadObject was reentered?");
-  mInstantiating = true;
-  AutoSetInstantiatingToFalse autoset(this);
-
   mUserDisabled = mSuppressed = false;
 
   mURI = aURI;
   mContentType = aTypeHint;
 
   nsCOMPtr<nsIContent> thisContent = 
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "must be a content");
@@ -1314,17 +1332,17 @@ nsObjectLoadingContent::LoadObject(nsIUR
         // Don't notify, because we will take care of that ourselves.
         if (aURI) {
           rv = LoadImage(aURI, aForceLoad, false);
         } else {
           rv = NS_ERROR_NOT_AVAILABLE;
         }
         break;
       case eType_Plugin:
-        rv = TryInstantiate(mContentType, mURI);
+        rv = AsyncStartPluginInstance();
         break;
       case eType_Document:
         if (aURI) {
           rv = mFrameLoader->LoadURI(aURI);
         } else {
           rv = NS_ERROR_NOT_AVAILABLE;
         }
         break;
@@ -1349,27 +1367,25 @@ nsObjectLoadingContent::LoadObject(nsIUR
     if (!classid.IsEmpty()) {
       hasID = true;
       isSupportedClassID = NS_SUCCEEDED(TypeForClassID(classid, typeForID));
     }
   }
 
   if (hasID && !isSupportedClassID) {
     // We have a class ID and it's unsupported.  Fallback in that case.
-    LOG(("OBJLC [%p]: invalid classid\n", this));
     rv = NS_ERROR_NOT_AVAILABLE;
     return NS_OK;
   }
 
   if (isSupportedClassID ||
       (!aURI && !aTypeHint.IsEmpty() &&
        GetTypeOfContent(aTypeHint) == eType_Plugin)) {
     // No URI, but we have a type. The plugin will handle the load.
     // Or: supported class id, plugin will handle the load.
-    LOG(("OBJLC [%p]: (classid) Changing type from %u to eType_Plugin\n", this, mType));
     mType = eType_Plugin;
 
     // At this point, the stored content type
     // must be equal to our type hint. Similar,
     // our URI must be the requested URI.
     // (->Equals would suffice, but == is cheaper
     // and handles NULL)
     NS_ASSERTION(mContentType.Equals(aTypeHint), "mContentType wrong!");
@@ -1383,46 +1399,44 @@ nsObjectLoadingContent::LoadObject(nsIUR
       // here instead of the plugin URI for instantiation via class ID, so I
       // continue to do so. Why that is, no idea...
       GetObjectBaseURI(thisContent, getter_AddRefs(mURI));
       if (!mURI) {
         mURI = aURI;
       }
     }
 
-    rv = TryInstantiate(mContentType, mURI);
-    return NS_OK;
+    // rv is references by a stack-based object, need to assign here
+    rv = AsyncStartPluginInstance();
+
+    return rv;
   }
 
   if (!aURI) {
     // No URI and if we have got this far no enabled plugin supports the type
-    LOG(("OBJLC [%p]: no URI\n", this));
     rv = NS_ERROR_NOT_AVAILABLE;
 
     // We should only notify the UI if there is at least a type to go on for
     // finding a plugin to use, unless it's a supported image or document type.
     if (!aTypeHint.IsEmpty() && GetTypeOfContent(aTypeHint) == eType_Null) {
       UpdateFallbackState(thisContent, fallback, aTypeHint);
     }
 
     return NS_OK;
   }
 
   // E.g. mms://
   if (!CanHandleURI(aURI)) {
-    LOG(("OBJLC [%p]: can't handle URI\n", this));
     if (aTypeHint.IsEmpty()) {
       rv = NS_ERROR_NOT_AVAILABLE;
       return NS_OK;
     }
 
     if (IsSupportedPlugin(aTypeHint, mShouldPlay)) {
       mType = eType_Plugin;
-
-      rv = TryInstantiate(aTypeHint, aURI);
     } else {
       rv = NS_ERROR_NOT_AVAILABLE;
       // No plugin to load, notify of the failure.
       UpdateFallbackState(thisContent, fallback, aTypeHint);
     }
 
     return NS_OK;
   }
@@ -1489,36 +1503,46 @@ nsObjectLoadingContent::GetCapabilities(
          eSupportPlugins |
          eSupportDocuments |
          eSupportSVG;
 }
 
 void
 nsObjectLoadingContent::Fallback(bool aNotify)
 {
-  LOG(("OBJLC [%p]: Falling back (Notify=%i)\n", this, aNotify));
-
   AutoNotifier notifier(this, aNotify);
 
   UnloadContent();
 }
 
 void
 nsObjectLoadingContent::RemovedFromDocument()
 {
-  LOG(("OBJLC [%p]: Removed from doc\n", this));
   if (mFrameLoader) {
     // XXX This is very temporary and must go away
     mFrameLoader->Destroy();
     mFrameLoader = nsnull;
 
     // Clear the current URI, so that LoadObject doesn't think that we
     // have already loaded the content.
     mURI = nsnull;
   }
+
+  // When a plugin instance node is removed from the document we'll
+  // let the plugin continue to run at least until we get back to
+  // the event loop. If we get back to the event loop and the node
+  // has still not been added back to the document then we stop
+  // the plugin.
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  nsCOMPtr<nsIRunnable> event = new InDocCheckEvent(thisContent);
+
+  nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
+  if (appShell) {
+    appShell->RunInStableState(event);
+  }
 }
 
 /* static */
 void
 nsObjectLoadingContent::Traverse(nsObjectLoadingContent *tmp,
                                  nsCycleCollectionTraversalCallback &cb)
 {
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameLoader");
@@ -1773,47 +1797,23 @@ nsObjectLoadingContent::GetObjectBaseURI
     nsContentUtils::NewURIWithDocumentCharset(aURI, codebase,
                                               thisContent->OwnerDoc(),
                                               baseURI);
   } else {
     baseURI.swap(*aURI);
   }
 }
 
-nsIObjectFrame*
-nsObjectLoadingContent::GetExistingFrame(FlushType aFlushType)
+nsObjectFrame*
+nsObjectLoadingContent::GetExistingFrame()
 {
-  nsCOMPtr<nsIContent> thisContent = 
-    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
-  NS_ASSERTION(thisContent, "must be a content");
-
-  nsIFrame* frame;
-  do {
-    frame = thisContent->GetPrimaryFrame();
-    if (!frame) {
-      return nsnull;
-    }
-
-    if (aFlushType == eDontFlush) {
-      break;
-    }
-    
-    // OK, let's flush out and try again.  Note that we want to reget
-    // the document, etc, since flushing might run script.
-    nsIDocument* doc = thisContent->GetCurrentDoc();
-    NS_ASSERTION(doc, "Frame but no document?");
-    mozFlushType flushType =
-      aFlushType == eFlushLayout ? Flush_Layout : Flush_ContentAndNotify;
-    doc->FlushPendingNotifications(flushType);
-
-    aFlushType = eDontFlush;
-  } while (1);
-
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  nsIFrame* frame = thisContent->GetPrimaryFrame();
   nsIObjectFrame* objFrame = do_QueryFrame(frame);
-  return objFrame;
+  return static_cast<nsObjectFrame*>(objFrame);
 }
 
 void
 nsObjectLoadingContent::HandleBeingBlockedByContentPolicy(nsresult aStatus,
                                                           PRInt16 aRetval)
 {
   // Must call UnloadContent first, as it overwrites
   // mSuppressed/mUserDisabled. It also takes care of setting the type to
@@ -1823,115 +1823,16 @@ nsObjectLoadingContent::HandleBeingBlock
     if (aRetval == nsIContentPolicy::REJECT_TYPE) {
       mUserDisabled = true;
     } else if (aRetval == nsIContentPolicy::REJECT_SERVER) {
       mSuppressed = true;
     }
   }
 }
 
-nsresult
-nsObjectLoadingContent::TryInstantiate(const nsACString& aMIMEType,
-                                       nsIURI* aURI)
-{
-  nsIObjectFrame* frame = GetExistingFrame(eFlushContent);
-  if (!frame) {
-    LOG(("OBJLC [%p]: No frame yet\n", this));
-    return NS_OK; // Not a failure to have no frame
-  }
-
-  nsRefPtr<nsNPAPIPluginInstance> instance;
-  frame->GetPluginInstance(getter_AddRefs(instance));
-
-  if (!instance) {
-    // The frame has no plugin instance yet. If the frame hasn't been
-    // reflowed yet, do nothing as once the reflow happens we'll end up
-    // instantiating the plugin with the correct size n' all (which
-    // isn't known until we've done the first reflow). But if the
-    // frame does have a plugin instance already, be sure to
-    // re-instantiate the plugin as its source or whatnot might have
-    // chanced since it was instantiated.
-    nsIFrame* iframe = do_QueryFrame(frame);
-    if (iframe->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
-      LOG(("OBJLC [%p]: Frame hasn't been reflowed yet\n", this));
-      return NS_OK; // Not a failure to have no frame
-    }
-  }
-
-  return Instantiate(frame, aMIMEType, aURI);
-}
-
-nsresult
-nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
-                                    const nsACString& aMIMEType,
-                                    nsIURI* aURI)
-{
-  NS_ASSERTION(aFrame, "Must have a frame here");
-
-  // We're instantiating now, invalidate any pending async instantiate
-  // calls.
-  mPendingInstantiateEvent = nsnull;
-
-  // Mark that we're instantiating now so that we don't end up
-  // re-entering instantiation code.
-  bool oldInstantiatingValue = mInstantiating;
-  mInstantiating = true;
-
-  nsCString typeToUse(aMIMEType);
-  if (typeToUse.IsEmpty() && aURI) {
-    IsPluginEnabledByExtension(aURI, typeToUse, mShouldPlay);
-  }
-
-  nsCOMPtr<nsIContent> thisContent = 
-    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
-  NS_ASSERTION(thisContent, "must be a content");
-  
-  nsCOMPtr<nsIURI> baseURI;
-  if (!aURI) {
-    // We need some URI. If we have nothing else, use the base URI.
-    // XXX(biesi): The code used to do this. Not sure why this is correct...
-    GetObjectBaseURI(thisContent, getter_AddRefs(baseURI));
-    aURI = baseURI;
-  }
-
-  nsIFrame *nsiframe = do_QueryFrame(aFrame);
-  nsWeakFrame weakFrame(nsiframe);
-
-  // We'll always have a type or a URI by the time we get here
-  NS_ASSERTION(aURI || !typeToUse.IsEmpty(), "Need a URI or a type");
-  LOG(("OBJLC [%p]: Calling [%p]->Instantiate(<%s>, %p)\n", this, aFrame,
-       typeToUse.get(), aURI));
-  nsresult rv = aFrame->Instantiate(typeToUse.get(), aURI);
-
-  mInstantiating = oldInstantiatingValue;
-
-  nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
-  if (weakFrame.IsAlive()) {
-    aFrame->GetPluginInstance(getter_AddRefs(pluginInstance));
-  }
-  if (pluginInstance) {
-    nsCOMPtr<nsIPluginTag> pluginTag;
-    nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
-    static_cast<nsPluginHost*>(host.get())->
-      GetPluginTagForInstance(pluginInstance, getter_AddRefs(pluginTag));
-
-    nsCOMPtr<nsIBlocklistService> blocklist =
-      do_GetService("@mozilla.org/extensions/blocklist;1");
-    if (blocklist) {
-      PRUint32 blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
-      blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
-                                         EmptyString(), &blockState);
-      if (blockState == nsIBlocklistService::STATE_OUTDATED)
-        FirePluginError(thisContent, ePluginOutdated);
-    }
-  }
-
-  return rv;
-}
-
 /* static */ PluginSupportState
 nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
                                               const nsCString& aContentType)
 {
   if (!aContent->IsHTML()) {
     return ePluginOtherState;
   }
 
@@ -1985,20 +1886,17 @@ nsObjectLoadingContent::CreateStaticClon
 {
   nsImageLoadingContent::CreateStaticImageClone(aDest);
 
   aDest->mType = mType;
   nsObjectLoadingContent* thisObj = const_cast<nsObjectLoadingContent*>(this);
   if (thisObj->mPrintFrame.IsAlive()) {
     aDest->mPrintFrame = thisObj->mPrintFrame;
   } else {
-    nsIObjectFrame* frame =
-      const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame(eDontFlush);
-    nsIFrame* f = do_QueryFrame(frame);
-    aDest->mPrintFrame = f;
+    aDest->mPrintFrame = const_cast<nsObjectLoadingContent*>(this)->GetExistingFrame();
   }
 
   if (mFrameLoader) {
     nsCOMPtr<nsIContent> content =
       do_QueryInterface(static_cast<nsIImageLoadingContent*>(aDest));
     nsFrameLoader* fl = nsFrameLoader::Create(content->AsElement(), false);
     if (fl) {
       aDest->mFrameLoader = fl;
@@ -2041,16 +1939,179 @@ nsObjectLoadingContent::PluginCrashed(ns
   nsresult rv = NS_DispatchToCurrentThread(ev);
   if (NS_FAILED(rv)) {
     NS_WARNING("failed to dispatch nsPluginCrashedEvent");
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsObjectLoadingContent::SyncStartPluginInstance()
+{
+  NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
+               "Must be able to run script in order to instantiate a plugin instance!");
+
+  // Don't even attempt to start an instance unless the content is in the document.
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  if (!thisContent->IsInDoc()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return InstantiatePluginInstance(mContentType.get(), mURI.get());
+}
+
+NS_IMETHODIMP
+nsObjectLoadingContent::AsyncStartPluginInstance()
+{
+  // OK to have an instance already.
+  if (mInstanceOwner) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+  nsIDocument* doc = thisContent->OwnerDoc();
+  if (doc->IsStaticDocument() || doc->IsBeingUsedAsImage()) {
+    return NS_OK;
+  }
+
+  // We always start plugins on a runnable.
+  // We don't want a script blocker on the stack during instantiation.
+  nsCOMPtr<nsIRunnable> event = new nsAsyncInstantiateEvent(this);
+  if (!event) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  nsresult rv = NS_DispatchToCurrentThread(event);
+  if (NS_SUCCEEDED(rv)) {
+    // Remember this event.  This is a weak reference that will be cleared
+    // when the event runs.
+    mPendingInstantiateEvent = event;
+  }
+
+  return rv;
+}
+
+static bool
+DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop)
+{
+#if (MOZ_PLATFORM_MAEMO==5)
+  // Don't delay stop on Maemo/Hildon (bug 530739).
+  if (aDelayedStop && aInstanceOwner->MatchPluginName("Shockwave Flash"))
+    return false;
+#endif
+  
+  // Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524),
+  // XStandard (bug 430219), CMISS Zinc (bug 429604).
+  if (aDelayedStop
+#if !(defined XP_WIN || defined MOZ_X11)
+      && !aInstanceOwner->MatchPluginName("QuickTime")
+      && !aInstanceOwner->MatchPluginName("Flip4Mac")
+      && !aInstanceOwner->MatchPluginName("XStandard plugin")
+      && !aInstanceOwner->MatchPluginName("CMISS Zinc Plugin")
+#endif
+      ) {
+    nsCOMPtr<nsIRunnable> evt = new nsStopPluginRunnable(aInstanceOwner);
+    NS_DispatchToCurrentThread(evt);
+    return true;
+  }
+  return false;
+}
+
+void
+nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop)
+{
+  nsRefPtr<nsNPAPIPluginInstance> inst;
+  aInstanceOwner->GetInstance(getter_AddRefs(inst));
+  if (inst) {
+    if (DoDelayedStop(aInstanceOwner, aDelayedStop)) {
+      return;
+    }
+
+#if defined(XP_MACOSX)
+    aInstanceOwner->HidePluginWindow();
+#endif
+
+    nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
+    NS_ASSERTION(pluginHost, "Without a pluginHost, how can we have an instance to destroy?");
+    static_cast<nsPluginHost*>(pluginHost.get())->StopPluginInstance(inst);
+  }
+  
+  aInstanceOwner->Destroy();
+}
+
+NS_IMETHODIMP
+nsObjectLoadingContent::StopPluginInstance()
+{
+  if (!mInstanceOwner) {
+    return NS_OK;
+  }
+
+  DisconnectFrame();
+
+  bool delayedStop = false;
+#ifdef XP_WIN
+  // Force delayed stop for Real plugin only; see bug 420886, 426852.
+  nsRefPtr<nsNPAPIPluginInstance> inst;
+  mInstanceOwner->GetInstance(getter_AddRefs(inst));
+  if (inst) {
+    const char* mime = nsnull;
+    if (NS_SUCCEEDED(inst->GetMIMEType(&mime)) && mime) {
+      if (strcmp(mime, "audio/x-pn-realaudio-plugin") == 0) {
+        delayedStop = true;
+      }      
+    }
+  }
+#endif
+
+  DoStopPlugin(mInstanceOwner, delayedStop);
+
+  mInstanceOwner = nsnull;
+
+  return NS_OK;
+}
+
+void
+nsObjectLoadingContent::NotifyContentObjectWrapper()
+{
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+
+  nsCOMPtr<nsIDocument> doc = thisContent->GetDocument();
+  if (!doc)
+    return;
+  
+  nsIScriptGlobalObject *sgo = doc->GetScopeObject();
+  if (!sgo)
+    return;
+  
+  nsIScriptContext *scx = sgo->GetContext();
+  if (!scx)
+    return;
+  
+  JSContext *cx = scx->GetNativeContext();
+  
+  nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
+  nsContentUtils::XPConnect()->
+  GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), thisContent,
+                                 NS_GET_IID(nsISupports),
+                                 getter_AddRefs(wrapper));
+  
+  if (!wrapper) {
+    // Nothing to do here if there's no wrapper for mContent. The proto
+    // chain will be fixed appropriately when the wrapper is created.
+    return;
+  }
+  
+  JSObject *obj = nsnull;
+  nsresult rv = wrapper->GetJSObject(&obj);
+  if (NS_FAILED(rv))
+    return;
+  
+  nsHTMLPluginObjElementSH::SetupProtoChain(wrapper, cx, obj);
+}
+
+NS_IMETHODIMP
 nsObjectLoadingContent::PlayPlugin()
 {
   if (!nsContentUtils::IsCallerChrome())
     return NS_OK;
 
   mShouldPlay = true;
   return LoadObject(mURI, true, mContentType, true);
 }
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -48,21 +48,25 @@
 #include "nsImageLoadingContent.h"
 #include "nsIStreamListener.h"
 #include "nsFrameLoader.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIRunnable.h"
 #include "nsIFrame.h"
+#include "nsPluginInstanceOwner.h"
+#include "nsIThreadInternal.h"
 
 class nsAsyncInstantiateEvent;
+class nsStopPluginRunnable;
 class AutoNotifier;
 class AutoFallback;
 class AutoSetInstantiatingToFalse;
+class nsObjectFrame;
 
 enum PluginSupportState {
   ePluginUnsupported,  // The plugin is not supported (e.g. not installed)
   ePluginDisabled,     // The plugin has been explicitly disabled by the user
   ePluginBlocklisted,  // The plugin is blocklisted and disabled
   ePluginOutdated,     // The plugin is considered outdated, but not disabled
   ePluginOtherState,   // Something else (e.g. uninitialized or not a plugin)
   ePluginCrashed,
@@ -92,16 +96,18 @@ class nsObjectLoadingContent : public ns
                              , public nsIFrameLoaderOwner
                              , public nsIObjectLoadingContent
                              , public nsIInterfaceRequestor
                              , public nsIChannelEventSink
 {
   friend class AutoNotifier;
   friend class AutoFallback;
   friend class AutoSetInstantiatingToFalse;
+  friend class nsStopPluginRunnable;
+  friend class nsAsyncInstantiateEvent;
 
   public:
     // This enum's values must be the same as the constants on
     // nsIObjectLoadingContent
     enum ObjectType {
       eType_Loading  = TYPE_LOADING,  ///< Type not yet known
       eType_Image    = TYPE_IMAGE,    ///< This content is an image
       eType_Plugin   = TYPE_PLUGIN,   ///< This content is a plugin
@@ -134,16 +140,24 @@ class nsObjectLoadingContent : public ns
      * NS_EVENT_STATE_SUPPRESSED representing the current state of the object.
      */
     nsEventStates ObjectState() const;
 
     void SetIsNetworkCreated(bool aNetworkCreated)
     {
       mNetworkCreated = aNetworkCreated;
     }
+
+    // Can flush layout.
+    nsresult InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI);
+
+    void NotifyOwnerDocumentActivityChanged();
+
+    bool SrcStreamLoadInitiated() { return mSrcStreamLoadInitiated; };
+
   protected:
     /**
      * Load the object from the given URI.
      * @param aURI       The URI to load.
      * @param aNotify If true, nsIDocumentObserver state change notifications
      *                will be sent as needed.
      * @param aTypeHint  MIME Type hint. Overridden by the server unless this
      *                   class has the eOverrideServerType capability.
@@ -222,17 +236,23 @@ class nsObjectLoadingContent : public ns
      * XXX This is a temporary workaround for docshell suckyness
      */
     void RemovedFromDocument();
 
     static void Traverse(nsObjectLoadingContent *tmp,
                          nsCycleCollectionTraversalCallback &cb);
 
     void CreateStaticClone(nsObjectLoadingContent* aDest) const;
+
+    static void DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, bool aDelayedStop);
+
   private:
+
+    void NotifyContentObjectWrapper();
+
     /**
      * Check whether the given request represents a successful load.
      */
     static bool IsSuccessfulRequest(nsIRequest* aRequest);
 
     /**
      * Check whether the URI can be handled internally.
      */
@@ -283,61 +303,30 @@ class nsObjectLoadingContent : public ns
      * Gets the base URI to be used for this object. This differs from
      * nsIContent::GetBaseURI in that it takes codebase attributes into
      * account.
      */
     void GetObjectBaseURI(nsIContent* thisContent, nsIURI** aURI);
 
 
     /**
-     * Gets the frame that's associated with this content node in
-     * presentation 0. Always returns null if the node doesn't currently
-     * have a frame.
-     *
-     * @param aFlush When eFlushContent will flush content notifications
-     *               before returning a non-null value.
-     *               When eFlushLayout will flush layout and content
-     *               notifications before returning a non-null value.
-     *               When eDontFlush will never flush.
-     *         
-     *   eFlushLayout is needed in some cases by plug-ins to ensure
-     *   that NPP_SetWindow() gets called (from nsObjectFrame::DidReflow).
+     * Gets the frame that's associated with this content node.
+     * Does not flush.
      */
-    enum FlushType {
-      eFlushContent,
-      eFlushLayout,
-      eDontFlush
-    };
-    nsIObjectFrame* GetExistingFrame(FlushType aFlushType);
+    nsObjectFrame* GetExistingFrame();
 
     /**
      * Handle being blocked by a content policy.  aStatus is the nsresult
      * return value of the Should* call, while aRetval is what it returned in
      * its out parameter.
      */
     void HandleBeingBlockedByContentPolicy(nsresult aStatus,
                                            PRInt16 aRetval);
 
     /**
-     * Checks if we have a frame that's ready for instantiation, and
-     * if so, calls Instantiate(). Note that this can cause the frame
-     * to be deleted while we're instantiating the plugin.
-     */
-    nsresult TryInstantiate(const nsACString& aMIMEType, nsIURI* aURI);
-
-    /**
-     * Instantiates the plugin. This differs from
-     * GetFrame()->Instantiate() in that it ensures that the URI will
-     * be non-null, and that a MIME type will be passed. Note that
-     * this can cause the frame to be deleted while we're
-     * instantiating the plugin.
-     */
-    nsresult Instantiate(nsIObjectFrame* aFrame, const nsACString& aMIMEType, nsIURI* aURI);
-
-    /**
      * Get the plugin support state for the given content node and MIME type.
      * This is used for purposes of determining whether to fire PluginNotFound
      * events etc.  aContentType is the MIME type we ended up with.
      *
      * This should only be called if the type of this content is eType_Null.
      */
     static PluginSupportState
       GetPluginSupportState(nsIContent* aContent,
@@ -409,18 +398,21 @@ class nsObjectLoadingContent : public ns
     // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
     // it may lose the flag.
     bool                        mNetworkCreated : 1;
 
     // Used to keep track of whether or not a plugin should be played.
     // This is used for click-to-play plugins.
     bool                        mShouldPlay : 1;
 
+    // Used to indicate that a stream for a src/data attribute has been
+    // initiated so that we don't do it twice.
+    bool mSrcStreamLoadInitiated;
+
     // A specific state that caused us to fallback
     PluginSupportState          mFallbackReason;
 
     nsWeakFrame                 mPrintFrame;
 
-    friend class nsAsyncInstantiateEvent;
+    nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
 };
 
-
 #endif
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -76,16 +76,17 @@ include $(topsrcdir)/config/rules.mk
 	test_2d.composite.image.destination-atop.html \
 	test_2d.composite.image.destination-in.html \
 	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.source-out.html \
 	test_2d.composite.uncovered.image.destination-in.html \
 	test_2d.composite.uncovered.image.source-in.html \
 	test_2d.composite.uncovered.image.source-out.html \
 	test_2d.drawImage.zerocanvas.html \
+	test_2d.strokeRect.zero.5.html \
 	test_toDataURL_alpha.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_drawImage_edge_cases.html \
 	$(NULL)
@@ -109,17 +110,16 @@ endif
 #	test_2d.composite.clip.lighter.html \
 #
 
 # Tests that fail on Mac (possibly because spec is underdefined?).  Bug 407105
 ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 # XXX vlad don't test these anywhere, cairo behaviour changed
 _TEST_FILES_0 += \
 	test_2d.line.join.parallel.html \
-	test_2d.strokeRect.zero.5.html \
 	$(NULL)
 
 # This is an issue with Quartz's handling of radial gradients and some numeric
 # imprecision that results in errors here.
 _TEST_FILES_0 += \
 	test_2d.gradient.radial.inside2.html \
 	test_2d.gradient.radial.inside3.html \
 	test_2d.gradient.radial.outside1.html \
--- a/content/html/document/src/PluginDocument.cpp
+++ b/content/html/document/src/PluginDocument.cpp
@@ -42,16 +42,17 @@
 #include "nsIObjectFrame.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIPropertyBag2.h"
 #include "mozilla/dom/Element.h"
+#include "nsObjectLoadingContent.h"
 #include "sampler.h"
 
 namespace mozilla {
 namespace dom {
 
 class PluginDocument : public MediaDocument
                      , public nsIPluginDocument
 {
@@ -141,30 +142,23 @@ PluginStreamListener::SetupPlugin()
     return NS_BINDING_ABORTED;
   }
 
   // Flush out layout before we go to instantiate, because some
   // plug-ins depend on NPP_SetWindow() being called early enough and
   // nsObjectFrame does that at the end of reflow.
   shell->FlushPendingNotifications(Flush_Layout);
 
-  nsIFrame* frame = embed->GetPrimaryFrame();
-  if (!frame) {
-    mPluginDoc->AllowNormalInstantiation();
-    return NS_OK;
-  }
-
-  nsIObjectFrame* objFrame = do_QueryFrame(frame);
-  if (!objFrame) {
-    mPluginDoc->AllowNormalInstantiation();
+  nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(embed));
+  if (!olc) {
     return NS_ERROR_UNEXPECTED;
   }
-
-  nsresult rv = objFrame->Instantiate(mPluginDoc->GetType().get(),
-                                      mDocument->nsIDocument::GetDocumentURI());
+  nsObjectLoadingContent* olcc = static_cast<nsObjectLoadingContent*>(olc.get());
+  nsresult rv = olcc->InstantiatePluginInstance(mPluginDoc->GetType().get(),
+                                                mDocument->nsIDocument::GetDocumentURI());
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // Now that we're done, allow normal instantiation in the future
   // (say if there's a reframe of this entire presentation).
   mPluginDoc->AllowNormalInstantiation();
 
@@ -352,17 +346,17 @@ PluginDocument::SetStreamListener(nsIStr
 NS_IMETHODIMP
 PluginDocument::Print()
 {
   NS_ENSURE_TRUE(mPluginContent, NS_ERROR_FAILURE);
 
   nsIObjectFrame* objectFrame =
     do_QueryFrame(mPluginContent->GetPrimaryFrame());
   if (objectFrame) {
-    nsCOMPtr<nsNPAPIPluginInstance> pi;
+    nsRefPtr<nsNPAPIPluginInstance> pi;
     objectFrame->GetPluginInstance(getter_AddRefs(pi));
     if (pi) {
       NPPrint npprint;
       npprint.mode = NP_FULL;
       npprint.print.fullPrint.pluginPrinted = false;
       npprint.print.fullPrint.printOne = false;
       npprint.print.fullPrint.platformPrint = nsnull;
 
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -328,17 +328,17 @@ public:
   // the decode monitor held.
   virtual void UpdatePlaybackPosition(PRInt64 aTime) = 0;
 
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered) = 0;
 
   virtual PRInt64 VideoQueueMemoryInUse() = 0;
   virtual PRInt64 AudioQueueMemoryInUse() = 0;
 
-  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset) = 0;
+  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) = 0;
 
   // Causes the state machine to switch to buffering state, and to
   // immediately stop playback and buffer downloaded data. Must be called
   // with the decode monitor held. Called on the state machine thread and
   // the main thread.
   virtual void StartBuffering() = 0;
 
   // Sets the current size of the framebuffer used in MozAudioAvailable events.
@@ -499,17 +499,17 @@ class nsBuiltinDecoder : public nsMediaD
 
   virtual PRInt64 AudioQueueMemoryInUse() {
     if (mDecoderStateMachine) {
       return mDecoderStateMachine->AudioQueueMemoryInUse();
     }
     return 0;
   }
 
-  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset) {
+  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) {
     if (mDecoderStateMachine) {
       mDecoderStateMachine->NotifyDataArrived(aBuffer, aLength, aOffset);
     }
   }
 
   // Sets the length of the framebuffer used in MozAudioAvailable events.
   // The new size must be between 512 and 16384.
   virtual nsresult RequestFrameBufferLength(PRUint32 aLength);
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -493,17 +493,17 @@ public:
   PRInt64 AudioQueueMemoryInUse() {
     AudioQueueMemoryFunctor functor;
     mAudioQueue.LockedForEach(functor);
     return functor.mResult;
   }
 
   // Only used by nsWebMReader for now, so stub here rather than in every
   // reader than inherits from nsBuiltinDecoderReader.
-  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset) {}
+  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) {}
 
 protected:
 
   // Pumps the decode until we reach frames required to play at time aTarget
   // (usecs).
   nsresult DecodeToTarget(PRInt64 aTarget);
 
   // Reader decode function. Matches DecodeVideoFrame() and
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -1211,17 +1211,17 @@ void nsBuiltinDecoderStateMachine::Reset
   mVideoFrameEndTime = -1;
   mAudioStartTime = -1;
   mAudioEndTime = -1;
   mAudioCompleted = false;
 }
 
 void nsBuiltinDecoderStateMachine::NotifyDataArrived(const char* aBuffer,
                                                      PRUint32 aLength,
-                                                     PRUint32 aOffset)
+                                                     PRInt64 aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
 
   // While playing an unseekable stream of unknown duration, mEndTime is
   // updated (in AdvanceFrame()) as we play. But if data is being downloaded
   // faster than played, mEndTime won't reflect the end of playable data
   // since we haven't played the frame at the end of buffered data. So update
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -218,17 +218,17 @@ public:
 
   PRInt64 AudioQueueMemoryInUse() {
     if (mReader) {
       return mReader->AudioQueueMemoryInUse();
     }
     return 0;
   }
 
-  void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset);
+  void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
 
   PRInt64 GetEndMediaTime() const {
     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     return mEndTime;
   }
 
   bool IsSeekable() {
     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -330,17 +330,17 @@ public:
 
   // Called by nsChannelToPipeListener or nsMediaStream when the
   // download has ended. Called on the main thread only. aStatus is
   // the result from OnStopRequest.
   virtual void NotifyDownloadEnded(nsresult aStatus) = 0;
 
   // Called as data arrives on the stream and is read into the cache.  Called
   // on the main thread only.
-  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset) = 0;
+  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) = 0;
 
   // Cleanup internal data structures. Must be called on the main
   // thread by the owning object before that object disposes of this object.
   virtual void Shutdown();
 
   // Suspend any media downloads that are in progress. Called by the
   // media element when it is sent to the bfcache, or when we need
   // to throttle the download. Call on the main thread only. This can
--- a/content/media/webm/nsWebMBufferedParser.cpp
+++ b/content/media/webm/nsWebMBufferedParser.cpp
@@ -252,17 +252,17 @@ void nsWebMBufferedState::CalculateBuffe
   // from the ranges' start and end timestamps, so that those timestamps are
   // normalized in the range [0,duration].
 
   double startTime = (mTimeMapping[start].mTimecode * aTimecodeScale - aStartTimeOffsetNS) / NS_PER_S;
   double endTime = (mTimeMapping[end].mTimecode * aTimecodeScale - aStartTimeOffsetNS) / NS_PER_S;
   aBuffered->Add(startTime, endTime);
 }
 
-void nsWebMBufferedState::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset)
+void nsWebMBufferedState::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   PRUint32 idx;
   if (!mRangeParsers.GreatestIndexLtEq(aOffset, idx)) {
     // If the incoming data overlaps an already parsed range, adjust the
     // buffer so that we only reparse the new data.  It's also possible to
     // have an overlap where the end of the incoming data is within an
     // already parsed range, but we don't bother handling that other than by
--- a/content/media/webm/nsWebMBufferedParser.h
+++ b/content/media/webm/nsWebMBufferedParser.h
@@ -219,17 +219,17 @@ public:
   nsWebMBufferedState() : mReentrantMonitor("nsWebMBufferedState") {
     MOZ_COUNT_CTOR(nsWebMBufferedState);
   }
 
   ~nsWebMBufferedState() {
     MOZ_COUNT_DTOR(nsWebMBufferedState);
   }
 
-  void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset);
+  void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
   void CalculateBufferedForRange(nsTimeRanges* aBuffered,
                                  PRInt64 aStartOffset, PRInt64 aEndOffset,
                                  PRUint64 aTimecodeScale,
                                  PRInt64 aStartTimeOffsetNS);
 
 private:
   // Synchronizes access to the mTimeMapping array.
   ReentrantMonitor mReentrantMonitor;
--- a/content/media/webm/nsWebMReader.cpp
+++ b/content/media/webm/nsWebMReader.cpp
@@ -795,12 +795,12 @@ nsresult nsWebMReader::GetBuffered(nsTim
                                                 timecodeScale,
                                                 startTimeOffsetNS);
     }
   }
 
   return NS_OK;
 }
 
-void nsWebMReader::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset)
+void nsWebMReader::NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset)
 {
   mBufferedState->NotifyDataArrived(aBuffer, aLength, aOffset);
 }
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -156,17 +156,17 @@ public:
   {
     NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
     return mHasVideo;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
-  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRUint32 aOffset);
+  virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
 
 private:
   // Value passed to NextPacket to determine if we are reading a video or an
   // audio packet.
   enum TrackType {
     VIDEO = 0,
     AUDIO = 1
   };
--- a/content/svg/content/test/test_SVGxxxListIndexing.xhtml
+++ b/content/svg/content/test/test_SVGxxxListIndexing.xhtml
@@ -22,18 +22,16 @@ var text = document.getElementById("text
     poly = document.getElementById("poly");
     g    = document.getElementById("g");
 
 function CheckList(aListObject, aExpectedListLength, aListDescription)
 {
   is(aListObject.numberOfItems, aExpectedListLength, aListDescription + ".numberOfItems");
   is(aListObject.numberOfItems, aExpectedListLength, aListDescription + ".length");
   for (let i = 0; i < aListObject.length; i++) {
-    if (aListDescription.indexOf("SVGStringList") > -1)
-      continue;
     let item = aListObject.getItem(i);
     ok(aListObject[i] === item, aListDescription + "[" + i + "]");
   }
   ok(aListObject[aListObject.length] === void 0, aListDescription + "[outOfBounds]");
 }
 
 var tests = [
   { element: text,
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -72,16 +72,17 @@ ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 DIRS += \
   interfaces/apps \
   $(NULL)
 endif
 
 DIRS += \
   base \
   battery \
+  power \
   sms \
   src \
   locales \
   network \
   plugins/base \
   plugins/ipc \
   indexedDB \
   system \
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -64,16 +64,17 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIJSContextStack.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsUnicharUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "BatteryManager.h"
+#include "PowerManager.h"
 #include "SmsManager.h"
 #include "nsISmsService.h"
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "Connection.h"
 
 #ifdef MOZ_B2G_RIL
@@ -159,16 +160,18 @@ Navigator::Invalidate()
     mNotification = nsnull;
   }
 
   if (mBatteryManager) {
     mBatteryManager->Shutdown();
     mBatteryManager = nsnull;
   }
 
+  mPowerManager = nsnull;
+
   if (mSmsManager) {
     mSmsManager->Shutdown();
     mSmsManager = nsnull;
   }
 
 #ifdef MOZ_B2G_RIL
   if (mTelephony) {
     mTelephony = nsnull;
@@ -934,16 +937,28 @@ Navigator::GetMozBattery(nsIDOMMozBatter
     mBatteryManager->Init(win, scx);
   }
 
   NS_ADDREF(*aBattery = mBatteryManager);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+Navigator::GetMozPower(nsIDOMMozPowerManager** aPower)
+{
+  if (!mPowerManager) {
+    mPowerManager = new power::PowerManager();
+  }
+
+  NS_ADDREF(*aPower = mPowerManager);
+
+  return NS_OK;
+}
+
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorSms
 //*****************************************************************************
 
 bool
 Navigator::IsSmsAllowed() const
 {
   static const bool defaultSmsPermission = false;
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -79,16 +79,20 @@ class BatteryManager;
 namespace sms {
 class SmsManager;
 } // namespace sms
 
 namespace network {
 class Connection;
 } // namespace Connection;
 
+namespace power {
+class PowerManager;
+} // namespace power
+
 class Navigator : public nsIDOMNavigator
                 , public nsIDOMClientInformation
                 , public nsIDOMNavigatorGeolocation
                 , public nsIDOMNavigatorDesktopNotification
                 , public nsIDOMMozNavigatorBattery
                 , public nsIDOMMozNavigatorSms
 #ifdef MOZ_B2G_RIL
                 , public nsIDOMNavigatorTelephony
@@ -131,16 +135,17 @@ private:
   bool IsSmsAllowed() const;
   bool IsSmsSupported() const;
 
   nsRefPtr<nsMimeTypeArray> mMimeTypes;
   nsRefPtr<nsPluginArray> mPlugins;
   nsRefPtr<nsGeolocation> mGeolocation;
   nsRefPtr<nsDesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
+  nsRefPtr<power::PowerManager> mPowerManager;
   nsRefPtr<sms::SmsManager> mSmsManager;
 #ifdef MOZ_B2G_RIL
   nsCOMPtr<nsIDOMTelephony> mTelephony;
 #endif
   nsRefPtr<network::Connection> mConnection;
   nsWeakPtr mWindow;
 };
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -483,16 +483,17 @@
 #include "mozilla/dom/Element.h"
 #include "nsHTMLSelectElement.h"
 #include "nsHTMLLegendElement.h"
 
 #include "DOMSVGLengthList.h"
 #include "DOMSVGNumberList.h"
 #include "DOMSVGPathSegList.h"
 #include "DOMSVGPointList.h"
+#include "DOMSVGStringList.h"
 #include "DOMSVGTransformList.h"
 
 #include "mozilla/dom/indexedDB/IDBWrapperCache.h"
 #include "mozilla/dom/indexedDB/IDBFactory.h"
 #include "mozilla/dom/indexedDB/IDBRequest.h"
 #include "mozilla/dom/indexedDB/IDBDatabase.h"
 #include "mozilla/dom/indexedDB/IDBEvents.h"
 #include "mozilla/dom/indexedDB/IDBObjectStore.h"
@@ -509,16 +510,17 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "nsDOMTouchEvent.h"
 #include "nsIDOMCustomEvent.h"
 
 #include "nsWrapperCacheInlines.h"
 #include "dombindings.h"
 
 #include "nsIDOMBatteryManager.h"
 #include "BatteryManager.h"
+#include "nsIDOMPowerManager.h"
 #include "nsIDOMSmsManager.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsIDOMSmsEvent.h"
 #include "nsIDOMSmsRequest.h"
 #include "nsIDOMSmsFilter.h"
 #include "nsIDOMSmsCursor.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMConnection.h"
@@ -1288,18 +1290,18 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(SVGPoint, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGPointList, nsSVGPointListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGPreserveAspectRatio, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGRect, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(SVGStringList, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)    
+  NS_DEFINE_CLASSINFO_DATA(SVGStringList, nsSVGStringListSH,
+                           ARRAY_SCRIPTABLE_FLAGS)    
   NS_DEFINE_CLASSINFO_DATA(SVGTransform, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGTransformList, nsSVGTransformListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGZoomEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(HTMLCanvasElement, nsElementSH,
@@ -1438,16 +1440,19 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(GeoPositionError, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozBatteryManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
+  NS_DEFINE_CLASSINFO_DATA(MozPowerManager, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
   NS_DEFINE_CLASSINFO_DATA(MozSmsManager, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozSmsEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -4027,16 +4032,20 @@ nsDOMClassInfo::Init()
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMGeoPositionError)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozBatteryManager, nsIDOMMozBatteryManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozBatteryManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(MozPowerManager, nsIDOMMozPowerManager)
+     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozPowerManager)
+  DOM_CLASSINFO_MAP_END
+
   DOM_CLASSINFO_MAP_BEGIN(MozSmsManager, nsIDOMMozSmsManager)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsManager)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozSmsMessage, nsIDOMMozSmsMessage)
      DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage)
   DOM_CLASSINFO_MAP_END
 
@@ -9554,61 +9563,47 @@ nsHTMLSelectElementSH::SetProperty(nsIXP
     return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
   }
 
   return NS_OK;
 }
 
 
 // HTMLObject/EmbedElement helper
-
+// Keep in mind that it is OK for this to fail to return an instance. Don't return a
+// failure result unless something truly exceptional has happened.
 // static
 nsresult
 nsHTMLPluginObjElementSH::GetPluginInstanceIfSafe(nsIXPConnectWrappedNative *wrapper,
                                                   JSObject *obj,
                                                   nsNPAPIPluginInstance **_result)
 {
   *_result = nsnull;
 
   nsCOMPtr<nsIContent> content(do_QueryWrappedNative(wrapper, obj));
   NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
 
   nsCOMPtr<nsIObjectLoadingContent> objlc(do_QueryInterface(content));
   NS_ASSERTION(objlc, "Object nodes must implement nsIObjectLoadingContent");
 
-  // If it's not safe to run script we'll only return the instance if it
-  // exists.
+  nsresult rv = objlc->GetPluginInstance(_result);
+  if (NS_SUCCEEDED(rv) && *_result) {
+    return rv;
+  }
+
+  // If it's not safe to run script we'll only return the instance if it exists.
   if (!nsContentUtils::IsSafeToRunScript()) {
-    return objlc->GetPluginInstance(_result);
-  }
-
-  // Make sure that there is a plugin
-  return objlc->EnsureInstantiation(_result);
-}
-
-// Check if proto is already in obj's prototype chain.
-
-static bool
-IsObjInProtoChain(JSContext *cx, JSObject *obj, JSObject *proto)
-{
-  JSObject *o = obj;
-
-  JSAutoRequest ar(cx);
-
-  while (o) {
-    JSObject *p = ::JS_GetPrototype(cx, o);
-
-    if (p == proto) {
-      return true;
-    }
-
-    o = p;
-  }
-
-  return false;
+    return rv;
+  }
+
+  // We don't care if this actually starts the plugin or not, we just want to
+  // try to start it now if possible.
+  objlc->SyncStartPluginInstance();
+
+  return objlc->GetPluginInstance(_result);
 }
 
 class nsPluginProtoChainInstallRunner : public nsIRunnable
 {
 public:
   NS_DECL_ISUPPORTS
 
   nsPluginProtoChainInstallRunner(nsIXPConnectWrappedNative* wrapper,
@@ -9680,30 +9675,19 @@ nsHTMLPluginObjElementSH::SetupProtoChai
   JSObject *pi_obj = nsnull; // XPConnect-wrapped peer object, when we get it.
   JSObject *pi_proto = nsnull; // 'pi.__proto__'
 
   rv = GetPluginJSObject(cx, obj, pi, &pi_obj, &pi_proto);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!pi_obj) {
     // Didn't get a plugin instance JSObject, nothing we can do then.
-
     return NS_OK;
   }
 
-  if (IsObjInProtoChain(cx, obj, pi_obj)) {
-    // We must have re-entered ::PostCreate() from nsObjectFrame()
-    // (through the EnsureInstantiation() call in
-    // GetPluginInstanceIfSafe()), this means that we've already done what
-    // we're about to do in this function so we can just return here.
-
-    return NS_OK;
-  }
-
-
   // If we got an xpconnect-wrapped plugin object, set obj's
   // prototype's prototype to the scriptable plugin.
 
   JSObject *my_proto = nsnull;
 
   // Get 'this.__proto__'
   rv = wrapper->GetJSObjectPrototype(&my_proto);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -10901,8 +10885,50 @@ nsSVGListSH<ListInterfaceType, ListType>
     // question doesn't use the nsIDOMSVGXXXList pointer as the nsISupports
     // pointer. That must be fixed, or we'll crash...
     NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
   }
 #endif
 
   return list->GetItemWithoutAddRef(aIndex);
 }
+
+
+// SVGStringList helper
+
+nsresult
+nsSVGStringListSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
+                               nsAString& aResult)
+{
+  if (aIndex < 0) {
+    SetDOMStringToNull(aResult);
+    return NS_OK;
+  }
+
+  DOMSVGStringList* list = static_cast<DOMSVGStringList*>(
+                             static_cast<nsIDOMSVGStringList*>(aNative));
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsIDOMSVGStringList> list_qi = do_QueryInterface(aNative);
+    
+    // If this assertion fires the QI implementation for the object in
+    // question doesn't use the nsIDOMDOMSVGStringList pointer as the
+    // nsISupports pointer. That must be fixed, or we'll crash...
+    NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!");
+  }
+#endif
+
+  nsresult rv = list->GetItem(aIndex, aResult);
+#ifdef DEBUG
+  if (DOMStringIsNull(aResult)) {
+    PRUint32 length = 0;
+    list->GetLength(&length);
+    NS_ASSERTION(PRUint32(aIndex) >= length, "Item should only return null for out-of-bounds access");
+  }
+#endif
+  if (rv == NS_ERROR_DOM_INDEX_SIZE_ERR) {
+    SetDOMStringToNull(aResult);
+    rv = NS_OK;
+  }
+  return rv;
+}
+
+
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -1743,9 +1743,32 @@ public:
 };
 
 typedef nsSVGListSH<nsIDOMSVGLengthList, mozilla::DOMSVGLengthList> nsSVGLengthListSH;
 typedef nsSVGListSH<nsIDOMSVGNumberList, mozilla::DOMSVGNumberList> nsSVGNumberListSH;
 typedef nsSVGListSH<nsIDOMSVGPathSegList, mozilla::DOMSVGPathSegList> nsSVGPathSegListSH;
 typedef nsSVGListSH<nsIDOMSVGPointList, mozilla::DOMSVGPointList> nsSVGPointListSH;
 typedef nsSVGListSH<nsIDOMSVGTransformList, mozilla::DOMSVGTransformList> nsSVGTransformListSH;
 
+// SVGStringList helper
+
+class nsSVGStringListSH : public nsStringArraySH
+{
+protected:
+  nsSVGStringListSH(nsDOMClassInfoData* aData) : nsStringArraySH(aData)
+  {
+  }
+  
+  virtual ~nsSVGStringListSH()
+  {
+  }
+  
+  virtual nsresult GetStringAt(nsISupports *aNative, PRInt32 aIndex,
+                               nsAString& aResult);
+  
+public:
+  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
+  {
+    return new nsSVGStringListSH(aData);
+  }
+};
+
 #endif /* nsDOMClassInfo_h___ */
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -425,16 +425,18 @@ DOMCI_CLASS(MessageEvent)
 DOMCI_CLASS(GeoGeolocation)
 DOMCI_CLASS(GeoPosition)
 DOMCI_CLASS(GeoPositionCoords)
 DOMCI_CLASS(GeoPositionAddress)
 DOMCI_CLASS(GeoPositionError)
 
 DOMCI_CLASS(MozBatteryManager)
 
+DOMCI_CLASS(MozPowerManager)
+
 DOMCI_CLASS(MozSmsManager)
 DOMCI_CLASS(MozSmsMessage)
 DOMCI_CLASS(MozSmsEvent)
 DOMCI_CLASS(MozSmsRequest)
 DOMCI_CLASS(MozSmsFilter)
 DOMCI_CLASS(MozSmsCursor)
 
 DOMCI_CLASS(MozConnection)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -527,17 +527,17 @@ NS_IMETHODIMP
 nsDummyJavaPluginOwner::GetWindow(NPWindow *&aWindow)
 {
   aWindow = nsnull;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDummyJavaPluginOwner::SetWindow()
+nsDummyJavaPluginOwner::CallSetWindow()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsDummyJavaPluginOwner::GetMode(PRInt32 *aMode)
 {
   // This is wrong, but there's no better alternative.
@@ -7675,19 +7675,19 @@ void nsGlobalWindow::UpdateTouchState()
   if (!mainWidget)
     return;
 
   if (mMayHaveTouchEventListener) {
     mainWidget->RegisterTouchWindow();
 
     nsCOMPtr<nsIObserverService> observerService =
       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+
     if (observerService) {
-      nsPIDOMWindow *inner = GetCurrentInnerWindowInternal();
-      observerService->NotifyObservers(mainWidget,
+      observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
                                        DOM_TOUCH_LISTENER_ADDED,
                                        nsnull);
     }
   } else {
     mainWidget->UnregisterTouchWindow();
   }
 }
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3376,33 +3376,34 @@ CCTimerFired(nsITimer *aTimer, void *aCl
   }
   ++sCCTimerFireCount;
   if (sCCTimerFireCount < (NS_CC_DELAY / NS_CC_SKIPPABLE_DELAY)) {
     PRUint32 suspected = nsCycleCollector_suspectedCount();
     if ((sPreviousSuspectedCount + 100) > suspected) {
       // Just few new suspected objects, return early.
       return;
     }
-    sPreviousSuspectedCount = suspected;
+    
     PRTime startTime;
     if (sPostGCEventsToConsole) {
       startTime = PR_Now();
     }
     nsCycleCollector_forgetSkippable();
+    sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
     sCleanupSinceLastGC = true;
     if (sPostGCEventsToConsole) {
       PRTime delta = PR_Now() - startTime;
       if (sMinForgetSkippableTime > delta) {
         sMinForgetSkippableTime = delta;
       }
       if (sMaxForgetSkippableTime < delta) {
         sMaxForgetSkippableTime = delta;
       }
       sTotalForgetSkippableTime += delta;
-      sRemovedPurples += (suspected - nsCycleCollector_suspectedCount());
+      sRemovedPurples += (suspected - sPreviousSuspectedCount);
       ++sForgetSkippableBeforeCC;
     }
   } else {
     sPreviousSuspectedCount = 0;
     nsJSContext::KillCCTimer();
     if (nsCycleCollector_suspectedCount() > 500 ||
         sLastCCEndTime + NS_CC_FORCED < PR_Now()) {
       nsJSContext::CycleCollectNow();
@@ -3490,17 +3491,17 @@ nsJSContext::PokeShrinkGCBuffers()
                                               NS_SHRINK_GC_BUFFERS_DELAY,
                                               nsITimer::TYPE_ONE_SHOT);
 }
 
 // static
 void
 nsJSContext::MaybePokeCC()
 {
-  if (sCCTimer) {
+  if (sCCTimer || sDidShutdown) {
     return;
   }
 
   if (nsCycleCollector_suspectedCount() > 100 ||
       sLastCCEndTime + NS_CC_FORCED < PR_Now()) {
     sCCTimerFireCount = 0;
     CallCreateInstance("@mozilla.org/timer;1", &sCCTimer);
     if (!sCCTimer) {
--- a/dom/dom-config.mk
+++ b/dom/dom-config.mk
@@ -1,11 +1,12 @@
 DOM_SRCDIRS = \
   dom/base \
   dom/battery \
+  dom/power \
   dom/network/src \
   dom/sms/src \
   dom/src/events \
   dom/src/storage \
   dom/src/offline \
   dom/src/geolocation \
   dom/src/notification \
   dom/workers \
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -124,8 +124,11 @@ interface nsIDOMRange;
 // Crypto
 interface nsIDOMCRMFObject;
 interface nsIDOMCrypto;
 interface nsIDOMPkcs11;
 
 // Used font face (for inspector)
 interface nsIDOMFontFace;
 interface nsIDOMFontFaceList;
+
+// Power
+interface nsIDOMMozPowerManager;
--- a/dom/interfaces/base/nsIDOMNavigator.idl
+++ b/dom/interfaces/base/nsIDOMNavigator.idl
@@ -34,36 +34,37 @@
  * 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(a1ee08c1-0299-4908-a6ba-7cBc8da6531f)]
+[scriptable, uuid(b1f4b1fa-49c2-4375-9ce8-bf97ecf6b428)]
 interface nsIDOMNavigator : nsISupports
 {
-  readonly attribute DOMString           appCodeName;
-  readonly attribute DOMString           appName;
-  readonly attribute DOMString           appVersion;
-  readonly attribute DOMString           language;
-  readonly attribute nsIDOMMimeTypeArray mimeTypes;
-  readonly attribute DOMString           platform;
-  readonly attribute DOMString           oscpu;
-  readonly attribute DOMString           vendor;
-  readonly attribute DOMString           vendorSub;
-  readonly attribute DOMString           product;
-  readonly attribute DOMString           productSub;
-  readonly attribute nsIDOMPluginArray   plugins;
-  readonly attribute DOMString           userAgent;
-  readonly attribute boolean             cookieEnabled;
-  readonly attribute boolean             onLine;
-  readonly attribute DOMString           buildID;
-  readonly attribute DOMString           doNotTrack;
+  readonly attribute DOMString             appCodeName;
+  readonly attribute DOMString             appName;
+  readonly attribute DOMString             appVersion;
+  readonly attribute DOMString             language;
+  readonly attribute nsIDOMMimeTypeArray   mimeTypes;
+  readonly attribute DOMString             platform;
+  readonly attribute DOMString             oscpu;
+  readonly attribute DOMString             vendor;
+  readonly attribute DOMString             vendorSub;
+  readonly attribute DOMString             product;
+  readonly attribute DOMString             productSub;
+  readonly attribute nsIDOMPluginArray     plugins;
+  readonly attribute DOMString             userAgent;
+  readonly attribute boolean               cookieEnabled;
+  readonly attribute boolean               onLine;
+  readonly attribute DOMString             buildID;
+  readonly attribute DOMString             doNotTrack;
+  readonly attribute nsIDOMMozPowerManager mozPower;
 
   boolean                   javaEnabled();
 
   /**
    * Pulse the device's vibrator, if it has one.  If the device does not have a
    * vibrator, this function does nothing.  If the window is hidden, this
    * function does nothing.
    *
--- a/dom/plugins/base/nsIPluginInstanceOwner.idl
+++ b/dom/plugins/base/nsIPluginInstanceOwner.idl
@@ -139,10 +139,10 @@ interface nsIPluginInstanceOwner : nsISu
 
 %{C++
   virtual void SendIdleEvent() = 0;
 %}
 
   /**
    * Call NPP_SetWindow on the plugin.
    */
-  void setWindow();
+  void callSetWindow();
 };
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -88,17 +88,16 @@ nsNPAPIPluginInstance::nsNPAPIPluginInst
 #endif
 #endif
 #ifdef MOZ_WIDGET_ANDROID
     mSurface(nsnull),
     mANPDrawingModel(0),
 #endif
     mRunning(NOT_STARTED),
     mWindowless(false),
-    mWindowlessLocal(false),
     mTransparent(false),
     mCached(false),
     mUsesDOMForCursor(false),
     mInPluginInitCall(false),
     mPlugin(plugin),
     mMIMEType(nsnull),
     mOwner(nsnull),
     mCurrentPluginEvent(nsnull),
@@ -681,22 +680,16 @@ NPError nsNPAPIPluginInstance::SetWindow
     if (!PL_strncasecmp(mMIMEType, silverlight.get(), silverlight.Length())) {
       mTransparent = true;
     }
   }
 
   return NPERR_NO_ERROR;
 }
 
-NPError nsNPAPIPluginInstance::SetWindowlessLocal(bool aWindowlessLocal)
-{
-  mWindowlessLocal = aWindowlessLocal;
-  return NPERR_NO_ERROR;
-}
-
 NPError nsNPAPIPluginInstance::SetTransparent(bool aTransparent)
 {
   mTransparent = aTransparent;
   return NPERR_NO_ERROR;
 }
 
 NPError nsNPAPIPluginInstance::SetUsesDOMForCursor(bool aUsesDOMForCursor)
 {
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -130,18 +130,16 @@ public:
 
   nsresult GetNPP(NPP * aNPP);
 
   void SetURI(nsIURI* uri);
   nsIURI* GetURI();
 
   NPError SetWindowless(bool aWindowless);
 
-  NPError SetWindowlessLocal(bool aWindowlessLocal);
-
   NPError SetTransparent(bool aTransparent);
 
   NPError SetWantsAllNetworkStreams(bool aWantsAllNetworkStreams);
 
   NPError SetUsesDOMForCursor(bool aUsesDOMForCursor);
   bool UsesDOMForCursor();
 
 #ifdef XP_MACOSX
@@ -239,17 +237,16 @@ protected:
     RUNNING,
     DESTROYING,
     DESTROYED
   } mRunning;
 
   // these are used to store the windowless properties
   // which the browser will later query
   bool mWindowless;
-  bool mWindowlessLocal;
   bool mTransparent;
   bool mCached;
   bool mUsesDOMForCursor;
 
 public:
   // True while creating the plugin, or calling NPP_SetWindow() on it.
   bool mInPluginInitCall;
 
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -147,16 +147,17 @@
 #include "nsIDocShell.h"
 #include "nsPluginNativeWindow.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentErrors.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
+#include "nsIImageLoadingContent.h"
 #include "mozilla/Preferences.h"
 
 #if defined(XP_WIN)
 #include "nsIWindowMediator.h"
 #include "nsIBaseWindow.h"
 #include "windows.h"
 #include "winbase.h"
 #endif
@@ -934,90 +935,103 @@ nsPluginHost::GetPluginTempDir(nsIFile *
 
     tmpDir.swap(sPluginTempDir);
   }
 
   return sPluginTempDir->Clone(aDir);
 }
 
 nsresult nsPluginHost::InstantiatePluginForChannel(nsIChannel* aChannel,
-                                                   nsIPluginInstanceOwner* aOwner,
+                                                   nsObjectLoadingContent* aContent,
                                                    nsIStreamListener** aListener)
 {
-  NS_PRECONDITION(aChannel && aOwner,
+  NS_PRECONDITION(aChannel && aContent,
                   "Invalid arguments to InstantiatePluginForChannel");
   nsCOMPtr<nsIURI> uri;
   nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
   if (NS_FAILED(rv))
     return rv;
 
 #ifdef PLUGIN_LOGGING
   if (PR_LOG_TEST(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL)) {
     nsCAutoString urlSpec;
     uri->GetAsciiSpec(urlSpec);
 
     PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
-           ("nsPluginHost::InstantiatePluginForChannel Begin owner=%p, url=%s\n",
-           aOwner, urlSpec.get()));
+           ("nsPluginHost::InstantiatePluginForChannel Begin content=%p, url=%s\n",
+           aContent, urlSpec.get()));
 
     PR_LogFlush();
   }
 #endif
 
   // Note that we're not setting up a plugin instance here; the stream
   // listener's OnStartRequest will handle doing that.
 
-  return NewEmbeddedPluginStreamListener(uri, aOwner, nsnull, aListener);
+  return NewEmbeddedPluginStreamListener(uri, aContent, nsnull, aListener);
 }
 
 nsresult
 nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
-                                        nsIPluginInstanceOwner* aOwner)
+                                        nsObjectLoadingContent *aContent,
+                                        nsPluginInstanceOwner** aOwner)
 {
   NS_ENSURE_ARG_POINTER(aOwner);
 
 #ifdef PLUGIN_LOGGING
   nsCAutoString urlSpec;
   if (aURL)
     aURL->GetAsciiSpec(urlSpec);
 
   PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
-        ("nsPluginHost::InstantiateEmbeddedPlugin Begin mime=%s, owner=%p, url=%s\n",
-        aMimeType, aOwner, urlSpec.get()));
+        ("nsPluginHost::InstantiateEmbeddedPlugin Begin mime=%s, url=%s\n",
+        aMimeType, urlSpec.get()));
 
   PR_LogFlush();
 #endif
 
-  nsresult rv;
-  nsCOMPtr<nsIPluginTagInfo> pti;
-  nsPluginTagType tagType;
-
-  rv = aOwner->QueryInterface(kIPluginTagInfoIID, getter_AddRefs(pti));
-
-  if (rv != NS_OK)
+  nsRefPtr<nsPluginInstanceOwner> instanceOwner = new nsPluginInstanceOwner();
+  if (!instanceOwner) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  nsCOMPtr<nsIContent> ourContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(aContent));
+  nsresult rv = instanceOwner->Init(ourContent);
+  if (NS_FAILED(rv)) {
     return rv;
-
+  }
+
+  nsCOMPtr<nsIPluginTagInfo> pti;
+  rv = instanceOwner->QueryInterface(kIPluginTagInfoIID, getter_AddRefs(pti));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  nsPluginTagType tagType;
   rv = pti->GetTagType(&tagType);
-
-  if ((rv != NS_OK) || !((tagType == nsPluginTagType_Embed)
-                        || (tagType == nsPluginTagType_Applet)
-                        || (tagType == nsPluginTagType_Object))) {
+  if (NS_FAILED(rv)) {
     return rv;
   }
 
+  if (tagType != nsPluginTagType_Embed &&
+      tagType != nsPluginTagType_Applet &&
+      tagType != nsPluginTagType_Object) {
+    return NS_ERROR_FAILURE;
+  }
+
   // Security checks. Can't do security checks without a URI - hopefully the plugin
   // will take care of that.
   if (aURL) {
     nsCOMPtr<nsIScriptSecurityManager> secMan =
                     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv))
       return rv; // Better fail if we can't do security checks
 
     nsCOMPtr<nsIDocument> doc;
-    aOwner->GetDocument(getter_AddRefs(doc));
+    instanceOwner->GetDocument(getter_AddRefs(doc));
     if (!doc)
       return NS_ERROR_NULL_POINTER;
 
     rv = secMan->CheckLoadURIWithPrincipal(doc->NodePrincipal(), aURL, 0);
     if (NS_FAILED(rv))
       return rv;
 
     nsCOMPtr<nsIDOMElement> elem;
@@ -1055,107 +1069,128 @@ nsPluginHost::InstantiateEmbeddedPlugin(
       ToLowerCase(contractID);
       nsCOMPtr<nsIProtocolHandler> handler = do_GetService(contractID.get());
       if (handler)
         bCanHandleInternally = true;
   }
 
   // if we don't have a MIME type at this point, we still have one more chance by
   // opening the stream and seeing if the server hands one back
-  if (!aMimeType)
-    return bCanHandleInternally ? NewEmbeddedPluginStream(aURL, aOwner, nsnull) : NS_ERROR_FAILURE;
-
-  rv = SetUpPluginInstance(aMimeType, aURL, aOwner);
-
-  if (NS_FAILED(rv))
+  if (!aMimeType) {
+    if (bCanHandleInternally && !aContent->SrcStreamLoadInitiated()) {
+      NewEmbeddedPluginStream(aURL, aContent, nsnull);
+    }
     return NS_ERROR_FAILURE;
+  }
+
+  rv = SetUpPluginInstance(aMimeType, aURL, instanceOwner);
+  if (NS_FAILED(rv)) {
+    return NS_ERROR_FAILURE;
+  }
 
   nsRefPtr<nsNPAPIPluginInstance> instance;
-  rv = aOwner->GetInstance(getter_AddRefs(instance));
-  // if we have a failure error, it means we found a plugin for the mimetype,
-  // but we had a problem with the entry point
-  if (rv == NS_ERROR_FAILURE)
+  rv = instanceOwner->GetInstance(getter_AddRefs(instance));
+  if (NS_FAILED(rv)) {
     return rv;
+  }
 
   if (instance) {
-    aOwner->CreateWidget();
+    instanceOwner->CreateWidget();
 
     // If we've got a native window, the let the plugin know about it.
-    aOwner->SetWindow();
+    instanceOwner->CallSetWindow();
 
     // create an initial stream with data
     // don't make the stream if it's a java applet or we don't have SRC or DATA attribute
-    bool havedata = false;
-
-    nsCOMPtr<nsIPluginTagInfo> pti(do_QueryInterface(aOwner, &rv));
-
-    if (pti) {
-      const char *value;
-      havedata = NS_SUCCEEDED(pti->GetAttribute("SRC", &value));
-      // no need to check for "data" as it would have been converted to "src"
+    // no need to check for "data" as it would have been converted to "src"
+    const char *value;
+    bool havedata = NS_SUCCEEDED(pti->GetAttribute("SRC", &value));
+    if (havedata && !isJava && bCanHandleInternally && !aContent->SrcStreamLoadInitiated()) {
+      NewEmbeddedPluginStream(aURL, nsnull, instance.get());
     }
-
-    if (havedata && !isJava && bCanHandleInternally)
-      rv = NewEmbeddedPluginStream(aURL, aOwner, instance.get());
   }
 
+  // At this point we consider instantiation to be successful. Do not return an error.
+  instanceOwner.forget(aOwner);
+
 #ifdef PLUGIN_LOGGING
   nsCAutoString urlSpec2;
   if (aURL != nsnull) aURL->GetAsciiSpec(urlSpec2);
 
   PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
-        ("nsPluginHost::InstantiateEmbeddedPlugin Finished mime=%s, rv=%d, owner=%p, url=%s\n",
-        aMimeType, rv, aOwner, urlSpec2.get()));
+        ("nsPluginHost::InstantiateEmbeddedPlugin Finished mime=%s, rv=%d, url=%s\n",
+        aMimeType, rv, urlSpec2.get()));
 
   PR_LogFlush();
 #endif
 
-  return rv;
+  return NS_OK;
 }
 
 nsresult nsPluginHost::InstantiateFullPagePlugin(const char *aMimeType,
                                                  nsIURI* aURI,
-                                                 nsIPluginInstanceOwner *aOwner,
+                                                 nsObjectLoadingContent *aContent,
+                                                 nsPluginInstanceOwner **aOwner,
                                                  nsIStreamListener **aStreamListener)
 {
 #ifdef PLUGIN_LOGGING
   nsCAutoString urlSpec;
   aURI->GetSpec(urlSpec);
   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
-  ("nsPluginHost::InstantiateFullPagePlugin Begin mime=%s, owner=%p, url=%s\n",
-  aMimeType, aOwner, urlSpec.get()));
+  ("nsPluginHost::InstantiateFullPagePlugin Begin mime=%s, url=%s\n",
+  aMimeType, urlSpec.get()));
 #endif
 
-  nsresult rv = SetUpPluginInstance(aMimeType, aURI, aOwner);
-
-  if (NS_OK == rv) {
-    nsRefPtr<nsNPAPIPluginInstance> instance;
-    aOwner->GetInstance(getter_AddRefs(instance));
-
-    NPWindow* win = nsnull;
-    aOwner->GetWindow(win);
-
-    if (win && instance) {
-      aOwner->CreateWidget();
-
-      // If we've got a native window, the let the plugin know about it.
-      aOwner->SetWindow();
-
-      rv = NewFullPagePluginStream(aURI, instance.get(), aStreamListener);
-
-      // If we've got a native window, the let the plugin know about it.
-      aOwner->SetWindow();
-    }
+  nsRefPtr<nsPluginInstanceOwner> instanceOwner = new nsPluginInstanceOwner();
+  if (!instanceOwner) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  nsCOMPtr<nsIContent> ourContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(aContent));
+  nsresult rv = instanceOwner->Init(ourContent);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  rv = SetUpPluginInstance(aMimeType, aURI, instanceOwner);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  nsRefPtr<nsNPAPIPluginInstance> instance;
+  instanceOwner->GetInstance(getter_AddRefs(instance));
+  if (!instance) {
+    return NS_ERROR_FAILURE;
   }
 
+  NPWindow* win = nsnull;
+  instanceOwner->GetWindow(win);
+  if (!win) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Set up any widget that might be required.
+  instanceOwner->CreateWidget();
+  instanceOwner->CallSetWindow();
+
+  rv = NewFullPagePluginStream(aURI, instance.get(), aStreamListener);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  // Call SetWindow again in case something changed.
+  instanceOwner->CallSetWindow();
+
+  instanceOwner.forget(aOwner);
+
   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
-  ("nsPluginHost::InstantiateFullPagePlugin End mime=%s, rv=%d, owner=%p, url=%s\n",
-  aMimeType, rv, aOwner, urlSpec.get()));
-
-  return rv;
+  ("nsPluginHost::InstantiateFullPagePlugin End mime=%s, rv=%d, url=%s\n",
+  aMimeType, rv, urlSpec.get()));
+
+  return NS_OK;
 }
 
 nsPluginTag*
 nsPluginHost::FindTagForLibrary(PRLibrary* aLibrary)
 {
   nsPluginTag* pluginTag;
   for (pluginTag = mPlugins; pluginTag; pluginTag = pluginTag->mNext) {
     if (pluginTag->mLibrary == aLibrary) {
@@ -3260,17 +3295,17 @@ nsPluginHost::StopPluginInstance(nsNPAPI
     mInstances.RemoveElement(aInstance);
     OnPluginInstanceDestroyed(pluginTag);
   }
 
   return NS_OK;
 }
 
 nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURL,
-                                                       nsIPluginInstanceOwner *aOwner,
+                                                       nsObjectLoadingContent *aContent,
                                                        nsNPAPIPluginInstance* aInstance,
                                                        nsIStreamListener** aListener)
 {
   if (!aURL)
     return NS_OK;
 
   nsRefPtr<nsPluginStreamListenerPeer> listener = new nsPluginStreamListenerPeer();
   if (!listener)
@@ -3278,41 +3313,45 @@ nsresult nsPluginHost::NewEmbeddedPlugin
 
   nsresult rv;
 
   // if we have an instance, everything has been set up
   // if we only have an owner, then we need to pass it in
   // so the listener can set up the instance later after
   // we've determined the mimetype of the stream
   if (aInstance)
-    rv = listener->InitializeEmbedded(aURL, aInstance);
-  else if (aOwner != nsnull)
-    rv = listener->InitializeEmbedded(aURL, nsnull, aOwner);
+    rv = listener->InitializeEmbedded(aURL, aInstance, nsnull);
+  else if (aContent)
+    rv = listener->InitializeEmbedded(aURL, nsnull, aContent);
   else
     rv = NS_ERROR_ILLEGAL_VALUE;
+
   if (NS_SUCCEEDED(rv))
     NS_ADDREF(*aListener = listener);
 
   return rv;
 }
 
 // Called by InstantiateEmbeddedPlugin()
 nsresult nsPluginHost::NewEmbeddedPluginStream(nsIURI* aURL,
-                                               nsIPluginInstanceOwner *aOwner,
+                                               nsObjectLoadingContent *aContent,
                                                nsNPAPIPluginInstance* aInstance)
 {
+  NS_ASSERTION(!aContent || !aInstance, "Don't pass both content and an instance to NewEmbeddedPluginStream!");
+
   nsCOMPtr<nsIStreamListener> listener;
-  nsresult rv = NewEmbeddedPluginStreamListener(aURL, aOwner, aInstance,
+  nsresult rv = NewEmbeddedPluginStreamListener(aURL, aContent, aInstance,
                                                 getter_AddRefs(listener));
   if (NS_SUCCEEDED(rv)) {
     nsCOMPtr<nsIDocument> doc;
     nsCOMPtr<nsILoadGroup> loadGroup;
-    if (aOwner) {
-      rv = aOwner->GetDocument(getter_AddRefs(doc));
-      if (NS_SUCCEEDED(rv) && doc) {
+    if (aContent) {
+      nsCOMPtr<nsIContent> aIContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(aContent));
+      doc = aIContent->GetDocument();
+      if (doc) {
         loadGroup = doc->GetDocumentLoadGroup();
       }
     }
     nsCOMPtr<nsIChannel> channel;
     rv = NS_NewChannel(getter_AddRefs(channel), aURL, nsnull, loadGroup, nsnull);
     if (NS_SUCCEEDED(rv)) {
       // if this is http channel, set referrer, some servers are configured
       // to reject requests without referrer set, see bug 157796
@@ -3716,22 +3755,16 @@ nsPluginHost::CreateTempFileToPost(const
 
 nsresult
 nsPluginHost::NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
 {
   return PLUG_NewPluginNativeWindow(aPluginNativeWindow);
 }
 
 nsresult
-nsPluginHost::DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
-{
-  return PLUG_DeletePluginNativeWindow(aPluginNativeWindow);
-}
-
-nsresult
 nsPluginHost::InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner)
 {
   // Pass false as the second arg, we want the answer to be the
   // same here whether the Java plugin is enabled or not.
   nsPluginTag *plugin = FindPluginForType("application/x-java-vm", false);
 
   if (!plugin || !plugin->mIsNPRuntimeEnabledJavaPlugin) {
     // No NPRuntime enabled Java plugin found, no point in
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -64,16 +64,18 @@
 #include "nsIIDNService.h"
 #include "nsCRT.h"
 
 class nsNPAPIPlugin;
 class nsIComponentManager;
 class nsIFile;
 class nsIChannel;
 class nsPluginNativeWindow;
+class nsObjectLoadingContent;
+class nsPluginInstanceOwner;
 
 #if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
 #define MAC_CARBON_PLUGINS
 #endif
 
 class nsInvalidPluginTag : public nsISupports
 {
 public:
@@ -107,17 +109,17 @@ public:
   NS_DECL_NSIPLUGINHOST
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
 
   nsresult Init();
   nsresult Destroy();
   nsresult LoadPlugins();
   nsresult InstantiatePluginForChannel(nsIChannel* aChannel,
-                                       nsIPluginInstanceOwner* aOwner,
+                                       nsObjectLoadingContent* aContent,
                                        nsIStreamListener** aListener);
   nsresult SetUpPluginInstance(const char *aMimeType,
                                nsIURI *aURL,
                                nsIPluginInstanceOwner *aOwner);
   nsresult IsPluginEnabledForType(const char* aMimeType);
   nsresult IsPluginEnabledForType(const char* aMimeType,
                                   bool aShouldPlay);
   nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
@@ -147,17 +149,16 @@ public:
                    const char* postHeaders);
 
   nsresult FindProxyForURL(const char* url, char* *result);
   nsresult UserAgent(const char **retstring);
   nsresult ParsePostBufferToFixHeaders(const char *inPostData, PRUint32 inPostDataLen,
                                        char **outPostData, PRUint32 *outPostDataLen);
   nsresult CreateTempFileToPost(const char *aPostDataURL, nsIFile **aTmpFile);
   nsresult NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow);
-  nsresult DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow);
   nsresult InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner);
 
   void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, bool isVisible);
   void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame);
 
   nsresult GetPluginName(nsNPAPIPluginInstance *aPluginInstance, const char** aPluginName);
   nsresult StopPluginInstance(nsNPAPIPluginInstance* aInstance);
   nsresult HandleBadPlugin(PRLibrary* aLibrary, nsNPAPIPluginInstance *aInstance);
@@ -217,39 +218,41 @@ public:
   void DestroyRunningInstances(nsISupportsArray* aReloadDocs, nsPluginTag* aPluginTag);
 
   // Return the tag for |aLibrary| if found, nsnull if not.
   nsPluginTag* FindTagForLibrary(PRLibrary* aLibrary);
 
   // The last argument should be false if we already have an in-flight stream
   // and don't need to set up a new stream.
   nsresult InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
-                                     nsIPluginInstanceOwner* aOwner);
+                                     nsObjectLoadingContent *aContent,
+                                     nsPluginInstanceOwner** aOwner);
 
   nsresult InstantiateFullPagePlugin(const char *aMimeType,
                                      nsIURI* aURI,
-                                     nsIPluginInstanceOwner *aOwner,
+                                     nsObjectLoadingContent *aContent,
+                                     nsPluginInstanceOwner **aOwner,
                                      nsIStreamListener **aStreamListener);
 
   // Does not accept NULL and should never fail.
   nsPluginTag* TagForPlugin(nsNPAPIPlugin* aPlugin);
 
   nsresult GetPlugin(const char *aMimeType, nsNPAPIPlugin** aPlugin);
 
 private:
   nsresult
   TrySetUpPluginInstance(const char *aMimeType, nsIURI *aURL, nsIPluginInstanceOwner *aOwner);
 
   nsresult
-  NewEmbeddedPluginStreamListener(nsIURI* aURL, nsIPluginInstanceOwner *aOwner,
+  NewEmbeddedPluginStreamListener(nsIURI* aURL, nsObjectLoadingContent *aContent,
                                   nsNPAPIPluginInstance* aInstance,
                                   nsIStreamListener** aListener);
 
   nsresult
-  NewEmbeddedPluginStream(nsIURI* aURL, nsIPluginInstanceOwner *aOwner, nsNPAPIPluginInstance* aInstance);
+  NewEmbeddedPluginStream(nsIURI* aURL, nsObjectLoadingContent *aContent, nsNPAPIPluginInstance* aInstance);
 
   nsresult
   NewFullPagePluginStream(nsIURI* aURI,
                           nsNPAPIPluginInstance *aInstance,
                           nsIStreamListener **aStreamListener);
 
   // Return an nsPluginTag for this type, if any.  If aCheckEnabled is
   // true, only enabled plugins will be returned.
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -89,19 +89,21 @@ using mozilla::DefaultXDisplay;
 #include "nsIDOMHTMLObjectElement.h"
 #include "nsIAppShell.h"
 #include "nsIDOMHTMLAppletElement.h"
 #include "nsAttrName.h"
 #include "nsIFocusManager.h"
 #include "nsFocusManager.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIScrollableFrame.h"
+#include "nsIImageLoadingContent.h"
 
 #include "nsContentCID.h"
 #include "nsWidgetsCID.h"
+static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 #include <wtypes.h>
 #include <winuser.h>
 #endif
 
 #ifdef XP_MACOSX
@@ -180,17 +182,17 @@ nsPluginInstanceOwner::NotifyPaintWaiter
     // receive it immediately
     mWaitingForPaint = nsContentUtils::AddScriptRunner(event);
   }
 }
 
 #ifdef XP_MACOSX
 static void DrawPlugin(ImageContainer* aContainer, void* aPluginInstanceOwner)
 {
-  nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetOwner();
+  nsObjectFrame* frame = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner)->GetFrame();
   if (frame) {
     frame->UpdateImageLayer(aContainer, gfxRect(0,0,0,0));
   }
 }
 
 static void OnDestroyImage(void* aPluginInstanceOwner)
 {
   nsPluginInstanceOwner* owner = static_cast<nsPluginInstanceOwner*>(aPluginInstanceOwner);
@@ -252,34 +254,47 @@ nsPluginInstanceOwner::EndUpdateBackgrou
     mInstance->EndUpdateBackground(aContext, &rect);
   }
 }
 
 bool
 nsPluginInstanceOwner::UseAsyncRendering()
 {
 #ifdef XP_MACOSX
-  nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
+  if (mUseAsyncRendering) {
+    return true;
+  }
+
+  nsRefPtr<ImageContainer> container;
+  if (mObjectFrame) {
+    container = mObjectFrame->GetImageContainer();
+  }
 #endif
 
   bool useAsyncRendering;
   bool result = (mInstance &&
           NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
           useAsyncRendering &&
 #ifdef XP_MACOSX
           container &&
           container->GetBackendType() == 
                   LayerManager::LAYERS_OPENGL
 #else
           (!mPluginWindow ||
            mPluginWindow->type == NPWindowTypeDrawable)
 #endif
           );
 
-    return result;
+#ifdef XP_MACOSX
+  if (result) {
+    mUseAsyncRendering = true;
+  }
+#endif
+
+  return result;
 }
 
 nsIntSize
 nsPluginInstanceOwner::GetCurrentImageSize()
 {
   nsIntSize size(0,0);
   if (mInstance) {
     mInstance->GetImageSize(&size);
@@ -287,24 +302,26 @@ nsPluginInstanceOwner::GetCurrentImageSi
   return size;
 }
 
 nsPluginInstanceOwner::nsPluginInstanceOwner()
 {
   // create nsPluginNativeWindow object, it is derived from NPWindow
   // struct and allows to manipulate native window procedure
   nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
-  nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());  
-  if (pluginHost)
-    pluginHost->NewPluginNativeWindow(&mPluginWindow);
+  mPluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());  
+  if (mPluginHost)
+    mPluginHost->NewPluginNativeWindow(&mPluginWindow);
   else
     mPluginWindow = nsnull;
 
   mObjectFrame = nsnull;
+  mContent = nsnull;
   mTagText = nsnull;
+  mWidgetCreationComplete = false;
 #ifdef XP_MACOSX
   memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
 #ifndef NP_NO_QUICKDRAW
   memset(&mQDPluginPortCopy, 0, sizeof(NP_Port));
 #endif
   mInCGPaintLevel = 0;
   mSentInitialTopLevelWindowEvent = false;
   mColorProfile = nsnull;
@@ -313,24 +330,24 @@ nsPluginInstanceOwner::nsPluginInstanceO
   mContentFocused = false;
   mWidgetVisible = true;
   mPluginWindowVisible = false;
   mPluginDocumentActiveState = true;
   mNumCachedAttrs = 0;
   mNumCachedParams = 0;
   mCachedAttrParamNames = nsnull;
   mCachedAttrParamValues = nsnull;
-  mDestroyWidget = false;
 
 #ifdef XP_MACOSX
 #ifndef NP_NO_QUICKDRAW
   mEventModel = NPEventModelCarbon;
 #else
   mEventModel = NPEventModelCocoa;
 #endif
+  mUseAsyncRendering = false;
 #endif
 
   mWaitingForPaint = false;
 
 #ifdef MOZ_WIDGET_ANDROID
   mPluginViewAdded = false;
   mLastPluginRect = gfxRect(0, 0, 0, 0);
 #endif
@@ -375,23 +392,18 @@ nsPluginInstanceOwner::~nsPluginInstance
     mCachedAttrParamValues = nsnull;
   }
 
   if (mTagText) {
     NS_Free(mTagText);
     mTagText = nsnull;
   }
 
-  // clean up plugin native window object
-  nsCOMPtr<nsIPluginHost> pluginHostCOM = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
-  nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
-  if (pluginHost) {
-    pluginHost->DeletePluginNativeWindow(mPluginWindow);
-    mPluginWindow = nsnull;
-  }
+  PLUG_DeletePluginNativeWindow(mPluginWindow);
+  mPluginWindow = nsnull;
 
   if (mInstance) {
     mInstance->InvalidateOwner();
   }
 }
 
 NS_IMPL_ISUPPORTS3(nsPluginInstanceOwner,
                    nsIPluginInstanceOwner,
@@ -485,24 +497,39 @@ nsresult nsPluginInstanceOwner::GetInsta
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
                                             const char *aTarget,
                                             nsIInputStream *aPostStream,
                                             void *aHeadersData,
                                             PRUint32 aHeadersDataLen)
 {
-  NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(mContent, NS_ERROR_NULL_POINTER);
 
   if (mContent->IsEditable()) {
     return NS_OK;
   }
 
+  nsIDocument *doc = mContent->GetCurrentDoc();
+  if (!doc) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIPresShell *presShell = doc->GetShell();
+  if (!presShell) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsPresContext *presContext = presShell->GetPresContext();
+  if (!presContext) {
+    return NS_ERROR_FAILURE;
+  }
+
   // the container of the pres context will give us the link handler
-  nsCOMPtr<nsISupports> container = mObjectFrame->PresContext()->GetContainer();
+  nsCOMPtr<nsISupports> container = presContext->GetContainer();
   NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);
   nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
   NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE);
 
   nsAutoString  unitarget;
   unitarget.AssignASCII(aTarget); // XXX could this be nonascii?
 
   nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
@@ -740,22 +767,16 @@ NS_IMETHODIMP nsPluginInstanceOwner::Set
 #ifdef XP_MACOSX
   mEventModel = static_cast<NPEventModel>(eventModel);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
-NS_IMETHODIMP nsPluginInstanceOwner::SetWindow()
-{
-  NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
-  return mObjectFrame->CallSetWindow(false);
-}
-
 NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
 {
   if (!menu || !event)
     return NPERR_GENERIC_ERROR;
 
 #ifdef XP_MACOSX
   if (GetEventModel() != NPEventModelCocoa)
     return NPERR_INCOMPATIBLE_VERSION_ERROR;
@@ -1087,17 +1108,16 @@ nsresult nsPluginInstanceOwner::EnsureCa
 {
   if (mCachedAttrParamValues)
     return NS_OK;
 
   NS_PRECONDITION(((mNumCachedAttrs + mNumCachedParams) == 0) &&
                     !mCachedAttrParamNames,
                   "re-cache of attrs/params not implemented! use the DOM "
                     "node directy instead");
-  NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_NULL_POINTER);
 
   // Convert to a 16-bit count. Subtract 2 in case we add an extra
   // "src" or "wmode" entry below.
   PRUint32 cattrs = mContent->GetAttrCount();
   if (cattrs < 0x0000FFFD) {
     mNumCachedAttrs = static_cast<PRUint16>(cattrs);
   } else {
     mNumCachedAttrs = 0xFFFD;
@@ -1160,19 +1180,16 @@ nsresult nsPluginInstanceOwner::EnsureCa
               ourParams.AppendObject(domelement);
             }
           }
         }
       }
     }
   }
 
-  // We're done with DOM method calls now. Make sure we still have a frame.
-  NS_ENSURE_TRUE(mObjectFrame, NS_ERROR_OUT_OF_MEMORY);
-
   // Convert to a 16-bit count.
   PRUint32 cparams = ourParams.Count();
   if (cparams < 0x0000FFFF) {
     mNumCachedParams = static_cast<PRUint16>(cparams);
   } else {
     mNumCachedParams = 0xFFFF;
   }
 
@@ -2725,85 +2742,30 @@ nsPluginInstanceOwner::Destroy()
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true);
   mContent->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, true);
   mContent->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, true);
 #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
   mContent->RemoveEventListener(NS_LITERAL_STRING("text"), this, true);
 #endif
 
   if (mWidget) {
+    if (mPluginWindow) {
+      mPluginWindow->SetPluginWidget(nsnull);
+    }
+
     nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-    if (pluginWidget)
+    if (pluginWidget) {
       pluginWidget->SetPluginInstanceOwner(nsnull);
-
-    if (mDestroyWidget)
-      mWidget->Destroy();
+    }
+    mWidget->Destroy();
   }
 
   return NS_OK;
 }
 
-/*
- * Prepare to stop 
- */
-void
-nsPluginInstanceOwner::PrepareToStop(bool aDelayedStop)
-{
-  // Drop image reference because the child may destroy the surface after we return.
-  nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
-  if (container) {
-#ifdef XP_MACOSX
-    nsRefPtr<Image> image = container->GetCurrentImage();
-    if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
-      // Undo what we did to the current image in SetCurrentImage().
-      MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
-      oglImage->SetUpdateCallback(nsnull, nsnull);
-      oglImage->SetDestroyCallback(nsnull);
-      // If we have a current image here, its destructor hasn't yet been
-      // called, so OnDestroyImage() can't yet have been called.  So we need
-      // to do ourselves what OnDestroyImage() would have done.
-      NS_RELEASE_THIS();
-    }
-#endif
-    container->SetCurrentImage(nsnull);
-  }
-
-#if defined(XP_WIN) || defined(MOZ_X11)
-  if (aDelayedStop && mWidget) {
-    // To delay stopping a plugin we need to reparent the plugin
-    // so that we can safely tear down the
-    // plugin after its frame (and view) is gone.
-
-    // Also hide and disable the widget to avoid it from appearing in
-    // odd places after reparenting it, but before it gets destroyed.
-    mWidget->Show(false);
-    mWidget->Enable(false);
-
-    // Reparent the plugins native window. This relies on the widget
-    // and plugin et al not holding any other references to its
-    // parent.
-    mWidget->SetParent(nsnull);
-
-    mDestroyWidget = true;
-  }
-#endif
-
-#ifdef MOZ_WIDGET_ANDROID
-  RemovePluginView();
-#endif
-
-  // Unregister scroll position listeners
-  for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-    nsIScrollableFrame* sf = do_QueryFrame(f);
-    if (sf) {
-      sf->RemoveScrollPositionListener(this);
-    }
-  }
-}
-
 // Paints are handled differently, so we just simulate an update event.
 
 #ifdef XP_MACOSX
 void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgContext)
 {
   if (!mInstance || !mObjectFrame)
     return;
  
@@ -3201,35 +3163,34 @@ void nsPluginInstanceOwner::StartTimer(b
 }
 
 void nsPluginInstanceOwner::CancelTimer()
 {
   mPluginHost->RemoveIdleTimeTarget(this);
 }
 #endif
 
-nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
-                                     nsObjectFrame* aFrame,
-                                     nsIContent*    aContent)
+nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
 {
   mLastEventloopNestingLevel = GetEventloopNestingLevel();
 
-  mObjectFrame = aFrame;
   mContent = aContent;
 
-  nsWeakFrame weakFrame(aFrame);
-
-  // Some plugins require a specific sequence of shutdown and startup when
-  // a page is reloaded. Shutdown happens usually when the last instance
-  // is destroyed. Here we make sure the plugin instance in the old
-  // document is destroyed before we try to create the new one.
-  aPresContext->EnsureVisible();
-
-  if (!weakFrame.IsAlive()) {
-    return NS_ERROR_NOT_AVAILABLE;
+  // Get a frame, don't reflow. If a reflow was necessary it should have been
+  // done at a higher level than this (content).
+  nsIFrame* frame = aContent->GetPrimaryFrame();
+  nsIObjectFrame* iObjFrame = do_QueryFrame(frame);
+  nsObjectFrame* objFrame =  static_cast<nsObjectFrame*>(iObjFrame);
+  if (objFrame) {
+    SetFrame(objFrame);
+    // Some plugins require a specific sequence of shutdown and startup when
+    // a page is reloaded. Shutdown happens usually when the last instance
+    // is destroyed. Here we make sure the plugin instance in the old
+    // document is destroyed before we try to create the new one.
+    objFrame->PresContext()->EnsureVisible();
   }
 
   // register context menu listener
   mCXMenuListener = new nsPluginDOMContextMenuListener();
   if (mCXMenuListener) {    
     mCXMenuListener->Init(aContent);
   }
 
@@ -3262,26 +3223,16 @@ nsresult nsPluginInstanceOwner::Init(nsP
   mContent->AddEventListener(NS_LITERAL_STRING("dragleave"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("dragexit"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true);
   mContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true);
 #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
   mContent->AddEventListener(NS_LITERAL_STRING("text"), this, true);
 #endif
-  
-  // Register scroll position listeners
-  // We need to register a scroll position listener on every scrollable
-  // frame up to the top
-  for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-    nsIScrollableFrame* sf = do_QueryFrame(f);
-    if (sf) {
-      sf->AddScrollPositionListener(this);
-    }
-  }
 
   return NS_OK; 
 }
 
 void* nsPluginInstanceOwner::GetPluginPortFromWidget()
 {
 //!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
 
@@ -3313,98 +3264,105 @@ void nsPluginInstanceOwner::ReleasePlugi
   }
 #endif
 }
 
 NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
 {
   NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
 
-  nsresult  rv = NS_ERROR_FAILURE;
+    nsresult rv = NS_ERROR_FAILURE;
+  
+  // Can't call this twice!
+  if (mWidget) {
+    NS_WARNING("Trying to create a plugin widget twice!");
+    return NS_ERROR_FAILURE;
+  }
+  
+  bool windowless = false;
+  mInstance->IsWindowless(&windowless);
+  if (!windowless && !nsIWidget::UsePuppetWidgets()) {
+    // Try to get a parent widget, on some platforms widget creation will fail without
+    // a parent.
+    nsCOMPtr<nsIWidget> parentWidget;
+    nsIDocument *doc = nsnull;
+    if (mContent) {
+      doc = mContent->OwnerDoc();
+      parentWidget = nsContentUtils::WidgetForDocument(doc);
+    }
+
+    mWidget = do_CreateInstance(kWidgetCID, &rv);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    nsWidgetInitData initData;
+    initData.mWindowType = eWindowType_plugin;
+    initData.mUnicode = false;
+    initData.clipChildren = true;
+    initData.clipSiblings = true;
+    rv = mWidget->Create(parentWidget.get(), nsnull, nsIntRect(0,0,0,0),
+                         nsnull, nsnull, &initData);
+    if (NS_FAILED(rv)) {
+      mWidget->Destroy();
+      mWidget = nsnull;
+      return rv;
+    }
+
+    mWidget->EnableDragDrop(true);
+    mWidget->Show(false);
+    mWidget->Enable(false);
+  }
 
   if (mObjectFrame) {
-    if (!mWidget) {
-      bool windowless = false;
-      mInstance->IsWindowless(&windowless);
-      nsIDocument *doc = mContent ? mContent->OwnerDoc() : nsnull;
-      // always create widgets in Twips, not pixels
-      nsPresContext* context = mObjectFrame->PresContext();
-      rv = mObjectFrame->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),
-                                      context->DevPixelsToAppUnits(mPluginWindow->height),
-                                      windowless);
-      if (NS_OK == rv) {
-        mWidget = mObjectFrame->GetWidget();
-
-        if (true == windowless) {
-          mPluginWindow->type = NPWindowTypeDrawable;
-
-          // this needs to be a HDC according to the spec, but I do
-          // not see the right way to release it so let's postpone
-          // passing HDC till paint event when it is really
-          // needed. Change spec?
-          mPluginWindow->window = nsnull;
+    // NULL widget is fine, will result in windowless setup.
+    mObjectFrame->PrepForDrawing(mWidget);
+  }
+
+  if (windowless) {
+    mPluginWindow->type = NPWindowTypeDrawable;
+
+    // this needs to be a HDC according to the spec, but I do
+    // not see the right way to release it so let's postpone
+    // passing HDC till paint event when it is really
+    // needed. Change spec?
+    mPluginWindow->window = nsnull;
 #ifdef MOZ_X11
-          // Fill in the display field.
-          NPSetWindowCallbackStruct* ws_info = 
-            static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
-          ws_info->display = DefaultXDisplay();
-
-          nsCAutoString description;
-          GetPluginDescription(description);
-          NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
-          mFlash10Quirks = StringBeginsWith(description, flash10Head);
+    // Fill in the display field.
+    NPSetWindowCallbackStruct* ws_info = 
+    static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
+    ws_info->display = DefaultXDisplay();
+    
+    nsCAutoString description;
+    GetPluginDescription(description);
+    NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
+    mFlash10Quirks = StringBeginsWith(description, flash10Head);
 #endif
-
-          // Changing to windowless mode changes the NPWindow geometry.
-          mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
-        } else if (mWidget) {
-          nsIWidget* parent = mWidget->GetParent();
-          NS_ASSERTION(parent, "Plugin windows must not be toplevel");
-          // Set the plugin window to have an empty cliprect. The cliprect
-          // will be reset when nsRootPresContext::UpdatePluginGeometry
-          // runs later. The plugin window does need to have the correct
-          // size here. GetEmptyClipConfiguration will probably give it the
-          // size, but just in case we haven't been reflowed or something, set
-          // the size explicitly.
-          nsAutoTArray<nsIWidget::Configuration,1> configuration;
-          mObjectFrame->GetEmptyClipConfiguration(&configuration);
-          if (configuration.Length() > 0) {
-            configuration[0].mBounds.width = mPluginWindow->width;
-            configuration[0].mBounds.height = mPluginWindow->height;
-          }
-          parent->ConfigureChildren(configuration);
-
-          // mPluginWindow->type is used in |GetPluginPort| so it must
-          // be initialized first
-          mPluginWindow->type = NPWindowTypeWindow;
-          mPluginWindow->window = GetPluginPortFromWidget();
-
+  } else if (mWidget) {
+    // mPluginWindow->type is used in |GetPluginPort| so it must
+    // be initialized first
+    mPluginWindow->type = NPWindowTypeWindow;
+    mPluginWindow->window = GetPluginPortFromWidget();
 #ifdef MAC_CARBON_PLUGINS
-          // start the idle timer.
-          StartTimer(true);
+    // start the idle timer.
+    StartTimer(true);
 #endif
-
-          // tell the plugin window about the widget
-          mPluginWindow->SetPluginWidget(mWidget);
-
-          // tell the widget about the current plugin instance owner.
-          nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
-          if (pluginWidget)
-            pluginWidget->SetPluginInstanceOwner(this);
-        }
-      }
+    // tell the plugin window about the widget
+    mPluginWindow->SetPluginWidget(mWidget);
+    
+    // tell the widget about the current plugin instance owner.
+    nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
+    if (pluginWidget) {
+      pluginWidget->SetPluginInstanceOwner(this);
     }
   }
 
-  return rv;
-}
-
-void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
-{
-  mPluginHost = static_cast<nsPluginHost*>(aHost);
+  mWidgetCreationComplete = true;
+
+  return NS_OK;
 }
 
 // Mac specific code to fix up the port location and clipping region
 #ifdef XP_MACOSX
 
 void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
 {
   if (!mWidget || !mPluginWindow || !mInstance || !mObjectFrame)
@@ -3500,31 +3458,41 @@ void* nsPluginInstanceOwner::FixUpPlugin
 
   // if the clip rect changed, call SetWindow()
   // (RealPlayer needs this to draw correctly)
   if (mPluginWindow->clipRect.left    != oldClipRect.left   ||
       mPluginWindow->clipRect.top     != oldClipRect.top    ||
       mPluginWindow->clipRect.right   != oldClipRect.right  ||
       mPluginWindow->clipRect.bottom  != oldClipRect.bottom)
   {
-    CallSetWindow();
+    if (UseAsyncRendering()) {
+      mInstance->AsyncSetWindow(mPluginWindow);
+    }
+    else {
+      mPluginWindow->CallSetWindow(mInstance);
+    }
     mPluginPortChanged = false;
 #ifdef MAC_CARBON_PLUGINS
     // if the clipRect is of size 0, make the null timer fire less often
     CancelTimer();
     if (mPluginWindow->clipRect.left == mPluginWindow->clipRect.right ||
         mPluginWindow->clipRect.top == mPluginWindow->clipRect.bottom) {
       StartTimer(false);
     }
     else {
       StartTimer(true);
     }
 #endif
   } else if (mPluginPortChanged) {
-    CallSetWindow();
+    if (UseAsyncRendering()) {
+      mInstance->AsyncSetWindow(mPluginWindow);
+    }
+    else {
+      mPluginWindow->CallSetWindow(mInstance);
+    }
     mPluginPortChanged = false;
   }
 
   // After the first NPP_SetWindow call we need to send an initial
   // top-level window focus event.
   if (eventModel == NPEventModelCocoa && !mSentInitialTopLevelWindowEvent) {
     // Set this before calling ProcessEvent to avoid endless recursion.
     mSentInitialTopLevelWindowEvent = true;
@@ -3556,17 +3524,17 @@ nsPluginInstanceOwner::HidePluginWindow(
 {
   if (!mPluginWindow || !mInstance) {
     return;
   }
 
   mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
   mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
   mWidgetVisible = false;
-  if (mAsyncHidePluginWindow) {
+  if (UseAsyncRendering()) {
     mInstance->AsyncSetWindow(mPluginWindow);
   } else {
     mInstance->SetWindow(mPluginWindow);
   }
 }
 
 #else // XP_MACOSX
 
@@ -3626,29 +3594,108 @@ nsPluginInstanceOwner::UpdateWindowVisib
 void
 nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
 {
   mPluginDocumentActiveState = aIsActive;
   UpdateWindowPositionAndClipRect(true);
 }
 #endif // XP_MACOSX
 
-void
+NS_IMETHODIMP
 nsPluginInstanceOwner::CallSetWindow()
 {
-  if (!mInstance)
+  if (mObjectFrame) {
+    mObjectFrame->CallSetWindow(false);
+  } else if (mInstance) {
+    if (UseAsyncRendering()) {
+      mInstance->AsyncSetWindow(mPluginWindow);
+    } else {
+      mInstance->SetWindow(mPluginWindow);
+    }
+  }
+
+  return NS_OK;
+}
+
+void nsPluginInstanceOwner::SetFrame(nsObjectFrame *aFrame)
+{
+  // Don't do anything if the frame situation hasn't changed.
+  if (mObjectFrame == aFrame) {
     return;
-
-  if (UseAsyncRendering()) {
-    mAsyncHidePluginWindow = true;
-    mInstance->AsyncSetWindow(mPluginWindow);
+  }
+
+  // Deal with things that depend on whether or not we used to have a frame.
+  if (mObjectFrame) {
+    // We have an old frame.
+    // Drop image reference because the child may destroy the surface after we return.
+    nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
+    if (container) {
+#ifdef XP_MACOSX
+      nsRefPtr<Image> image = container->GetCurrentImage();
+      if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
+        // Undo what we did to the current image in SetCurrentImage().
+        MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image.get());
+        oglImage->SetUpdateCallback(nsnull, nsnull);
+        oglImage->SetDestroyCallback(nsnull);
+        // If we have a current image here, its destructor hasn't yet been
+        // called, so OnDestroyImage() can't yet have been called.  So we need
+        // to do ourselves what OnDestroyImage() would have done.
+        NS_RELEASE_THIS();
+      }
+#endif
+      container->SetCurrentImage(nsnull);
+    }
+
+    // If we had an old frame and we're not going to have a new one then
+    // we should unregister for some things.
+    if (!aFrame) {
+      // Unregister scroll position listeners
+      for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
+        nsIScrollableFrame* sf = do_QueryFrame(f);
+        if (sf) {
+          sf->RemoveScrollPositionListener(this);
+        }
+      }
+    }
+
+    // Make sure the old frame isn't holding a reference to us.
+    mObjectFrame->SetInstanceOwner(nsnull);
   } else {
-    mAsyncHidePluginWindow = false;
-    mInstance->SetWindow(mPluginWindow);
+    if (aFrame) {
+      // We didn't have an object frame before but we do now!
+      // We need to register a scroll position listener on every scrollable
+      // frame up to the top
+      for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
+        nsIScrollableFrame* sf = do_QueryFrame(f);
+        if (sf) {
+          sf->AddScrollPositionListener(this);
+        }
+      }
+    }
   }
+
+  // Swap in the new frame (or no frame)
+  mObjectFrame = aFrame;
+
+  // Set up a new frame
+  if (mObjectFrame) {
+    mObjectFrame->SetInstanceOwner(this);
+    // Can only call PrepForDrawing on an object frame once. Don't do it here unless
+    // widget creation is complete. Doesn't matter if we actually have a widget.
+    if (mWidgetCreationComplete) {
+      mObjectFrame->PrepForDrawing(mWidget);
+    }
+    mObjectFrame->FixupWindow(mObjectFrame->GetContentRectRelativeToSelf().Size());
+    mObjectFrame->Invalidate(mObjectFrame->GetContentRectRelativeToSelf());
+  }
+}
+
+nsObjectFrame* nsPluginInstanceOwner::GetFrame()
+{
+  return mObjectFrame;
 }
 
 // Little helper function to resolve relative URL in
 // |value| for certain inputs of |name|
 void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
 {
   if (name.LowerCaseEqualsLiteral("pluginurl") ||
       name.LowerCaseEqualsLiteral("pluginspage")) {        
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -130,19 +130,17 @@ public:
   
   nsresult MouseDown(nsIDOMEvent* aKeyEvent);
   nsresult KeyPress(nsIDOMEvent* aKeyEvent);
 #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6)
   nsresult Text(nsIDOMEvent* aTextEvent);
 #endif
 
   nsresult Destroy();  
-  
-  void PrepareToStop(bool aDelayedStop);
-  
+
 #ifdef XP_WIN
   void Paint(const RECT& aDirty, HDC aDC);
 #elif defined(XP_MACOSX)
   void Paint(const gfxRect& aDirtyRect, CGContextRef cgContext);  
   void RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight);
   void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext);
 #elif defined(MOZ_X11) || defined(ANDROID)
   void Paint(gfxContext* aContext,
@@ -159,24 +157,21 @@ public:
   void SendIdleEvent();
   
   // nsIScrollPositionListener interface
   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY);
   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY);
   
   //locals
   
-  nsresult Init(nsPresContext* aPresContext, nsObjectFrame* aFrame,
-                nsIContent* aContent);
+  nsresult Init(nsIContent* aContent);
   
   void* GetPluginPortFromWidget();
   void ReleasePluginPort(void* pluginPort);
-  
-  void SetPluginHost(nsIPluginHost* aHost);
-  
+
   nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
   
 #ifdef XP_MACOSX
   enum { ePluginPaintEnable, ePluginPaintDisable };
   
   NPDrawingModel GetDrawingModel();
   bool IsRemoteDrawingCoreAnimation();
   NPEventModel GetEventModel();
@@ -205,26 +200,20 @@ public:
   // CoreGraphics drawing model).
   void BeginCGPaint();
   void EndCGPaint();
 #else // XP_MACOSX
   void UpdateWindowPositionAndClipRect(bool aSetWindow);
   void UpdateWindowVisibility(bool aVisible);
   void UpdateDocumentActiveState(bool aIsActive);
 #endif // XP_MACOSX
-  void CallSetWindow();
-  
-  void SetOwner(nsObjectFrame *aOwner)
-  {
-    mObjectFrame = aOwner;
-  }
-  nsObjectFrame* GetOwner() {
-    return mObjectFrame;
-  }
-  
+
+  void SetFrame(nsObjectFrame *aFrame);
+  nsObjectFrame* GetFrame();
+
   PRUint32 GetLastEventloopNestingLevel() const {
     return mLastEventloopNestingLevel; 
   }
   
   static PRUint32 GetEventloopNestingLevel();
   
   void ConsiderNewEventloopNestingLevel() {
     PRUint32 currentLevel = GetEventloopNestingLevel();
@@ -313,20 +302,21 @@ private:
   bool AddPluginView(const gfxRect& aRect);
   void RemovePluginView();
   bool mPluginViewAdded;
   gfxRect mLastPluginRect;
 #endif 
  
   nsPluginNativeWindow       *mPluginWindow;
   nsRefPtr<nsNPAPIPluginInstance> mInstance;
-  nsObjectFrame              *mObjectFrame; // owns nsPluginInstanceOwner
-  nsCOMPtr<nsIContent>        mContent;
+  nsObjectFrame              *mObjectFrame;
+  nsIContent                 *mContent; // WEAK, content owns us
   nsCString                   mDocumentBase;
   char                       *mTagText;
+  bool                        mWidgetCreationComplete;
   nsCOMPtr<nsIWidget>         mWidget;
   nsRefPtr<nsPluginHost>      mPluginHost;
   
 #ifdef XP_MACOSX
   NP_CGContext                              mCGPluginPortCopy;
 #ifndef NP_NO_QUICKDRAW
   NP_Port                                   mQDPluginPortCopy;
 #endif
@@ -352,27 +342,29 @@ private:
   bool                        mPluginPortChanged;
 #endif
 #ifdef MOZ_X11
   // Used with windowless plugins only, initialized in CreateWidget().
   bool                        mFlash10Quirks;
 #endif
   bool                        mPluginWindowVisible;
   bool                        mPluginDocumentActiveState;
-  
-  // If true, destroy the widget on destruction. Used when plugin stop
-  // is being delayed to a safer point in time.
-  bool                        mDestroyWidget;
+
   PRUint16          mNumCachedAttrs;
   PRUint16          mNumCachedParams;
   char              **mCachedAttrParamNames;
   char              **mCachedAttrParamValues;
   
 #ifdef XP_MACOSX
   NPEventModel mEventModel;
+  // This is a hack! UseAsyncRendering() can incorrectly return false
+  // when we don't have an object frame (possible as of bug 90268).
+  // We hack around this by always returning true if we've ever
+  // returned true.
+  bool mUseAsyncRendering;
 #endif
   
   // pointer to wrapper for nsIDOMContextMenuListener
   nsRefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
   
   nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
   nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
   nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -381,17 +381,17 @@ nsresult nsPluginStreamListenerPeer::Ini
 
 /* Called by NewEmbeddedPluginStream() - if this is called, we weren't
  * able to load the plugin, so we need to load it later once we figure
  * out the mimetype.  In order to load it later, we need the plugin
  * instance owner.
  */
 nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL,
                                                         nsNPAPIPluginInstance* aInstance,
-                                                        nsIPluginInstanceOwner *aOwner)
+                                                        nsObjectLoadingContent *aContent)
 {
 #ifdef PLUGIN_LOGGING
   nsCAutoString urlSpec;
   aURL->GetSpec(urlSpec);
   
   PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
          ("nsPluginStreamListenerPeer::InitializeEmbedded url=%s\n", urlSpec.get()));
   
@@ -399,17 +399,17 @@ nsresult nsPluginStreamListenerPeer::Ini
 #endif
   
   mURL = aURL;
   
   if (aInstance) {
     NS_ASSERTION(mPluginInstance == nsnull, "nsPluginStreamListenerPeer::InitializeEmbedded mPluginInstance != nsnull");
     mPluginInstance = aInstance;
   } else {
-    mOwner = aOwner;
+    mContent = aContent;
   }
   
   mPendingRequests = 1;
   
   mDataForwardToRequest = new nsHashtable(16, false);
   if (!mDataForwardToRequest)
     return NS_ERROR_FAILURE;
   
@@ -572,27 +572,16 @@ nsPluginStreamListenerPeer::OnStartReque
 
       if (!bWantsAllNetworkStreams) {
         mRequestFailed = true;
         return NS_ERROR_FAILURE;
       }
     }
   }
   
-  // do a little sanity check to make sure our frame isn't gone
-  // by getting the tag type and checking for an error, we can determine if
-  // the frame is gone
-  if (mOwner) {
-    nsCOMPtr<nsIPluginTagInfo> pti = do_QueryInterface(mOwner);
-    NS_ENSURE_TRUE(pti, NS_ERROR_FAILURE);
-    nsPluginTagType tagType;
-    if (NS_FAILED(pti->GetTagType(&tagType)))
-      return NS_ERROR_FAILURE;  // something happened to our object frame, so bail!
-  }
-  
   // Get the notification callbacks from the channel and save it as
   // week ref we'll use it in nsPluginStreamInfo::RequestRead() when
   // we'll create channel for byte range request.
   nsCOMPtr<nsIInterfaceRequestor> callbacks;
   channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
   if (callbacks)
     mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks);
   
@@ -637,47 +626,31 @@ nsPluginStreamListenerPeer::OnStartReque
   
 #ifdef PLUGIN_LOGGING
   PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY,
          ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n",
           this, request, aContentType.get(), mURLSpec.get()));
   
   PR_LogFlush();
 #endif
-  
-  NPWindow* window = nsnull;
-  
-  // if we don't have an nsNPAPIPluginInstance (mPluginInstance), it means
-  // we weren't able to load a plugin previously because we
-  // didn't have the mimetype.  Now that we do (aContentType),
-  // we'll try again with SetUpPluginInstance()
-  // which is called by InstantiateEmbeddedPlugin()
-  // NOTE: we don't want to try again if we didn't get the MIME type this time
-  
-  if (!mPluginInstance && mOwner && !aContentType.IsEmpty()) {
-    nsRefPtr<nsNPAPIPluginInstance> pluginInstRefPtr;
-    mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
-    mPluginInstance = pluginInstRefPtr.get();
 
-    mOwner->GetWindow(window);
-    if (!mPluginInstance && window) {
-      nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst());
-      rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner);
-      if (NS_SUCCEEDED(rv)) {
-        mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
-        mPluginInstance = pluginInstRefPtr.get();
-        if (mPluginInstance) {
-          mOwner->CreateWidget();
-          // If we've got a native window, the let the plugin know about it.
-          mOwner->SetWindow();
-        }
+  // If we don't have an instance yet it means we weren't able to load
+  // a plugin previously because we didn't have the mimetype. Try again
+  // if we have a mime type now.
+  if (!mPluginInstance && mContent && !aContentType.IsEmpty()) {
+    nsObjectLoadingContent *olc = static_cast<nsObjectLoadingContent*>(mContent.get());
+    rv = olc->InstantiatePluginInstance(aContentType.get(), aURL.get());
+    if (NS_SUCCEEDED(rv)) {
+      rv = olc->GetPluginInstance(getter_AddRefs(mPluginInstance));
+      if (NS_FAILED(rv)) {
+        return rv;
       }
     }
   }
-  
+
   // Set up the stream listener...
   rv = SetUpStreamListener(request, aURL);
   if (NS_FAILED(rv)) return rv;
   
   return rv;
 }
 
 NS_IMETHODIMP nsPluginStreamListenerPeer::OnProgress(nsIRequest *request,
@@ -864,17 +837,17 @@ nsresult nsPluginStreamListenerPeer::Ser
     // Should call GetPluginPort() here.
     // This part is copied from nsPluginInstanceOwner::GetPluginPort(). 
     nsCOMPtr<nsIWidget> widget;
     ((nsPluginNativeWindow*)window)->GetPluginWidget(getter_AddRefs(widget));
     if (widget) {
       window->window = widget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
     }
 #endif
-    owner->SetWindow();
+    owner->CallSetWindow();
   }
   
   mSeekable = false;
   mPStreamListener->OnStartBinding(this);
   mStreamOffset = 0;
   
   // force the plugin to use stream as file
   mStreamType = NP_ASFILE;
--- a/dom/plugins/base/nsPluginStreamListenerPeer.h
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.h
@@ -47,16 +47,17 @@
 #include "nsIProgressEventSink.h"
 #include "nsIHttpHeaderVisitor.h"
 #include "nsWeakReference.h"
 #include "nsNPAPIPluginStreamListener.h"
 #include "nsHashtable.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
+#include "nsObjectLoadingContent.h"
 
 class nsIChannel;
 
 /**
  * When a plugin requests opens multiple requests to the same URL and
  * the request must be satified by saving a file to disk, each stream
  * listener holds a reference to the backing file: the file is only removed
  * when all the listeners are done.
@@ -108,34 +109,34 @@ public:
   
   // Called by GetURL and PostURL (via NewStream)
   nsresult Initialize(nsIURI *aURL,
                       nsNPAPIPluginInstance *aInstance,
                       nsIPluginStreamListener *aListener);
   
   nsresult InitializeEmbedded(nsIURI *aURL,
                               nsNPAPIPluginInstance* aInstance,
-                              nsIPluginInstanceOwner *aOwner = nsnull);
+                              nsObjectLoadingContent *aContent);
   
   nsresult InitializeFullPage(nsIURI* aURL, nsNPAPIPluginInstance *aInstance);
 
   nsresult OnFileAvailable(nsIFile* aFile);
   
   nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt);
   
   nsNPAPIPluginInstance *GetPluginInstance() { return mPluginInstance; }
   
 private:
   nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
   nsresult SetupPluginCacheFile(nsIChannel* channel);
   nsresult GetInterfaceGlobal(const nsIID& aIID, void** result);
 
   nsCOMPtr<nsIURI> mURL;
   nsCString mURLSpec; // Have to keep this member because GetURL hands out char*
-  nsCOMPtr<nsIPluginInstanceOwner> mOwner;
+  nsCOMPtr<nsIObjectLoadingContent> mContent;
   nsRefPtr<nsNPAPIPluginStreamListener> mPStreamListener;
 
   // Set to true if we request failed (like with a HTTP response of 404)
   bool                    mRequestFailed;
   
   /*
    * Set to true after nsIPluginStreamListener::OnStartBinding() has
    * been called.  Checked in ::OnStopRequest so we can call the
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -100,16 +100,20 @@ include $(topsrcdir)/config/rules.mk
   test_enumerate.html \
   test_npruntime_construct.html \
   307-xo-redirect.sjs \
   test_redirect_handling.html \
   test_zero_opacity.html \
   test_NPPVpluginWantsAllNetworkStreams.html \
   test_npruntime_npnsetexception.html \
   test_NPNVdocumentOrigin.html \
+  test_instance_re-parent.html \
+  test_instance_unparent1.html \
+  test_instance_unparent2.html \
+  test_instance_unparent3.html \
   $(NULL)
 
 #  test_plugin_scroll_painting.html \ bug 596491
 
 ifeq ($(OS_ARCH),WINNT)
 _MOCHITEST_FILES += \
   test_windowed_invalidate.html \
   $(NULL)
@@ -124,16 +128,17 @@ endif
   test_npruntime.xul   \
   test_privatemode.xul \
   test_wmode.xul \
   test_bug479979.xul \
   $(NULL)
 
 ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 _MOCHITEST_FILES += \
+  test_instance_re-parent-windowed.html \
   test_visibility.html \
   $(NULL)
 
 ifneq ($(OS_ARCH),WINNT)
 _MOCHICHROME_FILES += \
   test_xulbrowser_plugin_visibility.xul \
   xulbrowser_plugin_visibility.xul \
   plugin_visibility_loader.html \
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_instance_re-parent-windowed.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test re-parentinging an instance's DOM node</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="startTest()">
+  <p id="display"></p>
+
+  <div id="div1">
+    <embed id="plugin1" type="application/x-test" width="200" height="200" wmode="window"></embed>
+  </div>
+  <div id="div2">
+  </div>
+
+  <script type="application/javascript;version=1.8">
+  SimpleTest.waitForExplicitFinish();
+
+  var destroyed = false;
+  function onDestroy() {
+    destroyed = true;
+  }
+
+  function startTest() {
+    var exceptionThrown = false;
+
+    var p = document.getElementById('plugin1');
+    var d1 = document.getElementById('div1');
+    var d2 = document.getElementById('div2');
+
+    p.startWatchingInstanceCount();
+    p.callOnDestroy(onDestroy);
+
+    try {
+      d1.removeChild(p);
+    } catch (e) {
+      exceptionThrown = true;
+    }
+    is(exceptionThrown, false, "Testing for exception after removeChild.");
+
+    try {
+      d2.appendChild(p);
+    } catch (e) {
+      exceptionThrown = true;
+    }
+    is(exceptionThrown, false, "Testing for exception after appendChild.");
+
+    is(destroyed, false, "No instances should have been destroyed at this point.");
+    is(p.getInstanceCount(), 0, "No new instances should have been created at this point.");
+
+    p.stopWatchingInstanceCount();
+
+    SimpleTest.finish();
+  }
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_instance_re-parent.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test re-parentinging an instance's DOM node</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="runTests()">
+  <p id="display"></p>
+
+  <div id="div1">
+    <!-- This embed has to have a "src" attribute. Part of this test involves seeing if we
+         properly restart plugins that have been added back to a document without a change
+         in URL. Not re-loading an object when the URL hasn't changed is a shortcut used for
+         some object types. Without a URL, this won't be tested. -->
+    <embed id="plugin1" src="loremipsum.txt" type="application/x-test" width="200" height="200"></embed>
+  </div>
+  <div id="div2">
+  </div>
+
+  <script type="application/javascript;version=1.8">
+  SimpleTest.waitForExplicitFinish();
+
+  var exceptionThrown = false;
+  var p = document.getElementById('plugin1');
+  var d1 = document.getElementById('div1');
+  var d2 = document.getElementById('div2');
+
+  var destroyed = false;
+  function onDestroy() {
+    destroyed = true;
+  }
+
+  function testsFinished() {
+    p.stopWatchingInstanceCount();
+    SimpleTest.finish();
+  }
+
+  function continueTests2() {
+    try {
+      is(p.getInstanceCount(), 1, "One new instance should have been created at this point.");
+    } catch (e) {
+      exceptionThrown = true;
+    }
+    is(exceptionThrown, false, "Testing for exception getting instance count from plugin.");
+
+    testsFinished();
+  }
+
+  function continueTests1() {
+    // Adding to the document will kick off the plugin load. Need to have a timeout
+    // before we can safely call into it.
+    d2.appendChild(p);
+    setTimeout('continueTests2();', 0);
+  }
+
+  function runTests() {
+    // First tests involve moving the instance from one div to another.
+    p.startWatchingInstanceCount();
+    p.callOnDestroy(onDestroy);
+
+    try {
+      d1.removeChild(p);
+    } catch (e) {
+      exceptionThrown = true;
+    }
+    is(exceptionThrown, false, "Testing for exception after removeChild.");
+
+    try {
+      d2.appendChild(p);
+    } catch (e) {
+      exceptionThrown = true;
+    }
+    is(exceptionThrown, false, "Testing for exception after appendChild.");
+
+    is(destroyed, false, "No instances should have been destroyed at this point.");
+    is(p.getInstanceCount(), 0, "No new instances should have been created at this point.");
+
+    // Now remove the instance from the document and let it die.
+    d2.removeChild(p);
+    setTimeout('continueTests1();', 0);
+  }
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_instance_unparent1.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test removing an instance's DOM node</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="startTest()">
+  <p id="display"></p>
+
+  <div id="div1">
+    <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+  </div>
+
+  <script type="application/javascript;version=1.8">
+  SimpleTest.waitForExplicitFinish();
+
+  var destroyed = false;
+  function onDestroy() {
+    destroyed = true;
+  }
+
+  function checkPluginAlreadyDestroyed() {
+    is(destroyed, true, "Plugin instance should have been destroyed.");
+    SimpleTest.finish();
+  }
+
+  function startTest() {
+    var p1 = document.getElementById('plugin1');
+    var d1 = document.getElementById('div1');
+
+    p1.callOnDestroy(onDestroy);
+
+    setTimeout(checkPluginAlreadyDestroyed, 0);
+
+    d1.removeChild(p1);
+  }
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_instance_unparent2.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test removing an instance's DOM node</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="startTest()">
+  <p id="display"></p>
+
+  <div id="div1">
+    <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+  </div>
+
+  <div id="div2">
+    <div id="div3">
+        <embed id="plugin2" type="application/x-test" width="200" height="200"></embed>
+    </div>
+  </div>
+
+  <script type="application/javascript;version=1.8">
+  SimpleTest.waitForExplicitFinish();
+
+  var destroyed = false;
+  function onDestroy() {
+    destroyed = true;
+  }
+
+  function checkPluginAlreadyDestroyed() {
+    is(destroyed, true, "Plugin instance should have been destroyed.");
+    SimpleTest.finish();
+  }
+
+  function startTest() {
+    var p1 = document.getElementById('plugin1');
+    var d1 = document.getElementById('div1');
+
+    p1.callOnDestroy(onDestroy);
+
+    setTimeout(checkPluginAlreadyDestroyed, 0);
+
+    // Get two parent check events to run.
+    d1.removeChild(p1);
+    d1.appendChild(p1);
+    d1.removeChild(p1);
+  }
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_instance_unparent3.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Test removing an instance's DOM node</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="startTest()">
+  <p id="display"></p>
+
+  <div id="div1">
+    <div id="div2">
+      <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+    </div<
+  </div>
+
+  <script type="application/javascript;version=1.8">
+  SimpleTest.waitForExplicitFinish();
+
+  var destroyed = false;
+  function onDestroy() {
+    destroyed = true;
+  }
+
+  function checkPluginAlreadyDestroyed() {
+    is(destroyed, true, "Plugin instance should have been destroyed.");
+    SimpleTest.finish();
+  }
+
+  function startTest() {
+    var p1 = document.getElementById('plugin1');
+    var d1 = document.getElementById('div1');
+    var d2 = document.getElementById('div2');
+
+    p1.callOnDestroy(onDestroy);
+
+    setTimeout(checkPluginAlreadyDestroyed, 0);
+
+    d1.removeChild(d2);
+  }
+  </script>
+</body>
+</html>
--- a/dom/plugins/test/reftest/reftest.list
+++ b/dom/plugins/test/reftest/reftest.list
@@ -2,18 +2,19 @@
 random-if(!haveTestPlugin) != plugin-sanity.html about:blank
 fails-if(!haveTestPlugin) == plugin-sanity.html div-sanity.html
 fails-if(!haveTestPlugin) == plugin-alpha-zindex.html div-alpha-zindex.html
 fails-if(!haveTestPlugin) == plugin-alpha-opacity.html div-alpha-opacity.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == windowless-clipping-1.html windowless-clipping-1-ref.html # bug 631832
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-1.html border-padding-1-ref.html # bug 629430
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html # bug 629430
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) skip-if(Android) == border-padding-3.html border-padding-3-ref.html # bug 629430
-random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
-random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
+# The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
+#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
+#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
 fails-if(!haveTestPlugin) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
 fails-if(!haveTestPlugin) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-1-step.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-2-step.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-5-step.html plugin-background-ref.html
 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-10-step.html plugin-background-ref.html
new file mode 100644
--- /dev/null
+++ b/dom/power/Makefile.in
@@ -0,0 +1,73 @@
+# ***** 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.org build system.
+#
+# 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):
+#   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+#
+# 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
+
+LIBRARY_NAME     = dom_power_s
+XPIDL_MODULE     = dom_power
+LIBXUL_LIBRARY   = 1
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/dom/dom-config.mk
+
+EXPORTS_NAMESPACES = mozilla/dom/power
+
+EXPORTS_mozilla/dom/power = \
+  PowerManagerService.h \
+  $(NULL)
+
+CPPSRCS = \
+  PowerManager.cpp \
+  PowerManagerService.cpp \
+  $(NULL)
+
+XPIDLSRCS = \
+  nsIDOMPowerManager.idl \
+  nsIPowerManagerService.idl \
+  $(NULL)
+
+ifdef ENABLE_TESTS
+DIRS += test
+endif
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/power/PowerManager.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; 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 mozilla.org code.
+ *
+ * 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):
+ *   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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
+ * 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 "PowerManager.h"
+#include "nsContentUtils.h"
+#include "nsDOMClassInfoID.h"
+#include "nsIPowerManagerService.h"
+#include "nsServiceManagerUtils.h"
+
+DOMCI_DATA(MozPowerManager, mozilla::dom::power::PowerManager)
+
+namespace mozilla {
+namespace dom {
+namespace power {
+
+NS_INTERFACE_MAP_BEGIN(PowerManager)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMMozPowerManager)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozPowerManager)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozPowerManager)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(PowerManager)
+NS_IMPL_RELEASE(PowerManager)
+
+NS_IMETHODIMP
+PowerManager::Reboot()
+{
+  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
+
+  nsCOMPtr<nsIPowerManagerService> pmService =
+    do_GetService(POWERMANAGERSERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(pmService, NS_OK);
+
+  pmService->Reboot();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManager::PowerOff()
+{
+  NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_DOM_SECURITY_ERR);
+
+  nsCOMPtr<nsIPowerManagerService> pmService =
+    do_GetService(POWERMANAGERSERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(pmService, NS_OK);
+
+  pmService->PowerOff();
+
+  return NS_OK;
+}
+
+} // power
+} // dom
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/dom/power/PowerManager.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; 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 mozilla.org code.
+ *
+ * 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):
+ *   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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
+ * 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 ***** */
+#ifndef mozilla_dom_power_PowerManager_h
+#define mozilla_dom_power_PowerManager_h
+
+#include "nsIDOMPowerManager.h"
+
+namespace mozilla {
+namespace dom {
+namespace power {
+
+class PowerManager
+  : public nsIDOMMozPowerManager
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMMOZPOWERMANAGER
+
+  PowerManager() {};
+  virtual ~PowerManager() {};
+};
+
+} // namespace power
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_power_PowerManager_h
new file mode 100644
--- /dev/null
+++ b/dom/power/PowerManagerService.cpp
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; 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 mozilla.org code.
+ *
+ * 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):
+ *   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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
+ * 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 "mozilla/Hal.h"
+#include "PowerManagerService.h"
+
+namespace mozilla {
+namespace dom {
+namespace power {
+
+NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService)
+
+/* static */ already_AddRefed<nsIPowerManagerService>
+PowerManagerService::GetInstance()
+{
+  nsCOMPtr<nsIPowerManagerService> pmService;
+
+  pmService = new PowerManagerService();
+
+  return pmService.forget();
+}
+
+NS_IMETHODIMP
+PowerManagerService::Reboot()
+{
+  hal::Reboot();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManagerService::PowerOff()
+{
+  hal::PowerOff();
+  return NS_OK;
+}
+
+} // power
+} // dom
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/dom/power/PowerManagerService.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; 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 mozilla.org code.
+ *
+ * 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):
+ *   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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
+ * 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 ***** */
+#ifndef mozilla_dom_power_PowerManagerService_h
+#define mozilla_dom_power_PowerManagerService_h
+
+#include "nsIPowerManagerService.h"
+#include "nsCOMPtr.h" // for already_AddRefed
+
+namespace mozilla {
+namespace dom {
+namespace power {
+
+class PowerManagerService
+  : public nsIPowerManagerService
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIPOWERMANAGERSERVICE
+
+  static already_AddRefed<nsIPowerManagerService> GetInstance();
+};
+
+} // namespace power
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_power_PowerManagerService_h
new file mode 100644
--- /dev/null
+++ b/dom/power/nsIDOMPowerManager.idl
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * 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.org.
+ *
+ * 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):
+ *  Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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 "nsISupports.idl"
+
+[scriptable, uuid(6ec16abc-2fe8-4ab3-99b0-0f08405be81b)]
+interface nsIDOMMozPowerManager : nsISupports
+{
+    void powerOff();
+    void reboot();
+};
new file mode 100644
--- /dev/null
+++ b/dom/power/nsIPowerManagerService.idl
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * 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.org.
+ *
+ * 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):
+ *  Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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 "nsISupports.idl"
+
+%{C++
+#define NS_POWERMANAGERSERVICE_CID { 0x18c2e238, 0x3a0a, 0x4153, {0x89, 0xfc, 0x16, 0x6b, 0x3b, 0x14, 0x65, 0xa1 } }
+#define POWERMANAGERSERVICE_CONTRACTID "@mozilla.org/power/powermanagerservice;1"
+%}
+
+[scriptable, builtinclass, uuid(38919539-4641-4f0b-9f11-6b6294a9386f)]
+interface nsIPowerManagerService : nsISupports
+{
+    void powerOff();
+    void reboot();
+};
new file mode 100644
--- /dev/null
+++ b/dom/power/test/Makefile.in
@@ -0,0 +1,59 @@
+# ***** 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.org build system.
+#
+# 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):
+#   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+#
+# 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@
+
+relativesrcdir   = dom/power/test
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS = \
+  $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+  test_power_basics.html \
+  $(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+#libs:: $(_CHROME_TEST_FILES)
+#	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/power/test/test_power_basics.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Power API</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Power API **/
+
+ok('mozPower' in navigator, "navigator.mozPower should exist");
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -405,17 +405,17 @@ nsEditor::GetDesiredSpellCheckState()
   if (presShell) {
     nsPresContext* context = presShell->GetPresContext();
     if (context && !context->IsDynamic()) {
       return false;
     }
   }
 
   // Check DOM state
-  nsCOMPtr<nsIContent> content = do_QueryInterface(GetRoot());
+  nsCOMPtr<nsIContent> content = GetRoot();
   if (!content) {
     return false;
   }
 
   if (content->IsRootOfNativeAnonymousSubtree()) {
     content = content->GetParent();
   }
 
@@ -774,131 +774,116 @@ nsEditor::SetTransactionManager(nsITrans
 
 NS_IMETHODIMP 
 nsEditor::Undo(PRUint32 aCount)
 {
 #ifdef NS_DEBUG_EDITOR
   if (gNoisy) { printf("Editor::Undo ----------\n"); }
 #endif
 
-  nsresult result = NS_OK;
   ForceCompositionEnd();
 
   bool hasTxnMgr, hasTransaction = false;
   CanUndo(&hasTxnMgr, &hasTransaction);
-  NS_ENSURE_TRUE(hasTransaction, result);
+  NS_ENSURE_TRUE(hasTransaction, NS_OK);
 
   nsAutoRules beginRulesSniffing(this, kOpUndo, nsIEditor::eNone);
 
-  if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
-  {
-    PRUint32 i=0;
-    for ( ; i<aCount; i++)
-    {
-      result = mTxnMgr->UndoTransaction();
-
-      if (NS_SUCCEEDED(result))
-        result = DoAfterUndoTransaction();
-          
-      if (NS_FAILED(result))
-        break;
-    }
+  if (!mTxnMgr) {
+    return NS_OK;
   }
 
-  return result;
+  for (PRUint32 i = 0; i < aCount; ++i) {
+    nsresult rv = mTxnMgr->UndoTransaction();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = DoAfterUndoTransaction();
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP nsEditor::CanUndo(bool *aIsEnabled, bool *aCanUndo)
 {
   NS_ENSURE_TRUE(aIsEnabled && aCanUndo, NS_ERROR_NULL_POINTER);
-  *aIsEnabled = ((bool)((nsITransactionManager *)0!=mTxnMgr.get()));
-  if (*aIsEnabled)
-  {
-    PRInt32 numTxns=0;
+  *aIsEnabled = !!mTxnMgr;
+  if (*aIsEnabled) {
+    PRInt32 numTxns = 0;
     mTxnMgr->GetNumberOfUndoItems(&numTxns);
-    *aCanUndo = ((bool)(0!=numTxns));
-  }
-  else {
+    *aCanUndo = !!numTxns;
+  } else {
     *aCanUndo = false;
   }
   return NS_OK;
 }
 
 
 NS_IMETHODIMP 
 nsEditor::Redo(PRUint32 aCount)
 {
 #ifdef NS_DEBUG_EDITOR
   if (gNoisy) { printf("Editor::Redo ----------\n"); }
 #endif
 
-  nsresult result = NS_OK;
-
   bool hasTxnMgr, hasTransaction = false;
   CanRedo(&hasTxnMgr, &hasTransaction);
-  NS_ENSURE_TRUE(hasTransaction, result);
+  NS_ENSURE_TRUE(hasTransaction, NS_OK);
 
   nsAutoRules beginRulesSniffing(this, kOpRedo, nsIEditor::eNone);
 
-  if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
-  {
-    PRUint32 i=0;
-    for ( ; i<aCount; i++)
-    {
-      result = mTxnMgr->RedoTransaction();
-
-      if (NS_SUCCEEDED(result))
-        result = DoAfterRedoTransaction();
-
-      if (NS_FAILED(result))
-        break;
-    }
+  if (!mTxnMgr) {
+    return NS_OK;
   }
 
-  return result;
+  for (PRUint32 i = 0; i < aCount; ++i) {
+    nsresult rv = mTxnMgr->RedoTransaction();
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = DoAfterRedoTransaction();
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP nsEditor::CanRedo(bool *aIsEnabled, bool *aCanRedo)
 {
   NS_ENSURE_TRUE(aIsEnabled && aCanRedo, NS_ERROR_NULL_POINTER);
 
-  *aIsEnabled = ((bool)((nsITransactionManager *)0!=mTxnMgr.get()));
-  if (*aIsEnabled)
-  {
-    PRInt32 numTxns=0;
+  *aIsEnabled = !!mTxnMgr;
+  if (*aIsEnabled) {
+    PRInt32 numTxns = 0;
     mTxnMgr->GetNumberOfRedoItems(&numTxns);
-    *aCanRedo = ((bool)(0!=numTxns));
-  }
-  else {
+    *aCanRedo = !!numTxns;
+  } else {
     *aCanRedo = false;
   }
   return NS_OK;
 }
 
 
 NS_IMETHODIMP 
 nsEditor::BeginTransaction()
 {
   BeginUpdateViewBatch();
 
-  if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
-  {
+  if (mTxnMgr) {
     mTxnMgr->BeginBatch();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsEditor::EndTransaction()
 {
-  if ((nsITransactionManager *)nsnull!=mTxnMgr.get())
-  {
+  if (mTxnMgr) {
     mTxnMgr->EndBatch();
   }
 
   EndUpdateViewBatch();
 
   return NS_OK;
 }
 
@@ -919,19 +904,17 @@ nsEditor::BeginPlaceHolderTransaction(ns
     // time to turn on the batch
     BeginUpdateViewBatch();
     mPlaceHolderTxn = nsnull;
     mPlaceHolderName = aName;
     nsCOMPtr<nsISelection> selection;
     nsresult res = GetSelection(getter_AddRefs(selection));
     if (NS_SUCCEEDED(res)) {
       mSelState = new nsSelectionState();
-      if (mSelState) {
-        mSelState->SaveSelection(selection);
-      }
+      mSelState->SaveSelection(selection);
     }
   }
   mPlaceHolderBatch++;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP 
@@ -940,22 +923,22 @@ nsEditor::EndPlaceHolderTransaction()
   NS_PRECONDITION(mPlaceHolderBatch > 0, "zero or negative placeholder batch count when ending batch!");
   if (mPlaceHolderBatch == 1)
   {
     nsCOMPtr<nsISelection>selection;
     GetSelection(getter_AddRefs(selection));
 
     nsCOMPtr<nsISelectionPrivate>selPrivate(do_QueryInterface(selection));
 
-   // By making the assumption that no reflow happens during the calls
-   // to EndUpdateViewBatch and ScrollSelectionIntoView, we are able to
-   // allow the selection to cache a frame offset which is used by the
-   // caret drawing code. We only enable this cache here; at other times,
-   // we have no way to know whether reflow invalidates it
-   // See bugs 35296 and 199412.
+    // By making the assumption that no reflow happens during the calls
+    // to EndUpdateViewBatch and ScrollSelectionIntoView, we are able to
+    // allow the selection to cache a frame offset which is used by the
+    // caret drawing code. We only enable this cache here; at other times,
+    // we have no way to know whether reflow invalidates it
+    // See bugs 35296 and 199412.
     if (selPrivate) {
       selPrivate->SetCanCacheFrameOffset(true);
     }
 
     {
       // Hide the caret here to avoid hiding it twice, once in EndUpdateViewBatch
       // and once in ScrollSelectionIntoView.
       nsRefPtr<nsCaret> caret;
@@ -1025,25 +1008,21 @@ nsEditor::SetShouldTxnSetSelection(bool 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEditor::GetDocumentIsEmpty(bool *aDocumentIsEmpty)
 {
   *aDocumentIsEmpty = true;
 
-  nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
-  NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER); 
-
-  bool hasChildNodes;
-  nsresult res = rootElement->HasChildNodes(&hasChildNodes);
-
-  *aDocumentIsEmpty = !hasChildNodes;
-
-  return res;
+  dom::Element* root = GetRoot();
+  NS_ENSURE_TRUE(root, NS_ERROR_NULL_POINTER); 
+
+  *aDocumentIsEmpty = !root->HasChildren();
+  return NS_OK;
 }
 
 
 // XXX: the rule system should tell us which node to select all on (ie, the root, or the body)
 NS_IMETHODIMP nsEditor::SelectAll()
 {
   if (!mDocWeak) { return NS_ERROR_NOT_INITIALIZED; }
   ForceCompositionEnd();
@@ -1066,47 +1045,39 @@ NS_IMETHODIMP nsEditor::BeginningOfDocum
 
   // get the selection
   nsCOMPtr<nsISelection> selection;
   nsresult result = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
     
   // get the root element 
-  nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
+  dom::Element* rootElement = GetRoot();
   NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER); 
   
   // find first editable thingy
-  nsCOMPtr<nsIDOMNode> firstNode;
-  result = GetFirstEditableNode(rootElement, address_of(firstNode));
-  if (firstNode)
-  {
-    // if firstNode is text, set selection to beginning of the text node
-    if (IsTextNode(firstNode)) 
-    {
-      result = selection->Collapse(firstNode, 0);
-    }
-    else
-    { // otherwise, it's a leaf node and we set the selection just in front of it
-      nsCOMPtr<nsIDOMNode> parentNode;
-      result = firstNode->GetParentNode(getter_AddRefs(parentNode));
-      if (NS_FAILED(result)) { return result; }
-      if (!parentNode) { return NS_ERROR_NULL_POINTER; }
-      PRInt32 offsetInParent;
-      result = nsEditor::GetChildOffset(firstNode, parentNode, offsetInParent);
-      NS_ENSURE_SUCCESS(result, result);
-      result = selection->Collapse(parentNode, offsetInParent);
-    }
+  nsCOMPtr<nsINode> firstNode = GetFirstEditableNode(rootElement);
+  if (!firstNode) {
+    // just the root node, set selection to inside the root
+    return selection->CollapseNative(rootElement, 0);
+  }
+
+  if (firstNode->NodeType() == nsIDOMNode::TEXT_NODE) {
+    // If firstNode is text, set selection to beginning of the text node.
+    return selection->CollapseNative(firstNode, 0);
   }
-  else
-  {
-    // just the root node, set selection to inside the root
-    result = selection->Collapse(rootElement, 0);
+
+  // Otherwise, it's a leaf node and we set the selection just in front of it.
+  nsCOMPtr<nsIContent> parent = firstNode->GetParent();
+  if (!parent) {
+    return NS_ERROR_NULL_POINTER;
   }
-  return result;
+
+  PRInt32 offsetInParent = parent->IndexOf(firstNode);
+  return selection->CollapseNative(parent, offsetInParent);
 }
 
 NS_IMETHODIMP
 nsEditor::EndOfDocument() 
 { 
   if (!mDocWeak) { return NS_ERROR_NOT_INITIALIZED; } 
   nsresult res; 
 
@@ -1613,16 +1584,23 @@ nsEditor::ReplaceContainer(nsIDOMNode *i
   return DeleteNode(inNode);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // RemoveContainer: remove inNode, reparenting its children into their
 //                  the parent of inNode
 //
 nsresult
+nsEditor::RemoveContainer(nsINode* aNode)
+{
+  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode);
+  return RemoveContainer(node);
+}
+
+nsresult
 nsEditor::RemoveContainer(nsIDOMNode *inNode)
 {
   NS_ENSURE_TRUE(inNode, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMNode> parent;
   PRInt32 offset;
   
   nsresult res = GetNodeLocation(inNode, address_of(parent), &offset);
   NS_ENSURE_SUCCESS(res, res);
@@ -2532,58 +2510,28 @@ NS_IMETHODIMP nsEditor::SelectEntireDocu
 
   nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
   if (!rootElement) { return NS_ERROR_NOT_INITIALIZED; }
 
   return aSelection->SelectAllChildren(rootElement);
 }
 
 
-nsresult nsEditor::GetFirstEditableNode(nsIDOMNode *aRoot, nsCOMPtr<nsIDOMNode> *outFirstNode)
-{
-  NS_ENSURE_TRUE(aRoot && outFirstNode, NS_ERROR_NULL_POINTER);
-  nsresult rv = NS_OK;
-  *outFirstNode = nsnull;
-
-  nsCOMPtr<nsIDOMNode> node = GetLeftmostChild(aRoot);
-  if (node && !IsEditable(node))
-  {
-    nsCOMPtr<nsIDOMNode> next;
-    rv = GetNextNode(node, true, address_of(next));
-    node = next;
+nsINode*
+nsEditor::GetFirstEditableNode(nsINode* aRoot)
+{
+  MOZ_ASSERT(aRoot);
+
+  nsIContent* node = GetLeftmostChild(aRoot);
+  if (node && !IsEditable(node)) {
+    node = GetNextNode(node, /* aEditableNode = */ true);
   }
-  
-  if (node != aRoot)
-    *outFirstNode = node;
-
-  return rv;
-}
-
-#ifdef XXX_DEAD_CODE
-// jfrancis wants to keep this method around for reference
-nsresult nsEditor::GetLastEditableNode(nsIDOMNode *aRoot, nsCOMPtr<nsIDOMNode> *outLastNode)
-{
-  NS_ENSURE_TRUE(aRoot && outLastNode, NS_ERROR_NULL_POINTER);
-  nsresult rv = NS_OK;
-  *outLastNode = nsnull;
-
-  nsCOMPtr<nsIDOMNode> node = GetRightmostChild(aRoot);
-  if (node && !IsEditable(node))
-  {
-    nsCOMPtr<nsIDOMNode> next;
-    rv = GetPriorNode(node, true, address_of(next));
-    node = next;
-  }
-
-  if (node != aRoot)
-    *outLastNode = node;
-
-  return rv;
-}
-#endif
+
+  return (node != aRoot) ? node : nsnull;
+}
 
 
 NS_IMETHODIMP
 nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationType)
 {
   PRInt32 numListeners = mDocStateListeners.Count();
   if (!numListeners)    // maybe there just aren't any.
     return NS_OK;
@@ -3329,38 +3277,51 @@ nsEditor::FindNextLeafNode(nsINode  *aCu
 
     cur = parent;
   }
 
   NS_NOTREACHED("What part of for(;;) do you not understand?");
   return nsnull;
 }
 
-nsresult 
-nsEditor::GetNextNode(nsIDOMNode  *aCurrentNode, 
-                      bool         aEditableNode, 
+nsresult
+nsEditor::GetNextNode(nsIDOMNode* aCurrentNode,
+                      bool aEditableNode,
                       nsCOMPtr<nsIDOMNode> *aResultNode,
-                      bool         bNoBlockCrossing,
-                      nsIContent  *aActiveEditorRoot)
-{
-  if (!aCurrentNode || !aResultNode) { return NS_ERROR_NULL_POINTER; }
-
+                      bool bNoBlockCrossing,
+                      nsIContent* aActiveEditorRoot)
+{
   nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
-  if (!IsDescendantOfBody(currentNode) ||
+  if (!currentNode || !aResultNode) {
+    return NS_ERROR_NULL_POINTER;
+  }
+
+  *aResultNode = do_QueryInterface(GetNextNode(currentNode, aEditableNode,
+                                               bNoBlockCrossing,
+                                               aActiveEditorRoot));
+  return NS_OK;
+}
+
+nsIContent*
+nsEditor::GetNextNode(nsINode* aCurrentNode,
+                      bool aEditableNode,
+                      bool bNoBlockCrossing,
+                      nsIContent* aActiveEditorRoot)
+{
+  MOZ_ASSERT(aCurrentNode);
+
+  if (!IsDescendantOfBody(aCurrentNode) ||
       (aActiveEditorRoot &&
-       !nsContentUtils::ContentIsDescendantOf(currentNode,
+       !nsContentUtils::ContentIsDescendantOf(aCurrentNode,
                                               aActiveEditorRoot))) {
-    *aResultNode = nsnull;
-    return NS_OK;
+    return nsnull;
   }
 
-  *aResultNode =
-    do_QueryInterface(FindNode(currentNode, true, aEditableNode,
-                               bNoBlockCrossing, aActiveEditorRoot));
-  return NS_OK;
+  return FindNode(aCurrentNode, true, aEditableNode, bNoBlockCrossing,
+                  aActiveEditorRoot);
 }
 
 nsIContent*
 nsEditor::FindNode(nsINode *aCurrentNode,
                    bool     aGoForward,
                    bool     aEditableNode,
                    bool     bNoBlockCrossing,
                    nsIContent *aActiveEditorRoot)
@@ -3677,23 +3638,16 @@ nsEditor::IsEditable(nsIContent *aNode)
   }
   if (aNode->NodeType() != nsIDOMNode::TEXT_NODE)
     return true;  // not a text node; not invisible
 
   return IsTextInDirtyFrameVisible(aNode);
 }
 
 bool
-nsEditor::IsMozEditorBogusNode(nsIDOMNode *aNode)
-{
-  nsCOMPtr<nsIContent> element = do_QueryInterface(aNode);
-  return IsMozEditorBogusNode(element);
-}
-
-bool
 nsEditor::IsMozEditorBogusNode(nsIContent *element)
 {
   return element &&
          element->AttrValueIs(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
                               kMOZEditorBogusNodeValue, eCaseMatters);
 }
 
 nsresult
@@ -5125,19 +5079,18 @@ nsEditor::InitializeSelection(nsIDOMEven
 {
   nsCOMPtr<nsINode> targetNode = do_QueryInterface(aFocusEventTarget);
   NS_ENSURE_TRUE(targetNode, NS_ERROR_INVALID_ARG);
   nsCOMPtr<nsIContent> selectionRootContent = FindSelectionRoot(targetNode);
   if (!selectionRootContent) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDocument> targetDoc = do_QueryInterface(aFocusEventTarget);
   bool isTargetDoc =
-    targetNode->IsNodeOfType(nsINode::eDOCUMENT) &&
+    targetNode->NodeType() == nsIDOMNode::DOCUMENT_NODE &&
     targetNode->HasFlag(NODE_IS_EDITABLE);
 
   nsCOMPtr<nsISelection> selection;
   nsresult rv = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -186,16 +186,17 @@ public:
   /* helper routines for node/parent manipulations */
   nsresult ReplaceContainer(nsIDOMNode *inNode, 
                             nsCOMPtr<nsIDOMNode> *outNode, 
                             const nsAString &aNodeType,
                             const nsAString *aAttribute = nsnull,
                             const nsAString *aValue = nsnull,
                             bool aCloneAttributes = false);
 
+  nsresult RemoveContainer(nsINode* aNode);
   nsresult RemoveContainer(nsIDOMNode *inNode);
   nsresult InsertContainerAbove(nsIDOMNode *inNode, 
                                 nsCOMPtr<nsIDOMNode> *outNode, 
                                 const nsAString &aNodeType,
                                 const nsAString *aAttribute = nsnull,
                                 const nsAString *aValue = nsnull);
   nsresult MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset);
 
@@ -499,16 +500,20 @@ public:
     *                       skipping non-editable nodes if aEditableNode is true.
     *                       If there is no prior node, aResultNode will be nsnull.
     */
   nsresult GetNextNode(nsIDOMNode  *aCurrentNode, 
                        bool         aEditableNode,
                        nsCOMPtr<nsIDOMNode> *aResultNode,
                        bool         bNoBlockCrossing = false,
                        nsIContent  *aActiveEditorRoot = nsnull);
+  nsIContent* GetNextNode(nsINode* aCurrentNode,
+                          bool aEditableNode,
+                          bool bNoBlockCrossing = false,
+                          nsIContent* aActiveEditorRoot = nsnull);
 
   // and another version that takes a {parent,offset} pair rather than a node
   nsresult GetNextNode(nsIDOMNode  *aParentNode, 
                        PRInt32      aOffset, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
                        bool         bNoBlockCrossing = false,
                        nsIContent  *aActiveEditorRoot = nsnull);
@@ -569,27 +574,23 @@ public:
 
   /** returns true if aNode is an editable node */
   bool IsEditable(nsIDOMNode *aNode);
   bool IsEditable(nsIContent *aNode);
 
   virtual bool IsTextInDirtyFrameVisible(nsIContent *aNode);
 
   /** returns true if aNode is a MozEditorBogus node */
-  bool IsMozEditorBogusNode(nsIDOMNode *aNode);
   bool IsMozEditorBogusNode(nsIContent *aNode);
 
   /** counts number of editable child nodes */
   nsresult CountEditableChildren(nsIDOMNode *aNode, PRUint32 &outCount);
   
-  /** Find the deep first and last children. Returned nodes are AddReffed */
-  nsresult GetFirstEditableNode(nsIDOMNode *aRoot, nsCOMPtr<nsIDOMNode> *outFirstNode);
-#ifdef XXX_DEAD_CODE
-  nsresult GetLastEditableNode(nsIDOMNode *aRoot, nsCOMPtr<nsIDOMNode> *outLastNode);
-#endif
+  /** Find the deep first and last children. */
+  nsINode* GetFirstEditableNode(nsINode* aRoot);
 
   nsresult GetIMEBufferLength(PRInt32* length);
   bool     IsIMEComposing();    /* test if IME is in composition state */
   void     SetIsIMEComposing(); /* call this before |IsIMEComposing()| */
 
   /** from html rules code - migration in progress */
   static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString);
   static nsIAtom *GetTag(nsIDOMNode *aNode);
--- a/editor/libeditor/html/nsHTMLAbsPosition.cpp
+++ b/editor/libeditor/html/nsHTMLAbsPosition.cpp
@@ -57,16 +57,17 @@
 
 #include "nsIDOMEventTarget.h"
 
 #include "nsIDOMCSSValue.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMRGBColor.h"
 
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 
 #define  BLACK_BG_RGB_TRIGGER 0xd0
 
 NS_IMETHODIMP
 nsHTMLEditor::AbsolutePositionSelection(bool aEnabled)
 {
@@ -556,16 +557,17 @@ nsHTMLEditor::AbsolutelyPositionElement(
     NS_ENSURE_SUCCESS(res, res);
 
     if (childCount == 1) {
       nsCOMPtr<nsIDOMNode> brNode;
       res = CreateBR(parentNode, 0, address_of(brNode));
     }
   }
   else {
+    res = NS_OK;
     mHTMLCSSUtils->RemoveCSSProperty(aElement,
                                      nsEditProperty::cssPosition,
                                      EmptyString(), false);
     mHTMLCSSUtils->RemoveCSSProperty(aElement,
                                      nsEditProperty::cssTop,
                                      EmptyString(), false);
     mHTMLCSSUtils->RemoveCSSProperty(aElement,
                                      nsEditProperty::cssLeft,
@@ -578,20 +580,18 @@ nsHTMLEditor::AbsolutelyPositionElement(
       mHTMLCSSUtils->RemoveCSSProperty(aElement,
                                        nsEditProperty::cssWidth,
                                        EmptyString(), false);
       mHTMLCSSUtils->RemoveCSSProperty(aElement,
                                        nsEditProperty::cssHeight,
                                        EmptyString(), false);
     }
 
-    bool hasStyleOrIdOrClass;
-    res = HasStyleOrIdOrClass(aElement, &hasStyleOrIdOrClass);
-    NS_ENSURE_SUCCESS(res, res);
-    if (!hasStyleOrIdOrClass && nsHTMLEditUtils::IsDiv(aElement)) {
+    nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
+    if (element && element->IsHTML(nsGkAtoms::div) && !HasStyleOrIdOrClass(element)) {
       nsHTMLEditRules* htmlRules = static_cast<nsHTMLEditRules*>(mRules.get());
       NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
       res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
       NS_ENSURE_SUCCESS(res, res);
       res = RemoveContainer(aElement);
     }
   }
   return res;
--- a/editor/libeditor/html/nsHTMLCSSUtils.cpp
+++ b/editor/libeditor/html/nsHTMLCSSUtils.cpp
@@ -536,69 +536,67 @@ nsresult
 nsHTMLCSSUtils::GetCSSInlinePropertyBase(nsIDOMNode *aNode, nsIAtom *aProperty,
                                          nsAString& aValue,
                                          nsIDOMWindow* aWindow,
                                          PRUint8 aStyleType)
 {
   aValue.Truncate();
   NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
 
-  nsCOMPtr<nsIDOMElement> element;
-  nsresult res = GetElementContainerOrSelf(aNode, getter_AddRefs(element));
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr<nsIDOMElement> element = GetElementContainerOrSelf(aNode);
+  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
 
   switch (aStyleType) {
     case COMPUTED_STYLE_TYPE:
       if (element && aWindow) {
         nsAutoString value, propString;
         nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
         aProperty->ToString(propString);
         // Get the all the computed css styles attached to the element node
-        res = aWindow->GetComputedStyle(element, EmptyString(), getter_AddRefs(cssDecl));
+        nsresult res = aWindow->GetComputedStyle(element, EmptyString(), getter_AddRefs(cssDecl));
         if (NS_FAILED(res) || !cssDecl)
           return res;
         // from these declarations, get the one we want and that one only
         res = cssDecl->GetPropertyValue(propString, value);
         NS_ENSURE_SUCCESS(res, res);
         aValue.Assign(value);
       }
       break;
     case SPECIFIED_STYLE_TYPE:
       if (element) {
         nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
         PRUint32 length;
-        res = GetInlineStyles(element, getter_AddRefs(cssDecl), &length);
+        nsresult res = GetInlineStyles(element, getter_AddRefs(cssDecl), &length);
         if (NS_FAILED(res) || !cssDecl) return res;
         nsAutoString value, propString;
         aProperty->ToString(propString);
         res = cssDecl->GetPropertyValue(propString, value);
         NS_ENSURE_SUCCESS(res, res);
         aValue.Assign(value);
       }
       break;
   }
   return NS_OK;
 }
 
 nsresult
 nsHTMLCSSUtils::GetDefaultViewCSS(nsIDOMNode *aNode, nsIDOMWindow **aViewCSS)
 {
-  nsCOMPtr<nsIDOMElement> element;
-  nsresult res = GetElementContainerOrSelf(aNode, getter_AddRefs(element));
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr<nsIDOMElement> element = GetElementContainerOrSelf(aNode);
+  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
 
   // TODO: move this initialization to the top of the function
   *aViewCSS = nsnull;
   if (!element) {
     return NS_OK;
   }
   // find the owner document
   nsCOMPtr<nsIDOMDocument> doc;
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
-  res = node->GetOwnerDocument(getter_AddRefs(doc));
+  nsresult res = node->GetOwnerDocument(getter_AddRefs(doc));
   NS_ENSURE_SUCCESS(res, res);
   if (!doc) {
     return NS_OK;
   }
   nsCOMPtr<nsIDOMWindow> window;
   res = doc->GetDefaultView(getter_AddRefs(window));
   NS_ENSURE_SUCCESS(res, res);
   window.forget(aViewCSS);
@@ -996,73 +994,52 @@ nsHTMLCSSUtils::RemoveCSSEquivalentToHTM
                               cssValueArray[index],
                               aSuppressTransaction);
       NS_ENSURE_SUCCESS(res, res);
     }
   }
   return NS_OK;
 }
 
-// aReturn is true if the element aElement carries an ID or a class.
-nsresult
-nsHTMLCSSUtils::HasClassOrID(nsIDOMElement * aElement, bool & aReturn)
-{
-  nsAutoString classVal, idVal;
-  bool isClassSet, isIdSet;
-  aReturn = false;
-
-  nsresult res = mHTMLEditor->GetAttributeValue(aElement,  NS_LITERAL_STRING("class"), classVal, &isClassSet);
-  NS_ENSURE_SUCCESS(res, res);
-  res = mHTMLEditor->GetAttributeValue(aElement,  NS_LITERAL_STRING("id"), idVal, &isIdSet);
-  NS_ENSURE_SUCCESS(res, res);
-
-  // we need to make sure that if the element has an id or a class attribute,
-  // the attribute is not the empty string
-  aReturn = ((isClassSet && !classVal.IsEmpty()) ||
-             (isIdSet    && !idVal.IsEmpty()));
-  return NS_OK;
-}
-
 // returns in aValueString the list of values for the CSS equivalences to
 // the HTML style aHTMLProperty/aAttribute/aValueString for the node aNode;
 // the value of aStyleType controls the styles we retrieve : specified or
 // computed.
 nsresult
 nsHTMLCSSUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
                                                      nsIAtom *aHTMLProperty,
                                                      const nsAString *aAttribute,
                                                      nsAString & aValueString,
                                                      PRUint8 aStyleType)
 {
   aValueString.Truncate();
-  nsCOMPtr<nsIDOMElement> theElement;
-  nsresult res = GetElementContainerOrSelf(aNode, getter_AddRefs(theElement));
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr<nsIDOMElement> theElement = GetElementContainerOrSelf(aNode);
+  NS_ENSURE_TRUE(theElement, NS_ERROR_NULL_POINTER);
 
   if (theElement && IsCSSEditableProperty(theElement, aHTMLProperty, aAttribute)) {
     // Yes, the requested HTML style has a CSS equivalence in this implementation
     // Retrieve the default ViewCSS if we are asked for computed styles
     nsCOMPtr<nsIDOMWindow> window;
     if (COMPUTED_STYLE_TYPE == aStyleType) {
-      res = GetDefaultViewCSS(theElement, getter_AddRefs(window));
+      nsresult res = GetDefaultViewCSS(theElement, getter_AddRefs(window));
       NS_ENSURE_SUCCESS(res, res);
     }
     nsTArray<nsIAtom*> cssPropertyArray;
     nsTArray<nsString> cssValueArray;
     // get the CSS equivalence with last param true indicating we want only the
     // "gettable" properties
     GenerateCSSDeclarationsFromHTMLStyle(theElement, aHTMLProperty, aAttribute, nsnull,
                                          cssPropertyArray, cssValueArray, true);
     PRInt32 count = cssPropertyArray.Length();
     PRInt32 index;
     for (index = 0; index < count; index++) {
       nsAutoString valueString;
       // retrieve the specified/computed value of the property
-      res = GetCSSInlinePropertyBase(theElement, cssPropertyArray[index],
-                                     valueString, window, aStyleType);
+      nsresult res = GetCSSInlinePropertyBase(theElement, cssPropertyArray[index],
+                                              valueString, window, aStyleType);
       NS_ENSURE_SUCCESS(res, res);
       // append the value to aValueString (possibly with a leading whitespace)
       if (index) aValueString.Append(PRUnichar(' '));
       aValueString.Append(valueString);
     }
   }
   return NS_OK;
 }
@@ -1339,47 +1316,35 @@ nsHTMLCSSUtils::GetInlineStyles(nsIDOMEl
   nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(aElement);
   NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
   nsresult res = inlineStyles->GetStyle(aCssDecl);
   if (NS_FAILED(res) || !aCssDecl) return NS_ERROR_NULL_POINTER;
   (*aCssDecl)->GetLength(aLength);
   return NS_OK;
 }
 
-nsresult
-nsHTMLCSSUtils::GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** aElement)
+already_AddRefed<nsIDOMElement>
+nsHTMLCSSUtils::GetElementContainerOrSelf(nsIDOMNode* aNode)
 {
-  NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
+  nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(node, nsnull);
 
-  nsCOMPtr<nsIDOMNode> node=aNode, parentNode;
-  PRUint16 type;
-  nsresult res;
-  res = node->GetNodeType(&type);
-  NS_ENSURE_SUCCESS(res, res);
-
-  if (nsIDOMNode::DOCUMENT_NODE == type) {
-    return NS_ERROR_NULL_POINTER;
+  if (nsIDOMNode::DOCUMENT_NODE == node->NodeType()) {
+    return nsnull;
   }
 
-  // loop until we find an element
-  while (node && nsIDOMNode::ELEMENT_NODE != type) {
-    parentNode = node;
-    res = parentNode->GetParentNode(getter_AddRefs(node));
-    NS_ENSURE_SUCCESS(res, res);
-    if (node) {
-      res = node->GetNodeType(&type);
-      NS_ENSURE_SUCCESS(res, res);
-    }
+  // Loop until we find an element.
+  while (node && !node->IsElement()) {
+    node = node->GetNodeParent();
   }
-  NS_ASSERTION(node, "we reached a null node ancestor !");
-  NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
+
+  NS_ENSURE_TRUE(node, nsnull);
+
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(node);
-  (*aElement) = element;
-  NS_IF_ADDREF(*aElement);
-  return NS_OK;
+  return element.forget();
 }
 
 nsresult
 nsHTMLCSSUtils::SetCSSProperty(nsIDOMElement * aElement,
                                const nsAString & aProperty,
                                const nsAString & aValue)
 {
   nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
--- a/editor/libeditor/html/nsHTMLCSSUtils.h
+++ b/editor/libeditor/html/nsHTMLCSSUtils.h
@@ -178,23 +178,16 @@ public:
   void        GetDefaultBackgroundColor(nsAString & aColor);
 
   /** Get the default length unit used for CSS Indent/Outdent
     *
     * @param aLengthUnit    [OUT] the default length unit as it is defined in prefs
     */
   void        GetDefaultLengthUnit(nsAString & aLengthUnit);
 
-  /** asnwers true if the element aElement carries an ID or a class
-    *
-    * @param aElement       [IN] a DOM element
-    * @param aReturn        [OUT] the boolean answer
-    */
-  nsresult    HasClassOrID(nsIDOMElement * aElement, bool & aReturn);
-
   /** returns the list of values for the CSS equivalences to
     * the passed HTML style for the passed node
     *
     * @param aNode          [IN] a DOM node
     * @param aHTMLProperty  [IN] an atom containing an HTML property
     * @param aAttribute     [IN] a pointer to an attribute name or nsnull if irrelevant
     * @param aValueString   [OUT] the list of css values
     * @param aStyleType     [IN] SPECIFIED_STYLE_TYPE to query the specified style values
@@ -301,17 +294,17 @@ public:
                            PRUint32 * aLength);
 
   /** returns aNode itself if it is an element node, or the first ancestors being an element
     * node if aNode is not one itself
     *
     * @param aNode           [IN] a node
     * @param aElement        [OUT] the deepest element node containing aNode (possibly aNode itself)
     */
-  nsresult GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** aElement);
+  already_AddRefed<nsIDOMElement> GetElementContainerOrSelf(nsIDOMNode* aNode);
 
   /**
    * Gets the default Window for a given node.
    *
    * @param aNode    the node we want the default Window for
    * @param aWindow  [OUT] the default Window
    */
   nsresult        GetDefaultViewCSS(nsIDOMNode* aNode, nsIDOMWindow** aWindow);
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -842,29 +842,27 @@ nsHTMLEditRules::GetAlignment(bool *aMix
     nsCOMArray<nsIDOMNode> arrayOfNodes;
     res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, kAlign, true);
     NS_ENSURE_SUCCESS(res, res);                                 
     nodeToExamine = arrayOfNodes.SafeObjectAt(0);
   }
 
   NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
 
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
   NS_NAMED_LITERAL_STRING(typeAttrName, "align");
   nsIAtom  *dummyProperty = nsnull;
   nsCOMPtr<nsIDOMNode> blockParent;
   if (mHTMLEditor->IsBlockNode(nodeToExamine))
     blockParent = nodeToExamine;
   else
     blockParent = mHTMLEditor->GetBlockNodeParent(nodeToExamine);
 
   NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
 
-  if (useCSS)
+  if (mHTMLEditor->IsCSSEnabled())
   {
     nsCOMPtr<nsIContent> blockParentContent = do_QueryInterface(blockParent);
     if (blockParentContent && 
         mHTMLEditor->mHTMLCSSUtils->IsCSSEditableProperty(blockParent, dummyProperty, &typeAttrName))
     {
       // we are in CSS mode and we know how to align this element with CSS
       nsAutoString value;
       // let's get the value(s) of text-align or margin-left/margin-right
@@ -966,18 +964,17 @@ nsHTMLEditRules::GetIndentState(bool *aC
   res = GetNodesFromSelection(selection, kIndent, arrayOfNodes, true);
   NS_ENSURE_SUCCESS(res, res);
 
   // examine nodes in selection for blockquotes or list elements;
   // these we can outdent.  Note that we return true for canOutdent
   // if *any* of the selection is outdentable, rather than all of it.
   PRInt32 listCount = arrayOfNodes.Count();
   PRInt32 i;
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
   for (i=listCount-1; i>=0; i--)
   {
     nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
     
     if (nsHTMLEditUtils::IsNodeThatCanOutdent(curNode))
     {
       *aCanOutdent = true;
       break;
@@ -3519,21 +3516,18 @@ nsHTMLEditRules::DidMakeBasicBlock(nsISe
   NS_ENSURE_SUCCESS(res, res);
   res = InsertMozBRIfNeeded(parent);
   return res;
 }
 
 nsresult
 nsHTMLEditRules::WillIndent(nsISelection *aSelection, bool *aCancel, bool * aHandled)
 {
-  bool useCSS;
   nsresult res;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
-  
-  if (useCSS) {
+  if (mHTMLEditor->IsCSSEnabled()) {
     res = WillCSSIndent(aSelection, aCancel, aHandled);
   }
   else {
     res = WillHTMLIndent(aSelection, aCancel, aHandled);
   }
   return res;
 }
 
@@ -3980,18 +3974,17 @@ nsresult
 nsHTMLEditRules::WillOutdent(nsISelection *aSelection, bool *aCancel, bool *aHandled)
 {
   if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
   // initialize out param
   *aCancel = false;
   *aHandled = true;
   nsresult res = NS_OK;
   nsCOMPtr<nsIDOMNode> rememberedLeftBQ, rememberedRightBQ;
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
 
   res = NormalizeSelection(aSelection);
   NS_ENSURE_SUCCESS(res, res);
   // some scoping for selection resetting - we may need to tweak it
   {
     nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
     
     // convert the selection ranges into "promoted" selection ranges:
@@ -4722,23 +4715,20 @@ nsHTMLEditRules::WillAlign(nsISelection 
 
   nsTArray<bool> transitionList;
   res = MakeTransitionList(arrayOfNodes, transitionList);
   NS_ENSURE_SUCCESS(res, res);                                 
 
   // Ok, now go through all the nodes and give them an align attrib or put them in a div, 
   // or whatever is appropriate.  Wohoo!
 
-  PRInt32 i;
   nsCOMPtr<nsIDOMNode> curParent;
   nsCOMPtr<nsIDOMNode> curDiv;
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
-  for (i=0; i<listCount; i++)
-  {
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
+  for (PRInt32 i = 0; i < listCount; ++i) {
     // here's where we actually figure out what to do
     nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i];
 
     // Ignore all non-editable nodes.  Leave them be.
     if (!mHTMLEditor->IsEditable(curNode)) continue;
 
     PRInt32 offset;
     res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
@@ -4866,18 +4856,17 @@ nsHTMLEditRules::AlignInnerBlocks(nsIDOM
 //                  
 nsresult
 nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType)
 {
   NS_ENSURE_TRUE(aNode && alignType, NS_ERROR_NULL_POINTER);
   nsresult res;
   nsCOMPtr <nsIDOMNode> firstChild, lastChild, divNode;
   
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
 
   res = mHTMLEditor->GetFirstEditableChild(aNode, address_of(firstChild));
   NS_ENSURE_SUCCESS(res, res);
   res = mHTMLEditor->GetLastEditableChild(aNode, address_of(lastChild));
   NS_ENSURE_SUCCESS(res, res);
   NS_NAMED_LITERAL_STRING(attr, "align");
   if (!firstChild)
   {
@@ -5847,19 +5836,16 @@ nsHTMLEditRules::GetNodesForOperation(ns
                                       PRInt32 inOperationType,
                                       bool aDontTouchContent)
 {
   PRInt32 rangeCount = inArrayOfRanges.Count();
   
   PRInt32 i;
   nsCOMPtr<nsIDOMRange> opRange;
 
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
-
   nsresult res = NS_OK;
   
   // bust up any inlines that cross our range endpoints,
   // but only if we are allowed to touch content.
   
   if (!aDontTouchContent)
   {
     nsAutoTArray<nsRangeStore, 16> rangeItemArray;
@@ -5960,17 +5946,17 @@ nsHTMLEditRules::GetNodesForOperation(ns
         PRInt32 j=i;
         outArrayOfNodes.RemoveObjectAt(i);
         res = GetInnerContent(node, outArrayOfNodes, &j);
         NS_ENSURE_SUCCESS(res, res);
       }
     }
   }
   // outdent should look inside of divs.
-  if (inOperationType == kOutdent && !useCSS) 
+  if (inOperationType == kOutdent && !mHTMLEditor->IsCSSEnabled()) 
   {
     PRInt32 listCount = outArrayOfNodes.Count();
     for (i=listCount-1; i>=0; i--)
     {
       nsCOMPtr<nsIDOMNode> node = outArrayOfNodes[i];
       if (nsHTMLEditUtils::IsDiv(node))
       {
         PRInt32 j=i;
@@ -7457,21 +7443,19 @@ nsHTMLEditRules::GetTopEnclosingMailCite
 }
 
 
 nsresult 
 nsHTMLEditRules::CacheInlineStyles(nsIDOMNode *aNode)
 {
   NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
 
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
-
-  PRInt32 j;
-  for (j=0; j<SIZE_STYLE_TABLE; j++)
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
+
+  for (PRInt32 j = 0; j < SIZE_STYLE_TABLE; ++j)
   {
     bool isSet = false;
     nsAutoString outValue;
     nsCOMPtr<nsIDOMNode> resultNode;
     if (!useCSS)
     {
       mHTMLEditor->IsTextPropertySetByContent(aNode, mCachedStyles[j].tag, &(mCachedStyles[j].attr), nsnull,
                                isSet, getter_AddRefs(resultNode), &outValue);
@@ -7499,31 +7483,28 @@ nsHTMLEditRules::ReapplyCachedStyles()
   // for them, so that they will be reinserted when new 
   // content is added.
   
   // When we apply cached styles to TypeInState, we always want
   // to blow away prior TypeInState:
   mHTMLEditor->mTypeInState->Reset();
 
   // remember if we are in css mode
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
 
   // get selection point
   nsCOMPtr<nsISelection>selection;
   nsresult res = mHTMLEditor->GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(res, res);
   nsCOMPtr<nsIDOMNode> selNode;
   PRInt32 selOffset;
   res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(res, res);
 
-  res = NS_OK;
-  PRInt32 j;
-  for (j=0; j<SIZE_STYLE_TABLE; j++)
+  for (PRInt32 j = 0; j < SIZE_STYLE_TABLE; ++j)
   {
     if (mCachedStyles[j].mPresent)
     {
       bool bFirst, bAny, bAll;
       bFirst = bAny = bAll = false;
       
       nsAutoString curValue;
       if (useCSS) // check computed style first in css case
@@ -8704,18 +8685,17 @@ nsHTMLEditRules::RemoveAlignment(nsIDOMN
   if (mHTMLEditor->IsTextNode(aNode) || nsHTMLEditUtils::IsTable(aNode)) return NS_OK;
   nsresult res = NS_OK;
 
   nsCOMPtr<nsIDOMNode> child = aNode,tmp;
   if (aChildrenOnly)
   {
     aNode->GetFirstChild(getter_AddRefs(child));
   }
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
+  bool useCSS = mHTMLEditor->IsCSSEnabled();
 
   while (child)
   {
     if (aChildrenOnly) {
       // get the next sibling right now because we could have to remove child
       child->GetNextSibling(getter_AddRefs(tmp));
     }
     else
@@ -8872,19 +8852,17 @@ nsHTMLEditRules::AlignBlock(nsIDOMElemen
   if (!isBlock && !nsHTMLEditUtils::IsHR(node)) {
     // we deal only with blocks; early way out
     return NS_OK;
   }
 
   nsresult res = RemoveAlignment(node, *aAlignType, aContentsOnly);
   NS_ENSURE_SUCCESS(res, res);
   NS_NAMED_LITERAL_STRING(attr, "align");
-  bool useCSS;
-  mHTMLEditor->GetIsCSSEnabled(&useCSS);
-  if (useCSS) {
+  if (mHTMLEditor->IsCSSEnabled()) {
     // let's use CSS alignment; we use margin-left and margin-right for tables
     // and text-align for other block-level elements
     res = mHTMLEditor->SetAttributeOrEquivalent(aElement, attr, *aAlignType, false); 
     NS_ENSURE_SUCCESS(res, res);
   }
   else {
     // HTML case; this code is supposed to be called ONLY if the element
     // supports the align attribute but we'll never know...
--- a/editor/libeditor/html/nsHTMLEditUtils.cpp
+++ b/editor/libeditor/html/nsHTMLEditUtils.cpp
@@ -193,21 +193,29 @@ nsHTMLEditUtils::IsListItem(dom::Element
       || (nodeAtom == nsEditProperty::dd)
       || (nodeAtom == nsEditProperty::dt);
 }
 
 
 ///////////////////////////////////////////////////////////////////////////
 // IsTableElement: true if node an html table, td, tr, ...
 //                  
-bool 
+bool
 nsHTMLEditUtils::IsTableElement(nsIDOMNode *node)
 {
   NS_PRECONDITION(node, "null node passed to nsHTMLEditor::IsTableElement");
-  nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
+  nsCOMPtr<dom::Element> element = do_QueryInterface(node);
+  return element && IsTableElement(element);
+}
+
+bool
+nsHTMLEditUtils::IsTableElement(dom::Element* node)
+{
+  MOZ_ASSERT(node);
+  nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
   return (nodeAtom == nsEditProperty::table)
       || (nodeAtom == nsEditProperty::tr)
       || (nodeAtom == nsEditProperty::td)
       || (nodeAtom == nsEditProperty::th)
       || (nodeAtom == nsEditProperty::thead)
       || (nodeAtom == nsEditProperty::tfoot)
       || (nodeAtom == nsEditProperty::tbody)
       || (nodeAtom == nsEditProperty::caption);
--- a/editor/libeditor/html/nsHTMLEditUtils.h
+++ b/editor/libeditor/html/nsHTMLEditUtils.h
@@ -61,16 +61,17 @@ public:
   static bool IsNodeThatCanOutdent(nsIDOMNode *aNode);
   static bool IsHeader(nsIDOMNode *aNode);
   static bool IsParagraph(nsIDOMNode *aNode);
   static bool IsHR(nsIDOMNode *aNode);
   static bool IsListItem(mozilla::dom::Element* aNode);
   static bool IsListItem(nsIDOMNode *aNode);
   static bool IsTable(nsIDOMNode *aNode);
   static bool IsTableRow(nsIDOMNode *aNode);
+  static bool IsTableElement(mozilla::dom::Element* aNode);
   static bool IsTableElement(nsIDOMNode *aNode);
   static bool IsTableElementButNotTable(nsIDOMNode *aNode);
   static bool IsTableCell(mozilla::dom::Element* node);
   static bool IsTableCell(nsIDOMNode *aNode);
   static bool IsTableCellOrCaption(nsIDOMNode *aNode);
   static bool IsList(mozilla::dom::Element* aNode);
   static bool IsList(nsIDOMNode *aNode);
   static bool IsOrderedList(nsIDOMNode *aNode);
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -1359,142 +1359,23 @@ NS_IMETHODIMP nsHTMLEditor::TabInTable(b
     node = do_QueryInterface(cell);
     if (node) selection->Collapse(node,0);
     return NS_OK;
   }
   
   return res;
 }
 
-NS_IMETHODIMP nsHTMLEditor::CreateBRImpl(nsCOMPtr<nsIDOMNode> *aInOutParent, 
-                                         PRInt32 *aInOutOffset, 
-                                         nsCOMPtr<nsIDOMNode> *outBRNode, 
-                                         EDirection aSelect)
-{
-  NS_ENSURE_TRUE(aInOutParent && *aInOutParent && aInOutOffset && outBRNode, NS_ERROR_NULL_POINTER);
-  *outBRNode = nsnull;
-  nsresult res;
-  
-  // we need to insert a br.  unfortunately, we may have to split a text node to do it.
-  nsCOMPtr<nsIDOMNode> node = *aInOutParent;
-  PRInt32 theOffset = *aInOutOffset;
-  nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(node);
-  NS_NAMED_LITERAL_STRING(brType, "br");
-  nsCOMPtr<nsIDOMNode> brNode;
-  if (nodeAsText)  
-  {
-    nsCOMPtr<nsIDOMNode> tmp;
-    PRInt32 offset;
-    PRUint32 len;
-    nodeAsText->GetLength(&len);
-    GetNodeLocation(node, address_of(tmp), &offset);
-    NS_ENSURE_TRUE(tmp, NS_ERROR_FAILURE);
-    if (!theOffset)
-    {
-      // we are already set to go
-    }
-    else if (theOffset == (PRInt32)len)
-    {
-      // update offset to point AFTER the text node
-      offset++;
-    }
-    else
-    {
-      // split the text node
-      res = SplitNode(node, theOffset, getter_AddRefs(tmp));
-      NS_ENSURE_SUCCESS(res, res);
-      res = GetNodeLocation(node, address_of(tmp), &offset);
-      NS_ENSURE_SUCCESS(res, res);
-    }
-    // create br
-    res = CreateNode(brType, tmp, offset, getter_AddRefs(brNode));
-    NS_ENSURE_SUCCESS(res, res);
-    *aInOutParent = tmp;
-    *aInOutOffset = offset+1;
-  }
-  else
-  {
-    res = CreateNode(brType, node, theOffset, getter_AddRefs(brNode));
-    NS_ENSURE_SUCCESS(res, res);
-    (*aInOutOffset)++;
-  }
-
-  *outBRNode = brNode;
-  if (*outBRNode && (aSelect != eNone))
-  {
-    nsCOMPtr<nsISelection> selection;
-    nsCOMPtr<nsIDOMNode> parent;
-    PRInt32 offset;
-    res = GetSelection(getter_AddRefs(selection));
-    NS_ENSURE_SUCCESS(res, res);
-    nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
-    res = GetNodeLocation(*outBRNode, address_of(parent), &offset);
-    NS_ENSURE_SUCCESS(res, res);
-    if (aSelect == eNext)
-    {
-      // position selection after br
-      selPriv->SetInterlinePosition(true);
-      res = selection->Collapse(parent, offset+1);
-    }
-    else if (aSelect == ePrevious)
-    {
-      // position selection before br
-      selPriv->SetInterlinePosition(true);
-      res = selection->Collapse(parent, offset);
-    }
-  }
-  return NS_OK;
-}
-
-
 NS_IMETHODIMP nsHTMLEditor::CreateBR(nsIDOMNode *aNode, PRInt32 aOffset, nsCOMPtr<nsIDOMNode> *outBRNode, EDirection aSelect)
 {
   nsCOMPtr<nsIDOMNode> parent = aNode;
   PRInt32 offset = aOffset;
   return CreateBRImpl(address_of(parent), &offset, outBRNode, aSelect);
 }
 
-NS_IMETHODIMP nsHTMLEditor::InsertBR(nsCOMPtr<nsIDOMNode> *outBRNode)
-{
-  bool bCollapsed;
-  nsCOMPtr<nsISelection> selection;
-
-  NS_ENSURE_TRUE(outBRNode, NS_ERROR_NULL_POINTER);
-  *outBRNode = nsnull;
-
-  // calling it text insertion to trigger moz br treatment by rules
-  nsAutoRules beginRulesSniffing(this, kOpInsertText, nsIEditor::eNext);
-
-  nsresult res = GetSelection(getter_AddRefs(selection));
-  NS_ENSURE_SUCCESS(res, res);
-  nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
-  res = selection->GetIsCollapsed(&bCollapsed);
-  NS_ENSURE_SUCCESS(res, res);
-  if (!bCollapsed)
-  {
-    res = DeleteSelection(nsIEditor::eNone);
-    NS_ENSURE_SUCCESS(res, res);
-  }
-  nsCOMPtr<nsIDOMNode> selNode;
-  PRInt32 selOffset;
-  res = GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset);
-  NS_ENSURE_SUCCESS(res, res);
-  
-  res = CreateBR(selNode, selOffset, outBRNode);
-  NS_ENSURE_SUCCESS(res, res);
-    
-  // position selection after br
-  res = GetNodeLocation(*outBRNode, address_of(selNode), &selOffset);
-  NS_ENSURE_SUCCESS(res, res);
-  selPriv->SetInterlinePosition(true);
-  res = selection->Collapse(selNode, selOffset+1);
-  
-  return res;
-}
-
 nsresult 
 nsHTMLEditor::CollapseSelectionToDeepestNonTableFirstChild(nsISelection *aSelection, nsIDOMNode *aNode)
 {
   NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
   nsresult res;
 
   nsCOMPtr<nsISelection> selection;
   if (aSelection)
@@ -2094,39 +1975,35 @@ nsHTMLEditor::GetParagraphState(bool *aM
   
   return htmlRules->GetParagraphState(aMixed, outFormat);
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::GetBackgroundColorState(bool *aMixed, nsAString &aOutColor)
 {
   nsresult res;
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-  if (useCSS) {
+  if (IsCSSEnabled()) {
     // if we are in CSS mode, we have to check if the containing block defines
     // a background color
     res = GetCSSBackgroundColorState(aMixed, aOutColor, true);
   }
   else {
     // in HTML mode, we look only at page's background
     res = GetHTMLBackgroundColorState(aMixed, aOutColor);
   }
   return res;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::GetHighlightColorState(bool *aMixed, nsAString &aOutColor)
 {
   nsresult res = NS_OK;
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
   *aMixed = false;
   aOutColor.AssignLiteral("transparent");
-  if (useCSS) {
+  if (IsCSSEnabled()) {
     // in CSS mode, text background can be added by the Text Highlight button
     // we need to query the background of the selection without looking for
     // the block container of the ranges in the selection
     res = GetCSSBackgroundColorState(aMixed, aOutColor, false);
   }
   return res;
 }
 
@@ -2243,52 +2120,51 @@ nsHTMLEditor::GetCSSBackgroundColorState
 NS_IMETHODIMP 
 nsHTMLEditor::GetHTMLBackgroundColorState(bool *aMixed, nsAString &aOutColor)
 {
   //TODO: We don't handle "mixed" correctly!
   NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
   *aMixed = false;
   aOutColor.Truncate();
   
-  nsCOMPtr<nsIDOMElement> element;
+  nsCOMPtr<nsIDOMElement> domElement;
   PRInt32 selectedCount;
   nsAutoString tagName;
   nsresult res = GetSelectedOrParentTableElement(tagName,
                                                  &selectedCount,
-                                                 getter_AddRefs(element));
+                                                 getter_AddRefs(domElement));
   NS_ENSURE_SUCCESS(res, res);
 
-  NS_NAMED_LITERAL_STRING(styleName, "bgcolor"); 
-
-  while (element)
-  {
+  nsCOMPtr<nsINode> element = do_QueryInterface(domElement);
+
+  while (element) {
     // We are in a cell or selected table
-    res = element->GetAttribute(styleName, aOutColor);
-    NS_ENSURE_SUCCESS(res, res);
+    element->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
 
     // Done if we have a color explicitly set
-    if (!aOutColor.IsEmpty())
+    if (!aOutColor.IsEmpty()) {
       return NS_OK;
+    }
 
     // Once we hit the body, we're done
-    if(nsTextEditUtils::IsBody(element)) return NS_OK;
+    if (element->AsElement()->IsHTML(nsGkAtoms::body)) {
+      return NS_OK;
+    }
 
     // No color is set, but we need to report visible color inherited 
     // from nested cells/tables, so search up parent chain
-    nsCOMPtr<nsIDOMNode> parentNode;
-    res = element->GetParentNode(getter_AddRefs(parentNode));
-    NS_ENSURE_SUCCESS(res, res);
-    element = do_QueryInterface(parentNode);
+    element = element->GetElementParent();
   }
 
   // If no table or cell found, get page body
-  mozilla::dom::Element *bodyElement = GetRoot();
+  dom::Element* bodyElement = GetRoot();
   NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
 
-  return bodyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
+  bodyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
+  return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsHTMLEditor::GetListState(bool *aMixed, bool *aOL, bool *aUL, bool *aDL)
 {
   if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
   NS_ENSURE_TRUE(aMixed && aOL && aUL && aDL, NS_ERROR_NULL_POINTER);
   nsHTMLEditRules* htmlRules = static_cast<nsHTMLEditRules*>(mRules.get());
@@ -3593,20 +3469,22 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupp
     }
     iter->Next();
   }
 
   return rv;
 }
 
 
-NS_IMETHODIMP nsHTMLEditor::DeleteNode(nsIDOMNode * aNode)
+NS_IMETHODIMP
+nsHTMLEditor::DeleteNode(nsIDOMNode* aNode)
 {
   // do nothing if the node is read-only
-  if (!IsModifiableNode(aNode) && !IsMozEditorBogusNode(aNode)) {
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
+  if (!IsModifiableNode(aNode) && !IsMozEditorBogusNode(content)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDOMNode> selectAllNode = FindUserSelectAllNode(aNode);
   
   if (selectAllNode)
   {
     return nsEditor::DeleteNode(selectAllNode);
@@ -3663,18 +3541,17 @@ nsHTMLEditor::ContentInserted(nsIDocumen
 
   nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
 
   if (ShouldReplaceRootElement()) {
     ResetRootElementAndEventTarget();
   }
   // We don't need to handle our own modifications
   else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
-    nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aChild);
-    if (node && IsMozEditorBogusNode(node)) {
+    if (IsMozEditorBogusNode(aChild)) {
       // Ignore insertion of the bogus node
       return;
     }
     mRules->DocumentModified();
   }
 }
 
 void
@@ -3684,18 +3561,17 @@ nsHTMLEditor::ContentRemoved(nsIDocument
 {
   nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
 
   if (SameCOMIdentity(aChild, mRootElement)) {
     ResetRootElementAndEventTarget();
   }
   // We don't need to handle our own modifications
   else if (!mAction && (aContainer ? aContainer->IsEditable() : aDocument->IsEditable())) {
-    nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aChild);
-    if (node && IsMozEditorBogusNode(node)) {
+    if (aChild && IsMozEditorBogusNode(aChild)) {
       // Ignore removal of the bogus node
       return;
     }
     mRules->DocumentModified();
   }
 }
 
 
@@ -4127,60 +4003,41 @@ nsHTMLEditor::IsNodeInActiveEditor(nsIDO
     return false;
   }
   return nsContentUtils::ContentIsDescendantOf(node, activeEditingHost);
 }
 
 bool
 nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement)
 {
-  bool caretIsSet = false;
-
-  if (aElement && IsNodeInActiveEditor(aElement)) {
-    nsresult res = NS_OK;
-    nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-    if (content)
-    {
-      nsIAtom *atom = content->Tag();
-      if (atom == nsEditProperty::table ||
-          atom == nsEditProperty::tbody ||
-          atom == nsEditProperty::thead ||
-          atom == nsEditProperty::tfoot ||
-          atom == nsEditProperty::caption ||
-          atom == nsEditProperty::tr ||
-          atom == nsEditProperty::td )
-      {
-        nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
-        nsCOMPtr<nsIDOMNode> parent;
-        // This MUST succeed if IsNodeInActiveEditor was TRUE
-        node->GetParentNode(getter_AddRefs(parent));
-        nsCOMPtr<nsIDOMNode>firstChild;
-        // Find deepest child
-        bool hasChild;
-        while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
-        {
-          if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
-          {
-            parent = node;
-            node = firstChild;
-          }
-        }
-        // Set selection at beginning of deepest node
-        nsCOMPtr<nsISelection> selection;
-        res = GetSelection(getter_AddRefs(selection));
-        if (NS_SUCCEEDED(res) && selection && firstChild)
-        {
-          res = selection->Collapse(firstChild, 0);
-          if (NS_SUCCEEDED(res))
-            caretIsSet = true;
-        }
-      }
-    }
+  if (!aElement || !IsNodeInActiveEditor(aElement)) {
+    return false;
+  }
+
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
+  if (!element || !element->IsHTML()) {
+    return false;
+  }
+
+  if (!nsHTMLEditUtils::IsTableElement(element)) {
+    return false;
   }
-  return caretIsSet;
+
+  nsIContent* node = element;
+  while (node->HasChildren()) {
+    node = node->GetFirstChild();
+  }
+
+  // Set selection at beginning of the found node
+  nsCOMPtr<nsISelection> selection;
+  nsresult rv = GetSelection(getter_AddRefs(selection));
+  NS_ENSURE_SUCCESS(rv, false);
+  NS_ENSURE_TRUE(selection, false);
+
+  return NS_SUCCEEDED(selection->CollapseNative(node, 0));
 }            
 
 ///////////////////////////////////////////////////////////////////////////
 // GetEnclosingTable: find ancestor who is a table, if any
 //                  
 nsCOMPtr<nsIDOMNode> 
 nsHTMLEditor::GetEnclosingTable(nsIDOMNode *aNode)
 {
@@ -4973,20 +4830,18 @@ nsHTMLEditor::IsEmptyNodeImpl(nsINode* a
 // add to aElement the CSS inline styles corresponding to the HTML attribute
 // aAttribute with its value aValue
 nsresult
 nsHTMLEditor::SetAttributeOrEquivalent(nsIDOMElement * aElement,
                                        const nsAString & aAttribute,
                                        const nsAString & aValue,
                                        bool aSuppressTransaction)
 {
-  bool useCSS;
   nsresult res = NS_OK;
-  GetIsCSSEnabled(&useCSS);
-  if (useCSS && mHTMLCSSUtils) {
+  if (IsCSSEnabled() && mHTMLCSSUtils) {
     PRInt32 count;
     res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(aElement, nsnull, &aAttribute, &aValue, &count,
                                                      aSuppressTransaction);
     NS_ENSURE_SUCCESS(res, res);
     if (count) {
       // we found an equivalence ; let's remove the HTML attribute itself if it is set
       nsAutoString existingValue;
       bool wasSet = false;
@@ -5037,20 +4892,18 @@ nsHTMLEditor::SetAttributeOrEquivalent(n
   return res;
 }
 
 nsresult
 nsHTMLEditor::RemoveAttributeOrEquivalent(nsIDOMElement * aElement,
                                           const nsAString & aAttribute,
                                           bool aSuppressTransaction)
 {
-  bool useCSS;
   nsresult res = NS_OK;
-  GetIsCSSEnabled(&useCSS);
-  if (useCSS && mHTMLCSSUtils) {
+  if (IsCSSEnabled() && mHTMLCSSUtils) {
     res = mHTMLCSSUtils->RemoveCSSEquivalentToHTMLStyle(aElement, nsnull, &aAttribute, nsnull,
                                                         aSuppressTransaction);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   nsAutoString existingValue;
   bool wasSet = false;
   res = GetAttributeValue(aElement, aAttribute, existingValue, &wasSet);
@@ -5307,19 +5160,17 @@ nsHTMLEditor::SetCSSBackgroundColor(cons
   }
   return res;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::SetBackgroundColor(const nsAString& aColor)
 {
   nsresult res;
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-  if (useCSS) {
+  if (IsCSSEnabled()) {
     // if we are in CSS mode, we have to apply the background color to the
     // containing block (or the body if we have no block-level element in
     // the document)
     res = SetCSSBackgroundColor(aColor);
   }
   else {
     // but in HTML mode, we can only set the document's background color
     res = SetHTMLBackgroundColor(aColor);
@@ -5334,23 +5185,20 @@ bool
 nsHTMLEditor::NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2)
 {
   if (!aNode1 || !aNode2) 
   {
     NS_NOTREACHED("null node passed to nsEditor::NodesSameType()");
     return false;
   }
 
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-
   nsIAtom *tag1 = GetTag(aNode1);
 
   if (tag1 == GetTag(aNode2)) {
-    if (useCSS && tag1 == nsEditProperty::span) {
+    if (IsCSSEnabled() && tag1 == nsEditProperty::span) {
       if (mHTMLCSSUtils->ElementsSameStyle(aNode1, aNode2)) {
         return true;
       }
     }
     else {
       return true;
     }
   }
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -413,17 +413,24 @@ public:
                                  nsCSSStyleSheet **_retval);
   NS_IMETHOD GetURLForStyleSheet(nsCSSStyleSheet *aStyleSheet, nsAString &aURL);
 
   // Add a url + known style sheet to the internal lists:
   nsresult AddNewStyleSheetToList(const nsAString &aURL,
                                   nsCSSStyleSheet *aStyleSheet);
 
   nsresult RemoveStyleSheetFromList(const nsAString &aURL);
-                       
+
+  bool IsCSSEnabled()
+  {
+    // TODO: removal of mCSSAware and use only the presence of mHTMLCSSUtils
+    return mCSSAware && mHTMLCSSUtils && mHTMLCSSUtils->IsCSSPrefChecked();
+  }
+
+
 protected:
 
   NS_IMETHOD  InitRules();
 
   // Create the event listeners for the editor to install
   virtual void CreateEventListeners();
 
   virtual nsresult InstallEventListeners();
@@ -440,21 +447,16 @@ protected:
   // Return TRUE if aElement is a table-related elemet and caret was set
   bool SetCaretInTableCell(nsIDOMElement* aElement);
   bool IsNodeInActiveEditor(nsIDOMNode* aNode);
 
   // key event helpers
   NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled);
   NS_IMETHOD CreateBR(nsIDOMNode *aNode, PRInt32 aOffset, 
                       nsCOMPtr<nsIDOMNode> *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone);
-  NS_IMETHOD CreateBRImpl(nsCOMPtr<nsIDOMNode> *aInOutParent, 
-                         PRInt32 *aInOutOffset, 
-                         nsCOMPtr<nsIDOMNode> *outBRNode, 
-                         nsIEditor::EDirection aSelect);
-  NS_IMETHOD InsertBR(nsCOMPtr<nsIDOMNode> *outBRNode);
 
 // Table Editing (implemented in nsTableEditor.cpp)
 
   // Table utilities
 
   // Insert a new cell after or before supplied aCell. 
   //  Optional: If aNewCell supplied, returns the newly-created cell (addref'd, of course)
   // This doesn't change or use the current selection
@@ -715,18 +717,18 @@ protected:
   nsresult GetInlinePropertyBase(nsIAtom *aProperty, 
                              const nsAString *aAttribute,
                              const nsAString *aValue,
                              bool *aFirst, 
                              bool *aAny, 
                              bool *aAll,
                              nsAString *outValue,
                              bool aCheckDefaults = true);
-  nsresult HasStyleOrIdOrClass(nsIDOMElement * aElement, bool *aHasStyleOrIdOrClass);
-  nsresult RemoveElementIfNoStyleOrIdOrClass(nsIDOMElement * aElement, nsIAtom * aTag);
+  bool HasStyleOrIdOrClass(mozilla::dom::Element* aElement);
+  nsresult RemoveElementIfNoStyleOrIdOrClass(nsIDOMNode* aElement);
 
   // Whether the outer window of the DOM event target has focus or not.
   bool     OurWindowHasFocus();
 
   // This function is used to insert a string of HTML input optionally with some
   // context information into the editable field.  The HTML input either comes
   // from a transferable object created as part of a drop/paste operation, or from
   // the InsertHTML method.  We may want the HTML input to be sanitized (for example,
--- a/editor/libeditor/html/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/html/nsHTMLEditorStyle.cpp
@@ -52,16 +52,19 @@
 #include "nsIDocumentObserver.h"
 #include "TypeInState.h"
 
 #include "nsIEnumerator.h"
 #include "nsIContent.h"
 #include "nsIContentIterator.h"
 #include "nsAttrName.h"
 
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla;
 
 NS_IMETHODIMP nsHTMLEditor::AddDefaultProperty(nsIAtom *aProperty, 
                                             const nsAString & aAttribute, 
                                             const nsAString & aValue)
 {
   nsString outValue;
   PRInt32 index;
   nsString attr(aAttribute);
@@ -107,19 +110,17 @@ NS_IMETHODIMP nsHTMLEditor::RemoveAllDef
 
 
 // Add the CSS style corresponding to the HTML inline style defined
 // by aProperty aAttribute and aValue to the selection
 NS_IMETHODIMP nsHTMLEditor::SetCSSInlineProperty(nsIAtom *aProperty, 
                             const nsAString & aAttribute, 
                             const nsAString & aValue)
 {
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-  if (useCSS) {
+  if (IsCSSEnabled()) {
     return SetInlineProperty(aProperty, aAttribute, aValue);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, 
                             const nsAString & aAttribute, 
                             const nsAString & aValue)
@@ -302,20 +303,17 @@ nsHTMLEditor::SetInlinePropertyOnTextNod
   
   // don't need to do anything if no characters actually selected
   if (aStartOffset == aEndOffset) return NS_OK;
   
   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aTextNode);
   
   // don't need to do anything if property already set on node
   bool bHasProp;
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-
-  if (useCSS &&
+  if (IsCSSEnabled() &&
       mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)) {
     // the HTML styles defined by aProperty/aAttribute has a CSS equivalence
     // in this implementation for node; let's check if it carries those css styles
     nsAutoString value;
     if (aValue) value.Assign(*aValue);
     mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, aAttribute,
                                                        bHasProp, value,
                                                        COMPUTED_STYLE_TYPE);
@@ -383,20 +381,17 @@ nsHTMLEditor::SetInlinePropertyOnNode( n
   NS_ENSURE_TRUE(aNode && aProperty, NS_ERROR_NULL_POINTER);
 
   nsresult res = NS_OK;
   nsCOMPtr<nsIDOMNode> tmp;
   nsAutoString tag;
   aProperty->ToString(tag);
   ToLowerCase(tag);
   
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-
-  if (useCSS)
+  if (IsCSSEnabled())
   {
     // we are in CSS mode
     if (mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute))
     {
       // the HTML style defined by aProperty/aAttribute has a CSS equivalence
       // in this implementation for the node aNode
       nsCOMPtr<nsIDOMNode> tmp = aNode;
       if (IsTextNode(tmp))
@@ -579,18 +574,17 @@ nsresult nsHTMLEditor::SplitStyleAbovePo
 {
   NS_ENSURE_TRUE(aNode && *aNode && aOffset, NS_ERROR_NULL_POINTER);
   if (outLeftNode)  *outLeftNode  = nsnull;
   if (outRightNode) *outRightNode = nsnull;
   // split any matching style nodes above the node/offset
   nsCOMPtr<nsIDOMNode> parent, tmp = *aNode;
   PRInt32 offset;
 
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
+  bool useCSS = IsCSSEnabled();
 
   bool isSet;
   while (tmp && !IsBlockNode(tmp))
   {
     isSet = false;
     if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(tmp, aProperty, aAttribute)) {
       // the HTML style defined by aProperty/aAttribute has a CSS equivalence
       // in this implementation for the node tmp; let's check if it carries those css styles
@@ -639,19 +633,19 @@ nsresult nsHTMLEditor::ApplyDefaultPrope
     NS_ENSURE_TRUE(propItem, NS_ERROR_NULL_POINTER);
     res = SetInlineProperty(propItem->tag, propItem->attr, propItem->value);
     NS_ENSURE_SUCCESS(res, res);
   }
   return res;
 }
 
 nsresult nsHTMLEditor::RemoveStyleInside(nsIDOMNode *aNode, 
-                                   nsIAtom *aProperty,   // null here means remove all properties
-                                   const nsAString *aAttribute, 
-                                   bool aChildrenOnly)
+                                         nsIAtom *aProperty,   // null here means remove all properties
+                                         const nsAString *aAttribute,
+                                         bool aChildrenOnly)
 {
   NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
   if (IsTextNode(aNode)) return NS_OK;
   nsresult res = NS_OK;
 
   // first process the children
   nsCOMPtr<nsIDOMNode> child, tmp;
   aNode->GetFirstChild(getter_AddRefs(child));
@@ -699,18 +693,17 @@ nsresult nsHTMLEditor::RemoveStyleInside
           // aProperty (bug 215406)
           nsAutoString propertyValue;
           mHTMLCSSUtils->RemoveCSSEquivalentToHTMLStyle(spanNode,
                                                         aProperty,
                                                         aAttribute,
                                                         &propertyValue,
                                                         false);
           // remove the span if it's useless
-          nsCOMPtr<nsIDOMElement> element = do_QueryInterface(spanNode);
-          res = RemoveElementIfNoStyleOrIdOrClass(element, nsEditProperty::span);
+          RemoveElementIfNoStyleOrIdOrClass(spanNode);
         }
       }
       res = RemoveContainer(aNode);
     }
     // otherwise we just want to eliminate the attribute
     else
     {
       if (HasAttr(aNode, aAttribute))
@@ -726,21 +719,18 @@ nsresult nsHTMLEditor::RemoveStyleInside
           nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode);
           NS_ENSURE_TRUE(elem, NS_ERROR_NULL_POINTER);
           res = RemoveAttribute(elem, *aAttribute);
         }
       }
     }
   }
   else {
-    bool useCSS;
-    GetIsCSSEnabled(&useCSS);
-
-    if (!aChildrenOnly
-        && useCSS && mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) {
+    if (!aChildrenOnly && IsCSSEnabled() &&
+        mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) {
       // the HTML style defined by aProperty/aAttribute has a CSS equivalence
       // in this implementation for the node aNode; let's check if it carries those css styles
       nsAutoString propertyValue;
       bool isSet;
       mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(aNode, aProperty, aAttribute,
                                                          isSet, propertyValue,
                                                          SPECIFIED_STYLE_TYPE);
       if (isSet) {
@@ -748,18 +738,18 @@ nsresult nsHTMLEditor::RemoveStyleInside
         // let's remove them
         mHTMLCSSUtils->RemoveCSSEquivalentToHTMLStyle(aNode,
                                                       aProperty,
                                                       aAttribute,
                                                       &propertyValue,
                                                       false);
         // remove the node if it is a span, if its style attribute is empty or absent,
         // and if it does not have a class nor an id
-        nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
-        res = RemoveElementIfNoStyleOrIdOrClass(element, nsEditProperty::span);
+        RemoveElementIfNoStyleOrIdOrClass(aNode);
+        res = NS_OK;
       }
     }
   }  
   if ( aProperty == nsEditProperty::font &&    // or node is big or small and we are setting font size
        (nsHTMLEditUtils::IsBig(aNode) || nsHTMLEditUtils::IsSmall(aNode)) &&
        aAttribute && aAttribute->LowerCaseEqualsLiteral("size"))       
   {
     res = RemoveContainer(aNode);  // if we are setting font size, remove any nested bigs and smalls
@@ -789,63 +779,54 @@ bool nsHTMLEditor::IsOnlyAttribute(nsIDO
       return false;
     }
   }
   // if we made it through all of them without finding a real attribute
   // other than aAttribute, then return true
   return true;
 }
 
-bool nsHTMLEditor::HasAttr(nsIDOMNode *aNode, 
-                             const nsAString *aAttribute)
+bool nsHTMLEditor::HasAttr(nsIDOMNode* aNode,
+                           const nsAString* aAttribute)
 {
   NS_ENSURE_TRUE(aNode, false);
-  if (!aAttribute || aAttribute->IsEmpty()) return true;  // everybody has the 'null' attribute
-  
+  if (!aAttribute || aAttribute->IsEmpty()) {
+    // everybody has the 'null' attribute
+    return true;
+  }
+
   // get element
-  nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(elem, false);
-  
-  // get attribute node
-  nsCOMPtr<nsIDOMAttr> attNode;
-  nsresult res = elem->GetAttributeNode(*aAttribute, getter_AddRefs(attNode));
-  if ((NS_FAILED(res)) || !attNode) return false;
-  return true;
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(element, false);
+
+  nsCOMPtr<nsIAtom> atom = do_GetAtom(*aAttribute);
+  NS_ENSURE_TRUE(atom, false);
+
+  return element->HasAttr(kNameSpaceID_None, atom);
 }
 
 
-bool nsHTMLEditor::HasAttrVal(nsIDOMNode *aNode, 
-                                const nsAString *aAttribute, 
-                                const nsAString *aValue)
+bool nsHTMLEditor::HasAttrVal(nsIDOMNode* aNode,
+                              const nsAString* aAttribute,
+                              const nsAString* aValue)
 {
   NS_ENSURE_TRUE(aNode, false);
-  if (!aAttribute || aAttribute->IsEmpty()) return true;  // everybody has the 'null' attribute
-  
+  if (!aAttribute || aAttribute->IsEmpty()) {
+    // everybody has the 'null' attribute
+    return true;
+  }
+
   // get element
-  nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode);
-  NS_ENSURE_TRUE(elem, false);
-  
-  // get attribute node
-  nsCOMPtr<nsIDOMAttr> attNode;
-  nsresult res = elem->GetAttributeNode(*aAttribute, getter_AddRefs(attNode));
-  if ((NS_FAILED(res)) || !attNode) return false;
-  
-  // check if attribute has a value
-  bool isSet;
-  attNode->GetSpecified(&isSet);
-  // if no value, and that's what we wanted, then return true
-  if (!isSet && (!aValue || aValue->IsEmpty())) return true; 
-  
-  // get attribute value
-  nsAutoString attrVal;
-  attNode->GetValue(attrVal);
-  
-  // do values match?
-  if (attrVal.Equals(*aValue,nsCaseInsensitiveStringComparator())) return true;
-  return false;
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
+  NS_ENSURE_TRUE(element, false);
+
+  nsCOMPtr<nsIAtom> atom = do_GetAtom(*aAttribute);
+  NS_ENSURE_TRUE(atom, false);
+
+  return element->AttrValueIs(kNameSpaceID_None, atom, *aValue, eIgnoreCase);
 }
 
 nsresult nsHTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsIDOMRange *inRange)
 {
   NS_ENSURE_TRUE(inRange, NS_ERROR_NULL_POINTER);
   nsresult res;
   nsCOMPtr<nsIDOMNode> startNode, endNode, parent, tmp;
   PRInt32 startOffset, endOffset, tmpOffset;
@@ -1006,18 +987,17 @@ nsHTMLEditor::GetInlinePropertyBase(nsIA
   NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
 
   nsresult result;
   *aAny=false;
   *aAll=true;
   *aFirst=false;
   bool first=true;
 
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
+  bool useCSS = IsCSSEnabled();
 
   nsCOMPtr<nsISelection>selection;
   result = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
 
   bool isCollapsed;
@@ -1263,19 +1243,17 @@ nsresult nsHTMLEditor::RemoveInlinePrope
   res = GetSelection(getter_AddRefs(selection));
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
 
   bool isCollapsed;
   selection->GetIsCollapsed(&isCollapsed);
 
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-
+  bool useCSS = IsCSSEnabled();
   if (isCollapsed)
   {
     // manipulating text attributes on a collapsed selection only sets state for the next text insertion
 
     // For links, aProperty uses "href", use "a" instead
     if (aProperty == nsEditProperty::href ||
         aProperty == nsEditProperty::name)
       aProperty = nsEditProperty::a;
@@ -1896,56 +1874,46 @@ nsHTMLEditor::GetFontColorState(bool *aM
 }
 
 // the return value is true only if the instance of the HTML editor we created
 // can handle CSS styles (for instance, Composer can, Messenger can't) and if
 // the CSS preference is checked
 nsresult
 nsHTMLEditor::GetIsCSSEnabled(bool *aIsCSSEnabled)
 {
-  *aIsCSSEnabled = false;
-  if (mCSSAware) {
-    // TBD later : removal of mCSSAware and use only the presence of mHTMLCSSUtils
-    if (mHTMLCSSUtils) {
-      *aIsCSSEnabled = mHTMLCSSUtils->IsCSSPrefChecked();
-    }
-  }
+  *aIsCSSEnabled = IsCSSEnabled();
   return NS_OK;
 }
 
-nsresult
-nsHTMLEditor::HasStyleOrIdOrClass(nsIDOMElement * aElement, bool *aHasStyleOrIdOrClass)
+static bool
+HasNonEmptyAttribute(dom::Element* aElement, nsIAtom* aName)
 {
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<nsIDOMNode> node  = do_QueryInterface(aElement);
+  MOZ_ASSERT(aElement);
 
+  nsAutoString value;
+  return aElement->GetAttr(kNameSpaceID_None, aName, value) && !value.IsEmpty();
+}
+
+bool
+nsHTMLEditor::HasStyleOrIdOrClass(dom::Element* aElement)
+{
+  MOZ_ASSERT(aElement);
 
   // remove the node if its style attribute is empty or absent,
   // and if it does not have a class nor an id
-  nsAutoString styleVal;
-  bool isStyleSet;
-  *aHasStyleOrIdOrClass = true;
-  nsresult res = GetAttributeValue(aElement,  NS_LITERAL_STRING("style"), styleVal, &isStyleSet);
-  NS_ENSURE_SUCCESS(res, res);
-  if (!isStyleSet || styleVal.IsEmpty()) {
-    res = mHTMLCSSUtils->HasClassOrID(aElement, *aHasStyleOrIdOrClass);
-    NS_ENSURE_SUCCESS(res, res);
-  }
-  return res;
+  return HasNonEmptyAttribute(aElement, nsGkAtoms::style) ||
+         HasNonEmptyAttribute(aElement, nsGkAtoms::_class) ||
+         HasNonEmptyAttribute(aElement, nsGkAtoms::id);
 }
 
 nsresult
-nsHTMLEditor::RemoveElementIfNoStyleOrIdOrClass(nsIDOMElement * aElement, nsIAtom * aTag)
+nsHTMLEditor::RemoveElementIfNoStyleOrIdOrClass(nsIDOMNode* aElement)
 {
-  NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
-  nsCOMPtr<nsIDOMNode> node  = do_QueryInterface(aElement);
+  nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
+  NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
 
   // early way out if node is not the right kind of element
-  if (!NodeIsType(node, aTag)) {
+  if (!element->IsHTML(nsGkAtoms::span) || HasStyleOrIdOrClass(element)) {
     return NS_OK;
   }
-  bool hasStyleOrIdOrClass;
-  nsresult res = HasStyleOrIdOrClass(aElement, &hasStyleOrIdOrClass);
-  if (!hasStyleOrIdOrClass) {
-    res = RemoveContainer(node);
-  }
-  return res;
+
+  return RemoveContainer(element);
 }
--- a/editor/libeditor/html/nsHTMLObjectResizer.cpp
+++ b/editor/libeditor/html/nsHTMLObjectResizer.cpp
@@ -941,20 +941,16 @@ nsHTMLEditor::SetFinalSize(PRInt32 aX, P
   PRInt32 height = GetNewResizingHeight(aX, aY);
   bool setWidth  = !mResizedObjectIsAbsolutelyPositioned || (width != mResizedObjectWidth);
   bool setHeight = !mResizedObjectIsAbsolutelyPositioned || (height != mResizedObjectHeight);
   
   PRInt32 x, y;
   x = left - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderLeft+mResizedObjectMarginLeft : 0);
   y = top - ((mResizedObjectIsAbsolutelyPositioned) ? mResizedObjectBorderTop+mResizedObjectMarginTop : 0);
 
-  // we need to know if we're in a CSS-enabled editor or not
-  bool useCSS;
-  GetIsCSSEnabled(&useCSS);
-
   // we want one transaction only from a user's point of view
   nsAutoEditBatch batchIt(this);
 
   NS_NAMED_LITERAL_STRING(widthStr,  "width");
   NS_NAMED_LITERAL_STRING(heightStr, "height");
   
   bool hasAttr = false;
   if (mResizedObjectIsAbsolutelyPositioned) {
@@ -964,17 +960,17 @@ nsHTMLEditor::SetFinalSize(PRInt32 aX, P
                                           y,
                                           false);
     if (setWidth)
       mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject,
                                           nsEditProperty::cssLeft,
                                           x,
                                           false);
   }
-  if (useCSS || mResizedObjectIsAbsolutelyPositioned) {
+  if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
     if (setWidth && NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
       RemoveAttribute(mResizedObject, widthStr);
 
     hasAttr = false;
     if (setHeight && NS_SUCCEEDED(mResizedObject->HasAttribute(heightStr, &hasAttr)) && hasAttr)
       RemoveAttribute(mResizedObject, heightStr);
 
     if (setWidth)
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -224,107 +224,120 @@ nsPlaintextEditor::EndEditorInit()
       // we're initializing the editor.
       EnableUndo(false);
       EnableUndo(true);
     }
   }
   return res;
 }
 
-NS_IMETHODIMP 
-nsPlaintextEditor::SetDocumentCharacterSet(const nsACString & characterSet) 
-{ 
-  nsresult result; 
+NS_IMETHODIMP
+nsPlaintextEditor::SetDocumentCharacterSet(const nsACString& characterSet)
+{
+  nsresult rv = nsEditor::SetDocumentCharacterSet(characterSet);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  result = nsEditor::SetDocumentCharacterSet(characterSet); 
+  // Update META charset element.
+  nsCOMPtr<nsIDOMDocument> domdoc;
+  rv = GetDocument(getter_AddRefs(domdoc));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(domdoc, NS_ERROR_FAILURE);
 
-  // update META charset tag 
-  if (NS_SUCCEEDED(result)) { 
-    nsCOMPtr<nsIDOMDocument>domdoc; 
-    result = GetDocument(getter_AddRefs(domdoc)); 
-    if (NS_SUCCEEDED(result) && domdoc) { 
-      nsCOMPtr<nsIDOMNodeList>metaList; 
-      nsCOMPtr<nsIDOMElement>metaElement; 
-      bool newMetaCharset = true; 
+  if (UpdateMetaCharset(domdoc, characterSet)) {
+    return NS_OK;
+  }
 
-      // get a list of META tags 
-      result = domdoc->GetElementsByTagName(NS_LITERAL_STRING("meta"), getter_AddRefs(metaList)); 
-      if (NS_SUCCEEDED(result) && metaList) { 
-        PRUint32 listLength = 0; 
-        (void) metaList->GetLength(&listLength); 
+  nsCOMPtr<nsIDOMNodeList> headList;
+  rv = domdoc->GetElementsByTagName(NS_LITERAL_STRING("head"), getter_AddRefs(headList));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(headList, NS_OK);
+
+  nsCOMPtr<nsIDOMNode> headNode;
+  headList->Item(0, getter_AddRefs(headNode));
+  NS_ENSURE_TRUE(headNode, NS_OK);
 
-        nsCOMPtr<nsIDOMNode>metaNode; 
-        for (PRUint32 i = 0; i < listLength; i++) { 
-          metaList->Item(i, getter_AddRefs(metaNode)); 
-          if (!metaNode) continue; 
-          metaElement = do_QueryInterface(metaNode); 
-          if (!metaElement) continue; 
+  // Create a new meta charset tag
+  nsCOMPtr<nsIDOMNode> resultNode;
+  rv = CreateNode(NS_LITERAL_STRING("meta"), headNode, 0, getter_AddRefs(resultNode));
+  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(resultNode, NS_OK);
 
-          nsAutoString currentValue; 
-          if (NS_FAILED(metaElement->GetAttribute(NS_LITERAL_STRING("http-equiv"), currentValue))) continue; 
+  // Set attributes to the created element
+  if (characterSet.IsEmpty()) {
+    return NS_OK;
+  }
 
-          if (FindInReadable(NS_LITERAL_STRING("content-type"),
-                             currentValue,
-                             nsCaseInsensitiveStringComparator())) { 
-            NS_NAMED_LITERAL_STRING(content, "content");
-            if (NS_FAILED(metaElement->GetAttribute(content, currentValue))) continue; 
+  nsCOMPtr<dom::Element> metaElement = do_QueryInterface(resultNode);
+  if (!metaElement) {
+    return NS_OK;
+  }
 
-            NS_NAMED_LITERAL_STRING(charsetEquals, "charset=");
-            nsAString::const_iterator originalStart, start, end;
-            originalStart = currentValue.BeginReading(start);
-            currentValue.EndReading(end);
-            if (FindInReadable(charsetEquals, start, end,
-                               nsCaseInsensitiveStringComparator())) {
+  // not undoable, undo should undo CreateNode
+  metaElement->SetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv,
+                       NS_LITERAL_STRING("Content-Type"), true);
+  metaElement->SetAttr(kNameSpaceID_None, nsGkAtoms::content,
+                       NS_LITERAL_STRING("text/html;charset=") +
+                         NS_ConvertASCIItoUTF16(characterSet),
+                       true);
+  return NS_OK;
+}
 
-              // set attribute to <original prefix> charset=text/html
-              result = nsEditor::SetAttribute(metaElement, content,
-                                              Substring(originalStart, start) +
-                                              charsetEquals + NS_ConvertASCIItoUTF16(characterSet)); 
-              if (NS_SUCCEEDED(result)) 
-                newMetaCharset = false; 
-              break; 
-            } 
-          } 
-        } 
-      } 
+bool
+nsPlaintextEditor::UpdateMetaCharset(nsIDOMDocument* aDocument,
+                                     const nsACString& aCharacterSet)
+{
+  // get a list of META tags
+  nsCOMPtr<nsIDOMNodeList> metaList;
+  nsresult rv = aDocument->GetElementsByTagName(NS_LITERAL_STRING("meta"),
+                                                getter_AddRefs(metaList));
+  NS_ENSURE_SUCCESS(rv, false);
+  NS_ENSURE_TRUE(metaList, false);
+
+  PRUint32 listLength = 0;
+  metaList->GetLength(&listLength);
+
+  for (PRUint32 i = 0; i < listLength; ++i) {
+    nsCOMPtr<nsIContent> metaNode = metaList->GetNodeAt(i);
+    MOZ_ASSERT(metaNode);
+
+    if (!metaNode->IsElement()) {
+      continue;
+    }
+
+    nsAutoString currentValue;
+    metaNode->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, currentValue);
 
-      if (newMetaCharset) { 
-        nsCOMPtr<nsIDOMNodeList>headList; 
-        result = domdoc->GetElementsByTagName(NS_LITERAL_STRING("head"),getter_AddRefs(headList)); 
-        if (NS_SUCCEEDED(result) && headList) { 
-          nsCOMPtr<nsIDOMNode>headNode; 
-          headList->Item(0, getter_AddRefs(headNode)); 
-          if (headNode) { 
-            nsCOMPtr<nsIDOMNode>resultNode; 
-            // Create a new meta charset tag 
-            result = CreateNode(NS_LITERAL_STRING("meta"), headNode, 0, getter_AddRefs(resultNode)); 
-            NS_ENSURE_SUCCESS(result, NS_ERROR_FAILURE); 
+    if (!FindInReadable(NS_LITERAL_STRING("content-type"),
+                        currentValue,
+                        nsCaseInsensitiveStringComparator())) {
+      continue;
+    }
+
+    metaNode->GetAttr(kNameSpaceID_None, nsGkAtoms::content, currentValue);
 
-            // Set attributes to the created element 
-            if (resultNode && !characterSet.IsEmpty()) { 
-              metaElement = do_QueryInterface(resultNode); 
-              if (metaElement) { 
-                // not undoable, undo should undo CreateNode 
-                result = metaElement->SetAttribute(NS_LITERAL_STRING("http-equiv"), NS_LITERAL_STRING("Content-Type")); 
-                if (NS_SUCCEEDED(result)) { 
-                  // not undoable, undo should undo CreateNode 
-                  result = metaElement->SetAttribute(NS_LITERAL_STRING("content"),
-                                                     NS_LITERAL_STRING("text/html;charset=") + NS_ConvertASCIItoUTF16(characterSet)); 
-                } 
-              } 
-            } 
-          } 
-        } 
-      } 
-    } 
-  } 
+    NS_NAMED_LITERAL_STRING(charsetEquals, "charset=");
+    nsAString::const_iterator originalStart, start, end;
+    originalStart = currentValue.BeginReading(start);
+    currentValue.EndReading(end);
+    if (!FindInReadable(charsetEquals, start, end,
+                        nsCaseInsensitiveStringComparator())) {
+      continue;
+    }
 
-  return result; 
-} 
-
+    // set attribute to <original prefix> charset=text/html
+    nsCOMPtr<nsIDOMElement> metaElement = do_QueryInterface(metaNode);
+    MOZ_ASSERT(metaElement);
+    rv = nsEditor::SetAttribute(metaElement, NS_LITERAL_STRING("content"),
+                                Substring(originalStart, start) +
+                                  charsetEquals +
+                                  NS_ConvertASCIItoUTF16(aCharacterSet));
+    return NS_SUCCEEDED(rv);
+  }
+  return false;
+}
 
 NS_IMETHODIMP nsPlaintextEditor::InitRules()
 {
   // instantiate the rules for this text editor
   mRules = new nsTextEditRules();
   return mRules->Init(this);
 }
 
@@ -431,19 +444,23 @@ NS_IMETHODIMP nsPlaintextEditor::TypedTe
     case eTypedBreak:
       {
         return InsertLineBreak();
       } 
   } 
   return NS_ERROR_FAILURE; 
 }
 
-NS_IMETHODIMP nsPlaintextEditor::CreateBRImpl(nsCOMPtr<nsIDOMNode> *aInOutParent, PRInt32 *aInOutOffset, nsCOMPtr<nsIDOMNode> *outBRNode, EDirection aSelect)
+nsresult
+nsPlaintextEditor::CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
+                                PRInt32* aInOutOffset,
+                                nsCOMPtr<nsIDOMNode>* outBRNode,
+                                EDirection aSelect)
 {
-  NS_ENSURE_SUCCESS(aInOutParent && *aInOutParent && aInOutOffset && outBRNode, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(aInOutParent && *aInOutParent && aInOutOffset && outBRNode, NS_ERROR_NULL_POINTER);
   *outBRNode = nsnull;
   nsresult res;
   
   // we need to insert a br.  unfortunately, we may have to split a text node to do it.
   nsCOMPtr<nsIDOMNode> node = *aInOutParent;
   PRInt32 theOffset = *aInOutOffset;
   nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(node);
   NS_NAMED_LITERAL_STRING(brType, "br");
@@ -517,17 +534,18 @@ NS_IMETHODIMP nsPlaintextEditor::CreateB
 
 NS_IMETHODIMP nsPlaintextEditor::CreateBR(nsIDOMNode *aNode, PRInt32 aOffset, nsCOMPtr<nsIDOMNode> *outBRNode, EDirection aSelect)
 {
   nsCOMPtr<nsIDOMNode> parent = aNode;
   PRInt32 offset = aOffset;
   return CreateBRImpl(address_of(parent), &offset, outBRNode, aSelect);
 }
 
-NS_IMETHODIMP nsPlaintextEditor::InsertBR(nsCOMPtr<nsIDOMNode> *outBRNode)
+nsresult
+nsPlaintextEditor::InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode)
 {
   NS_ENSURE_TRUE(outBRNode, NS_ERROR_NULL_POINTER);
   *outBRNode = nsnull;
 
   // calling it text insertion to trigger moz br treatment by rules
   nsAutoRules beginRulesSniffing(this, kOpInsertText, nsIEditor::eNext);
 
   nsCOMPtr<nsISelection> selection;
@@ -1328,58 +1346,58 @@ nsPlaintextEditor::GetAndInitDocEncoder(
 {
   nsresult rv = NS_OK;
 
   nsCAutoString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
   formatType.AppendWithConversion(aFormatType);
   nsCOMPtr<nsIDocumentEncoder> docEncoder (do_CreateInstance(formatType.get(), &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
-  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
+  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryReferent(mDocWeak);
   NS_ASSERTION(domDoc, "Need a document");
 
   rv = docEncoder->Init(domDoc, aFormatType, aFlags);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  if (!aCharset.IsEmpty()
-    && !(aCharset.EqualsLiteral("null")))
+  if (!aCharset.IsEmpty() && !aCharset.EqualsLiteral("null")) {
     docEncoder->SetCharset(aCharset);
+  }
 
   PRInt32 wc;
   (void) GetWrapWidth(&wc);
   if (wc >= 0)
     (void) docEncoder->SetWrapColumn(wc);
 
   // Set the selection, if appropriate.
   // We do this either if the OutputSelectionOnly flag is set,
   // in which case we use our existing selection ...
   if (aFlags & nsIDocumentEncoder::OutputSelectionOnly)
   {
     nsCOMPtr<nsISelection> selection;
     rv = GetSelection(getter_AddRefs(selection));
-    if (NS_SUCCEEDED(rv) && selection)
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (selection) {
       rv = docEncoder->SetSelection(selection);
-    NS_ENSURE_SUCCESS(rv, rv);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
   }
   // ... or if the root element is not a body,
   // in which case we set the selection to encompass the root.
   else
   {
-    nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
+    dom::Element* rootElement = GetRoot();
     NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
-    if (!nsTextEditUtils::IsBody(rootElement))
-    {
-      rv = docEncoder->SetContainerNode(rootElement);
+    if (!rootElement->IsHTML(nsGkAtoms::body)) {
+      rv = docEncoder->SetNativeContainerNode(rootElement);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
-  NS_ADDREF(*encoder = docEncoder);
-  return rv;
+  docEncoder.forget(encoder);
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP 
 nsPlaintextEditor::OutputToString(const nsAString& aFormatType,
                                   PRUint32 aFlags,
                                   nsAString& aOutputString)
 {
--- a/editor/libeditor/text/nsPlaintextEditor.h
+++ b/editor/libeditor/text/nsPlaintextEditor.h
@@ -188,21 +188,21 @@ protected:
   NS_IMETHOD GetAndInitDocEncoder(const nsAString& aFormatType,
                                   PRUint32 aFlags,
                                   const nsACString& aCharset,
                                   nsIDocumentEncoder** encoder);
 
   // key event helpers
   NS_IMETHOD CreateBR(nsIDOMNode *aNode, PRInt32 aOffset, 
                       nsCOMPtr<nsIDOMNode> *outBRNode, EDirection aSelect = eNone);
-  NS_IMETHOD CreateBRImpl(nsCOMPtr<nsIDOMNode> *aInOutParent, 
-                         PRInt32 *aInOutOffset, 
-                         nsCOMPtr<nsIDOMNode> *outBRNode, 
-                         EDirection aSelect);
-  NS_IMETHOD InsertBR(nsCOMPtr<nsIDOMNode> *outBRNode);
+  nsresult CreateBRImpl(nsCOMPtr<nsIDOMNode>* aInOutParent,
+                        PRInt32* aInOutOffset,
+                        nsCOMPtr<nsIDOMNode>* outBRNode,
+                        EDirection aSelect);
+  nsresult InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode);
 
   // factored methods for handling insertion of data from transferables (drag&drop or clipboard)
   NS_IMETHOD PrepareTransferable(nsITransferable **transferable);
   NS_IMETHOD InsertTextFromTransferable(nsITransferable *transferable,
                                         nsIDOMNode *aDestinationNode,
                                         PRInt32 aDestOffset,
                                         bool aDoDeleteSelection);
   virtual nsresult SetupDocEncoder(nsIDocumentEncoder **aDocEncoder);
@@ -216,16 +216,19 @@ protected:
 
   //XXX Kludge: Used to suppress spurious drag/drop events (bug 50703)
   bool     mIgnoreSpuriousDragEvent;
   NS_IMETHOD IgnoreSpuriousDragEvent(bool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;}
 
   bool CanCutOrCopy();
   bool FireClipboardEvent(PRInt32 aType);
 
+  bool UpdateMetaCharset(nsIDOMDocument* aDocument,
+                         const nsACString& aCharacterSet);
+
 // Data members
 protected:
 
   nsCOMPtr<nsIEditRules>        mRules;
   bool    mWrapToWindow;
   PRInt32 mWrapColumn;
   PRInt32 mMaxTextLength;
   PRInt32 mInitTriggerCounter;
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -985,23 +985,23 @@ nsTextEditRules::DidRedo(nsISelection *a
       nodeList->GetLength(&len);
       
       if (len != 1) {
         // only in the case of one br could there be the bogus node
         mBogusNode = nsnull;
         return NS_OK;  
       }
 
-      nsCOMPtr<nsIDOMNode> node;
-      nodeList->Item(0, getter_AddRefs(node));
-      NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
-      if (mEditor->IsMozEditorBogusNode(node))
-        mBogusNode = node;
-      else
+      nsCOMPtr<nsIContent> content = nodeList->GetNodeAt(0);
+      MOZ_ASSERT(content);
+      if (mEditor->IsMozEditorBogusNode(content)) {
+        mBogusNode = do_QueryInterface(content);
+      } else {
         mBogusNode = nsnull;
+      }
     }
   }
   return res;
 }
 
 nsresult
 nsTextEditRules::WillOutputText(nsISelection *aSelection, 
                                 const nsAString  *aOutputFormat,
@@ -1109,76 +1109,73 @@ nsTextEditRules::CreateTrailingBRIfNeede
     res = CreateMozBR(body, rootLen, address_of(unused));
   }
   return res;
 }
 
 nsresult
 nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
 {
-  if (!aSelection) { return NS_ERROR_NULL_POINTER; }
-  if (!mEditor) { return NS_ERROR_NULL_POINTER; }
-  if (mBogusNode) return NS_OK;  // let's not create more than one, ok?
+  NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(mEditor, NS_ERROR_NULL_POINTER);
+
+  if (mBogusNode) {
+    // Let's not create more than one, ok?
+    return NS_OK;
+  }
 
   // tell rules system to not do any post-processing
   nsAutoRules beginRulesSniffing(mEditor, nsEditor::kOpIgnore, nsIEditor::eNone);
 
-  nsCOMPtr<nsIDOMNode> body = do_QueryInterface(mEditor->GetRoot());
-  if (!body)
-  {
-    // we don't even have a body yet, don't insert any bogus nodes at
+  nsCOMPtr<dom::Element> body = mEditor->GetRoot();
+  if (!body) {
+    // We don't even have a body yet, don't insert any bogus nodes at
     // this point.
-
     return NS_OK;
   }
 
-  // now we've got the body tag.
-  // iterate the body tag, looking for editable content
-  // if no editable content is found, insert the bogus node
-  bool needsBogusContent=true;
-  nsCOMPtr<nsIDOMNode> bodyChild;
-  nsresult res = body->GetFirstChild(getter_AddRefs(bodyChild));        
-  while ((NS_SUCCEEDED(res)) && bodyChild)
-  { 
+  // Now we've got the body element. Iterate over the body element's children,
+  // looking for editable content. If no editable content is found, insert the
+  // bogus node.
+  for (nsCOMPtr<nsIContent> bodyChild = body->GetFirstChild();
+       bodyChild;
+       bodyChild = bodyChild->GetNextSibling()) {
     if (mEditor->IsMozEditorBogusNode(bodyChild) ||
-        !mEditor->IsEditable(body) ||
-        mEditor->IsEditable(bodyChild))
-    {
-      needsBogusContent = false;
-      break;
+        !mEditor->IsEditable(body) || // XXX hoist out of the loop?
+        mEditor->IsEditable(bodyChild)) {
+      return NS_OK;
     }
-    nsCOMPtr<nsIDOMNode>temp;
-    bodyChild->GetNextSibling(getter_AddRefs(temp));
-    bodyChild = do_QueryInterface(temp);
+  }
+
+  // Skip adding the bogus node if body is read-only.
+  if (!mEditor->IsModifiableNode(body)) {
+    return NS_OK;
   }
-  // Skip adding the bogus node if body is read-only
-  if (needsBogusContent && mEditor->IsModifiableNode(body))
-  {
-    // create a br
-    nsCOMPtr<nsIContent> newContent;
-    res = mEditor->CreateHTMLContent(NS_LITERAL_STRING("br"), getter_AddRefs(newContent));
-    NS_ENSURE_SUCCESS(res, res);
-    nsCOMPtr<nsIDOMElement>brElement = do_QueryInterface(newContent);
 
-    // set mBogusNode to be the newly created <br>
-    mBogusNode = brElement;
-    NS_ENSURE_TRUE(mBogusNode, NS_ERROR_NULL_POINTER);
+  // Create a br.
+  nsCOMPtr<nsIContent> newContent;
+  nsresult rv = mEditor->CreateHTMLContent(NS_LITERAL_STRING("br"), getter_AddRefs(newContent));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // set mBogusNode to be the newly created <br>
+  mBogusNode = do_QueryInterface(newContent);
+  NS_ENSURE_TRUE(mBogusNode, NS_ERROR_NULL_POINTER);
 
-    // give it a special attribute
-    newContent->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
-                        kMOZEditorBogusNodeValue, false);
-    
-    // put the node in the document
-    res = mEditor->InsertNode(mBogusNode, body, 0);
-    NS_ENSURE_SUCCESS(res, res);
+  // Give it a special attribute.
+  newContent->SetAttr(kNameSpaceID_None, kMOZEditorBogusNodeAttrAtom,
+                      kMOZEditorBogusNodeValue, false);
 
-    // set selection
-    aSelection->Collapse(body, 0);
-  }
-  return res;
+  // Put the node in the document.
+  nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(body);
+  rv = mEditor->InsertNode(mBogusNode, bodyNode, 0);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Set selection.
+  aSelection->CollapseNative(body, 0);
+  return NS_OK;
 }
 
 
 nsresult
 nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, 
                                            const nsAString  *aInString,
                                            nsAString  *aOutString,
                                            PRInt32          aMaxLength,
--- a/embedding/android/Makefile.in
+++ b/embedding/android/Makefile.in
@@ -194,13 +194,13 @@ RES_DRAWABLE = $(addprefix res/drawable/
 $(RESOURCES): $(RES_DIRS) $(subst res/,$(srcdir)/resources/,$(RESOURCES))
 	@echo "creating $@"
 	$(NSINSTALL) $(subst res/,$(srcdir)/resources/,$@) $(dir $@)
 
 
 R.java: $(MOZ_APP_ICON) $(RES_LAYOUT) $(RES_DRAWABLE) $(RES_VALUES) res/drawable/icon.png res/drawable-hdpi/icon.png AndroidManifest.xml chrome
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
 
-gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_LAYOUT) $(RES_DRAWABLE) $(RES_VALUES) chrome FORCE
+gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_LAYOUT) $(RES_DRAWABLE) $(RES_VALUES) res/values/strings.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
 
 libs:: classes.dex
 	$(INSTALL) classes.dex $(FINAL_TARGET)
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -367,10 +367,22 @@ GetCurrentNetworkInformation(NetworkInfo
 
 void
 NotifyNetworkChange(const NetworkInformation& aInfo)
 {
   sNetworkObservers.CacheInformation(aInfo);
   sNetworkObservers.BroadcastCachedInformation();
 }
 
+void Reboot()
+{
+  AssertMainThread();
+  PROXY_IF_SANDBOXED(Reboot());
+}
+
+void PowerOff()
+{
+  AssertMainThread();
+  PROXY_IF_SANDBOXED(PowerOff());
+}
+
 } // namespace hal
 } // namespace mozilla
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -187,16 +187,26 @@ void UnregisterNetworkObserver(NetworkOb
 void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo);
 
 /**
  * Notify of a change in the network state.
  * @param aNetworkInfo The new network information.
  */
 void NotifyNetworkChange(const hal::NetworkInformation& aNetworkInfo);
 
+/**
+ * Reboot the device.
+ */
+void Reboot();
+
+/**
+ * Power off the device.
+ */
+void PowerOff();
+
 } // namespace MOZ_HAL_NAMESPACE
 } // namespace mozilla
 
 #ifdef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_HAL_NAMESPACE
 #endif
 
--- a/hal/Makefile.in
+++ b/hal/Makefile.in
@@ -67,19 +67,19 @@ CPPSRCS = \
   Hal.cpp \
   SandboxHal.cpp \
   WindowIdentifier.cpp \
   $(NULL)
 
 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += AndroidHal.cpp
 else ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
-CPPSRCS += GonkHal.cpp
+CPPSRCS += GonkHal.cpp Power.cpp
 else ifeq (Linux,$(OS_TARGET))
-CPPSRCS += LinuxHal.cpp
+CPPSRCS += LinuxHal.cpp Power.cpp
 ifdef MOZ_ENABLE_DBUS
 CPPSRCS += UPowerClient.cpp
 endif
 else ifeq (WINNT,$(OS_TARGET))
 CPPSRCS += WindowsHal.cpp WindowsBattery.cpp
 else
 CPPSRCS += FallbackHal.cpp
 endif
--- a/hal/android/AndroidHal.cpp
+++ b/hal/android/AndroidHal.cpp
@@ -168,11 +168,19 @@ GetCurrentNetworkInformation(hal::Networ
   AndroidBridge* bridge = AndroidBridge::Bridge();
   if (!bridge) {
     return;
   }
 
   bridge->GetCurrentNetworkInformation(aNetworkInfo);
 }
 
+void
+Reboot()
+{}
+
+void
+PowerOff()
+{}
+
 } // hal_impl
 } // mozilla
 
--- a/hal/fallback/FallbackHal.cpp
+++ b/hal/fallback/FallbackHal.cpp
@@ -100,10 +100,18 @@ DisableNetworkNotifications()
 
 void
 GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
   aNetworkInfo->bandwidth() = dom::network::kDefaultBandwidth;
   aNetworkInfo->canBeMetered() = dom::network::kDefaultCanBeMetered;
 }
 
+void
+Reboot()
+{}
+
+void
+PowerOff()
+{}
+
 } // hal_impl
 } // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/linux/Power.cpp
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; 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 mozilla.org code.
+ *
+ * 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):
+ *   Kan-Ru Chen <kchen@mozilla.com> (Original Author)
+ *
+ * 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
+ * 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 "Hal.h"
+
+#include <unistd.h>
+#include <sys/reboot.h>
+
+namespace mozilla {
+namespace hal_impl {
+
+void
+Reboot()
+{
+  reboot(RB_AUTOBOOT);
+}
+
+void
+PowerOff()
+{
+  reboot(RB_POWER_OFF);
+}
+
+} // hal_impl
+} // mozilla
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -81,13 +81,16 @@ parent:
       returns (NetworkInformation aNetworkInfo);
 
     sync GetScreenEnabled() returns (bool enabled);
     SetScreenEnabled(bool enabled);
 
     sync GetScreenBrightness() returns (double brightness);
     SetScreenBrightness(double brightness);
 
+    Reboot();
+    PowerOff();
+
     __delete__();
 };
 
 } // namespace hal
 } // namespace mozilla
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -147,16 +147,28 @@ GetScreenBrightness()
 }
 
 void
 SetScreenBrightness(double brightness)
 {
   Hal()->SendSetScreenBrightness(brightness);
 }
 
+void
+Reboot()
+{
+  Hal()->SendReboot();
+}
+
+void
+PowerOff()
+{
+  Hal()->SendPowerOff();
+}
+
 class HalParent : public PHalParent
                 , public BatteryObserver
                 , public NetworkObserver
 {
 public:
   NS_OVERRIDE virtual bool
   RecvVibrate(const InfallibleTArray<unsigned int>& pattern,
               const InfallibleTArray<uint64> &id,
@@ -262,16 +274,30 @@ public:
   }
 
   NS_OVERRIDE virtual bool
   RecvSetScreenBrightness(const double &brightness)
   {
     hal::SetScreenBrightness(brightness);
     return true;
   }
+
+  NS_OVERRIDE virtual bool
+  RecvReboot()
+  {
+    hal::Reboot();
+    return true;
+  }
+
+  NS_OVERRIDE virtual bool
+  RecvPowerOff()
+  {
+    hal::PowerOff();
+    return true;
+  }
 };
 
 class HalChild : public PHalChild {
 public:
   NS_OVERRIDE virtual bool
   RecvNotifyBatteryChange(const BatteryInformation& aBatteryInfo) {
     hal::NotifyBatteryChange(aBatteryInfo);
     return true;
--- a/hal/windows/WindowsHal.cpp
+++ b/hal/windows/WindowsHal.cpp
@@ -79,10 +79,18 @@ DisableNetworkNotifications()
 
 void
 GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
   aNetworkInfo->bandwidth() = dom::network::kDefaultBandwidth;
   aNetworkInfo->canBeMetered() = dom::network::kDefaultCanBeMetered;
 }
 
+void
+Reboot()
+{}
+
+void
+PowerOff()
+{}
+
 } // hal_impl
 } // mozilla
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -724,16 +724,17 @@ sys/poll.h
 sys/ppc.h
 sys/prctl.h
 sys/priv.h
 sys/procfs.h
 sys/pstat.h
 sys/ptrace.h
 sys/queue.h
 sys/quota.h
+sys/reboot.h
 sys/reg.h
 sys/regset.h
 sys/resource.h
 sys/sched.h
 sys/select.h
 sys/sem.h
 sys/sendfile.h
 sys/shm.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/Proxy-function-freeze.js
@@ -0,0 +1,115 @@
+// Once a function proxy has been frozen, its handler's traps are no longer called,
+// but its call traps are.
+
+var callTrapCalls;
+function handleCall() {
+    print('call');
+    callTrapCalls++;
+    return 'favor';
+}
+function handleConstruct() {
+    print('construct');
+    callTrapCalls++;
+    return 'compliment';
+}
+
+var descriptorForX = { configurable: true, enumerable: true, writable: true, value: 42 };
+var trapCalls;
+var handler = {
+    getOwnPropertyNames: function () {
+        print('getOwnPropertyNames');
+        trapCalls++;
+        return ['x'];
+    },
+    getPropertyNames: function() {
+        print('getPropertyNames');
+        trapCalls++;
+        return ['x'];
+    },
+    getOwnPropertyDescriptor: function(name) {
+        print('getOwnPropertyDescriptor');
+        trapCalls++;
+        assertEq(name, 'x');
+        return descriptorForX;
+    },
+    getPropertyDescriptor: function(name) {
+        print('getPropertyDescriptor');
+        trapCalls++;
+        assertEq(name, 'x');
+        return descriptorForX;
+    },
+    defineProperty: function(name, propertyDescriptor) {
+        print('defineProperty');
+        trapCalls++;
+    },
+    delete: function(name) {
+        print('delete');
+        trapCalls++;
+        return false;
+    },
+    fix: function() {
+        print('fix');
+        trapCalls++;
+        return { x: descriptorForX };
+    }
+};
+
+var fp = Proxy.createFunction(handler, handleCall, handleConstruct);
+
+trapCalls = callTrapCalls = 0;
+assertEq(Object.getOwnPropertyNames(fp)[0], 'x');
+assertEq(trapCalls > 0, true);
+assertEq(callTrapCalls, 0);
+
+trapCalls = callTrapCalls = 0;
+assertEq(Object.getOwnPropertyDescriptor(fp, 'x').value, 42);
+assertEq(trapCalls > 0, true);
+assertEq(callTrapCalls, 0);
+
+trapCalls = callTrapCalls = 0;
+assertEq(delete fp.x, false);
+assertEq(trapCalls > 0, true);
+assertEq(callTrapCalls, 0);
+
+trapCalls = callTrapCalls = 0;
+assertEq(fp(), 'favor');
+assertEq(trapCalls, 0);
+assertEq(callTrapCalls, 1);
+
+trapCalls = callTrapCalls = 0;
+assertEq(new fp, 'compliment');
+assertEq(trapCalls, 0);
+assertEq(callTrapCalls, 1);
+
+trapCalls = callTrapCalls = 0;
+Object.freeze(fp);
+assertEq(trapCalls > 0, true);
+assertEq(callTrapCalls, 0);
+
+// Once the proxy has been frozen, its traps should never be invoked any
+// more.
+trapCalls = callTrapCalls = 0;
+assertEq(Object.getOwnPropertyNames(fp)[0], 'x');
+assertEq(trapCalls, 0);
+
+trapCalls = callTrapCalls = 0;
+assertEq(Object.getOwnPropertyDescriptor(fp, 'x').value, 42);
+assertEq(trapCalls, 0);
+
+trapCalls = callTrapCalls = 0;
+assertEq(delete fp.x, false);
+assertEq(trapCalls, 0);
+
+trapCalls = callTrapCalls = 0;
+assertEq(fp(), 'favor');
+assertEq(trapCalls, 0);
+assertEq(callTrapCalls, 1);
+
+trapCalls = callTrapCalls = 0;
+assertEq(new fp, 'compliment');
+assertEq(trapCalls, 0);
+assertEq(callTrapCalls, 1);
+
+trapCalls = callTrapCalls = 0;
+Object.freeze(fp);
+assertEq(trapCalls, 0);
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -381,22 +381,32 @@ JS_STATIC_ASSERT(offsetof(JSClass, hasIn
 JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
 JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
 
 static JS_ALWAYS_INLINE JSClass *
 Jsvalify(Class *c)
 {
     return (JSClass *)c;
 }
+static JS_ALWAYS_INLINE const JSClass *
+Jsvalify(const Class *c)
+{
+    return (const JSClass *)c;
+}
 
 static JS_ALWAYS_INLINE Class *
 Valueify(JSClass *c)
 {
     return (Class *)c;
 }
+static JS_ALWAYS_INLINE const Class *
+Valueify(const JSClass *c)
+{
+    return (const Class *)c;
+}
 
 /*
  * Enumeration describing possible values of the [[Class]] internal property
  * value of objects.
  */
 enum ESClassValue { ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean };
 
 /*
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -339,41 +339,21 @@ js::BoxNonStrictThis(JSContext *cx, cons
     return true;
 }
 
 #if JS_HAS_NO_SUCH_METHOD
 
 const uint32_t JSSLOT_FOUND_FUNCTION  = 0;
 const uint32_t JSSLOT_SAVED_ID        = 1;
 
-static void
-no_such_method_trace(JSTracer *trc, JSObject *obj)
-{
-    gc::MarkValue(trc, obj->getSlotRef(JSSLOT_FOUND_FUNCTION), "found function");
-    gc::MarkValue(trc, obj->getSlotRef(JSSLOT_SAVED_ID), "saved id");
-}
-
 Class js_NoSuchMethodClass = {
     "NoSuchMethod",
     JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
-    JS_PropertyStub,         /* addProperty */
-    JS_PropertyStub,         /* delProperty */
-    JS_PropertyStub,         /* getProperty */
-    JS_StrictPropertyStub,   /* setProperty */
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    NULL,                    /* finalize */
-    NULL,                    /* reserved0 */
-    NULL,                    /* checkAccess */
-    NULL,                    /* call */
-    NULL,                    /* construct */
-    NULL,                    /* XDR */
-    NULL,                    /* hasInstance */
-    no_such_method_trace     /* trace */
+    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,
 };
 
 /*
  * When JSOP_CALLPROP or JSOP_CALLELEM does not find the method property of
  * the base object, we search for the __noSuchMethod__ method in the base.
  * If it exists, we store the method and the property's id into an object of
  * NoSuchMethod class and store this object into the callee's stack slot.
  * Later, Invoke will recognise such an object and transfer control to
@@ -2844,16 +2824,22 @@ BEGIN_CASE(JSOP_FUNAPPLY)
         DO_NEXT_OP(len);
     }
 
     TypeMonitorCall(cx, args, construct);
 
     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
 
     JSScript *newScript = fun->script();
+
+    if (newScript->compileAndGo && newScript->hasClearedGlobal()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CLEARED_SCOPE);
+        goto error;
+    }
+
     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, newScript, initial))
         goto error;
 
     RESTORE_INTERP_VARS();
 
     if (!regs.fp()->functionPrologue(cx))
         goto error;
 
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1455,17 +1455,17 @@ JS_FRIEND_DATA(Class) js::FunctionProxyC
         proxy_SetPropertyAttributes,
         proxy_SetElementAttributes,
         proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         proxy_TypeOf,
-        NULL,                /* fix             */
+        proxy_Fix,           /* fix             */
         NULL,                /* thisObject      */
         NULL,                /* clear           */
     }
 };
 
 JS_FRIEND_API(JSObject *)
 js::NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv, JSObject *proto,
                    JSObject *parent, JSObject *call, JSObject *construct)
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -50,16 +50,20 @@
 #include "builtin/RegExp.h"
 #include "frontend/BytecodeEmitter.h"
 #include "vm/GlobalObject-inl.h"
 
 #include "jsobjinlines.h"
 #include "vm/RegExpObject-inl.h"