Bug 1127189 part 2 - Initialize browser API directly to get rid of nsBrowserElement observers. r=kanru
authorTing-Yu Chou <janus926@gmail.com>
Mon, 09 Feb 2015 15:04:18 +0800
changeset 255707 7e57011701b9127563ad71d427a70555cd0e6d74
parent 255706 20f6c0ee944d287300eae04e2d32ab167d1a4668
child 255708 179a122ae672c40638791c1bd751c9ffa4659ca7
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru
bugs1127189
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1127189 part 2 - Initialize browser API directly to get rid of nsBrowserElement observers. r=kanru
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
dom/html/nsBrowserElement.cpp
dom/html/nsBrowserElement.h
dom/html/nsGenericHTMLFrameElement.cpp
dom/interfaces/html/nsIMozBrowserFrame.idl
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -164,24 +164,22 @@ nsFrameLoader::nsFrameLoader(Element* aO
   , mInSwap(false)
   , mInShow(false)
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
   , mRemoteBrowserShown(false)
   , mRemoteFrame(false)
   , mClipSubdocument(true)
   , mClampScrollPosition(true)
-  , mRemoteBrowserInitialized(false)
   , mObservingOwnerContent(false)
   , mVisible(true)
   , mCurrentRemoteFrame(nullptr)
   , mRemoteBrowser(nullptr)
   , mChildID(0)
   , mEventMode(EVENT_MODE_NORMAL_DISPATCH)
-  , mPendingFrameSent(false)
 {
   ResetPermissionManagerStatus();
 }
 
 nsFrameLoader::~nsFrameLoader()
 {
   mNeedsAsyncDestroy = true;
   if (mMessageManager) {
@@ -358,25 +356,16 @@ nsFrameLoader::ReallyStartLoadingInterna
 
   nsresult rv = MaybeCreateDocShell();
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (mRemoteFrame) {
     if (!mRemoteBrowser) {
-      if (!mPendingFrameSent) {
-        nsCOMPtr<nsIObserverService> os = services::GetObserverService();
-        if (os && !mRemoteBrowserInitialized) {
-          os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
-                              "remote-browser-pending", nullptr);
-          mPendingFrameSent = true;
-        }
-      }
-
       TryRemoteBrowser();
 
       if (!mRemoteBrowser) {
         NS_WARNING("Couldn't create child process for iframe.");
         return NS_ERROR_FAILURE;
       }
     }
 
@@ -908,26 +897,21 @@ nsFrameLoader::ShowRemoteFrame(const nsI
         parentIsActive = topWin && topWin->IsActive();
       }
     }
     mRemoteBrowser->Show(size, parentIsActive);
     mRemoteBrowserShown = true;
 
     EnsureMessageManager();
 
+    InitializeBrowserAPI();
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
-    if (os && !mRemoteBrowserInitialized) {
-      if (!mPendingFrameSent) {
-        os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
-                            "remote-browser-pending", nullptr);
-        mPendingFrameSent = true;
-      }
+    if (os) {
       os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
                           "remote-browser-shown", nullptr);
-      mRemoteBrowserInitialized = true;
     }
   } else {
     nsIntRect dimensions;
     NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
 
     // Don't show remote iframe if we are waiting for the completion of reflow.
     if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
       nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
@@ -1780,16 +1764,17 @@ nsFrameLoader::MaybeCreateDocShell()
     uint32_t containingAppId = nsIScriptSecurityManager::NO_APP_ID;
     if (containingApp) {
       NS_ENSURE_SUCCESS(containingApp->GetLocalId(&containingAppId),
                         NS_ERROR_FAILURE);
     }
     mDocShell->SetIsBrowserInsideApp(containingAppId);
   }
 
+  InitializeBrowserAPI();
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
     os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
                         "inprocess-browser-shown", nullptr);
   }
 
   if (OwnerIsBrowserOrAppFrame() && mMessageManager) {
     mMessageManager->LoadFrameScript(
@@ -2743,8 +2728,17 @@ nsFrameLoader::GetLoadContext(nsILoadCon
   } else {
     nsCOMPtr<nsIDocShell> docShell;
     GetDocShell(getter_AddRefs(docShell));
     loadContext = do_GetInterface(docShell);
   }
   loadContext.forget(aLoadContext);
   return NS_OK;
 }
+
+void
+nsFrameLoader::InitializeBrowserAPI()
+{
+  nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
+  if (browserFrame) {
+    browserFrame->InitializeBrowserAPI();
+  }
+}
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -307,16 +307,18 @@ private:
   nsIAtom* TypeAttrName() const {
     return mOwnerContent->IsXUL() ? nsGkAtoms::type : nsGkAtoms::mozframetype;
   }
 
   // Update the permission manager's app-id refcount based on mOwnerContent's
   // own-or-containing-app.
   void ResetPermissionManagerStatus();
 
+  void InitializeBrowserAPI();
+
   nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURIToLoad;
   mozilla::dom::Element* mOwnerContent; // WEAK
 
   // Note: this variable must be modified only by ResetPermissionManagerStatus()
   uint32_t mAppIdSentToPermissionManager;
 
 public:
@@ -346,17 +348,16 @@ private:
   // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
   // it may lose the flag.
   bool mNetworkCreated : 1;
 
   bool mRemoteBrowserShown : 1;
   bool mRemoteFrame : 1;
   bool mClipSubdocument : 1;
   bool mClampScrollPosition : 1;
-  bool mRemoteBrowserInitialized : 1;
   bool mObservingOwnerContent : 1;
 
   // Backs nsIFrameLoader::{Get,Set}Visible.  Visibility state here relates to
   // whether this frameloader's <iframe mozbrowser> is setVisible(true)'ed, and
   // doesn't necessarily correlate with docshell/document visibility.
   bool mVisible : 1;
 
   // The ContentParent associated with mRemoteBrowser.  This was added as a
@@ -364,14 +365,11 @@ private:
   nsRefPtr<mozilla::dom::nsIContentParent> mContentParent;
   RenderFrameParent* mCurrentRemoteFrame;
   TabParent* mRemoteBrowser;
   uint64_t mChildID;
 
   // See nsIFrameLoader.idl. EVENT_MODE_NORMAL_DISPATCH automatically
   // forwards some input events to out-of-process content.
   uint32_t mEventMode;
-
-  // Indicate if we have sent 'remote-browser-pending'.
-  bool mPendingFrameSent;
 };
 
 #endif
--- a/dom/html/nsBrowserElement.cpp
+++ b/dom/html/nsBrowserElement.cpp
@@ -14,101 +14,22 @@
 #include "mozilla/dom/ToJSValue.h"
 
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsFrameLoader.h"
 #include "nsIDOMDOMRequest.h"
 #include "nsIDOMElement.h"
 #include "nsINode.h"
-#include "nsIObserver.h"
-#include "nsIObserverService.h"
 #include "nsIPrincipal.h"
-#include "nsWeakReference.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
-static const char kRemoteBrowserPending[] = "remote-browser-pending";
-static const char kInprocessBrowserShown[] = "inprocess-browser-shown";
-
-class nsBrowserElement::BrowserShownObserver : public nsIObserver
-                                             , public nsSupportsWeakReference
-{
-public:
-  explicit BrowserShownObserver(nsBrowserElement* aBrowserElement);
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
-  void AddObserver();
-  void RemoveObserver();
-private:
-  virtual ~BrowserShownObserver();
-
-  // Weak reference to the browser element. nsBrowserElement has a
-  // reference to us. nsBrowserElement's destructor is responsible to
-  // null out this weak reference via RemoveObserver()
-  nsBrowserElement* mBrowserElement;
-};
-
-NS_IMPL_ISUPPORTS(nsBrowserElement::BrowserShownObserver, nsIObserver, nsISupportsWeakReference)
-
-nsBrowserElement::BrowserShownObserver::BrowserShownObserver(nsBrowserElement* aBrowserElement)
-  : mBrowserElement(aBrowserElement)
-{
-}
-
-nsBrowserElement::BrowserShownObserver::~BrowserShownObserver()
-{
-  RemoveObserver();
-}
-
-NS_IMETHODIMP
-nsBrowserElement::BrowserShownObserver::Observe(nsISupports* aSubject,
-                                                const char* aTopic,
-                                                const char16_t* aData)
-{
-  NS_ENSURE_TRUE(mBrowserElement, NS_OK);
-
-  if (!strcmp(aTopic, kRemoteBrowserPending) ||
-      !strcmp(aTopic, kInprocessBrowserShown)) {
-    nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(aSubject);
-    nsCOMPtr<nsIFrameLoader> myFrameLoader = mBrowserElement->GetFrameLoader();
-    // The browser element API needs the frameloader to
-    // initialize. We still use the observer to get notified when the
-    // frameloader is created. So we check if the frameloader created
-    // is ours, then initialize the browser element API.
-    if (frameLoader && frameLoader == myFrameLoader) {
-      mBrowserElement->InitBrowserElementAPI();
-    }
-  }
-  return NS_OK;
-}
-
-void
-nsBrowserElement::BrowserShownObserver::AddObserver()
-{
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (obs) {
-    obs->AddObserver(this, kRemoteBrowserPending, true);
-    obs->AddObserver(this, kInprocessBrowserShown, true);
-  }
-}
-
-void
-nsBrowserElement::BrowserShownObserver::RemoveObserver()
-{
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (obs) {
-    obs->RemoveObserver(this, kRemoteBrowserPending);
-    obs->RemoveObserver(this, kInprocessBrowserShown);
-  }
-  mBrowserElement = nullptr;
-}
-
 bool
 nsBrowserElement::IsBrowserElementOrThrow(ErrorResult& aRv)
 {
   if (mBrowserElementAPI) {
     return true;
   }
   aRv.Throw(NS_ERROR_DOM_INVALID_NODE_TYPE_ERR);
   return false;
@@ -140,28 +61,16 @@ nsBrowserElement::InitBrowserElementAPI(
   }
 
   mBrowserElementAPI = do_CreateInstance("@mozilla.org/dom/browser-element-api;1");
   if (mBrowserElementAPI) {
     mBrowserElementAPI->SetFrameLoader(frameLoader);
   }
 }
 
-nsBrowserElement::nsBrowserElement()
-  : mOwnerIsWidget(false)
-{
-  mObserver = new BrowserShownObserver(this);
-  mObserver->AddObserver();
-}
-
-nsBrowserElement::~nsBrowserElement()
-{
-  mObserver->RemoveObserver();
-}
-
 void
 nsBrowserElement::SetVisible(bool aVisible, ErrorResult& aRv)
 {
   NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
 
   nsresult rv = mBrowserElementAPI->SetVisible(aVisible);
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/html/nsBrowserElement.h
+++ b/dom/html/nsBrowserElement.h
@@ -8,17 +8,16 @@
 #define nsBrowserElement_h
 
 #include "mozilla/dom/BindingDeclarations.h"
 
 #include "nsCOMPtr.h"
 #include "nsIBrowserElementAPI.h"
 
 class nsFrameLoader;
-class nsIObserver;
 
 namespace mozilla {
 
 namespace dom {
 struct BrowserElementDownloadOptions;
 class BrowserElementNextPaintEventCallback;
 class DOMRequest;
 } // namespace dom
@@ -26,18 +25,18 @@ class DOMRequest;
 class ErrorResult;
 
 /**
  * A helper class for browser-element frames
  */
 class nsBrowserElement
 {
 public:
-  nsBrowserElement();
-  virtual ~nsBrowserElement();
+  nsBrowserElement() : mOwnerIsWidget(false) {}
+  virtual ~nsBrowserElement() {}
 
   void SetVisible(bool aVisible, ErrorResult& aRv);
   already_AddRefed<dom::DOMRequest> GetVisible(ErrorResult& aRv);
   void SetActive(bool aActive, ErrorResult& aRv);
   bool GetActive(ErrorResult& aRv);
 
   void SendMouseEvent(const nsAString& aType,
                       uint32_t aX,
@@ -89,24 +88,20 @@ public:
   already_AddRefed<dom::DOMRequest> SetInputMethodActive(bool isActive,
                                                          ErrorResult& aRv);
 
   void SetNFCFocus(bool isFocus,
                    ErrorResult& aRv);
 
 protected:
   NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() = 0;
+  void InitBrowserElementAPI();
   nsCOMPtr<nsIBrowserElementAPI> mBrowserElementAPI;
 
 private:
-  void InitBrowserElementAPI();
   bool IsBrowserElementOrThrow(ErrorResult& aRv);
   bool IsNotWidgetOrThrow(ErrorResult& aRv);
   bool mOwnerIsWidget;
-
-  class BrowserShownObserver;
-  friend class BrowserShownObserver;
-  nsRefPtr<BrowserShownObserver> mObserver;
 };
 
 } // namespace mozilla
 
 #endif // nsBrowserElement_h
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -494,8 +494,16 @@ nsGenericHTMLFrameElement::DisallowCreat
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::AllowCreateFrameLoader()
 {
   MOZ_ASSERT(!mFrameLoader);
   MOZ_ASSERT(mFrameLoaderCreationDisallowed);
   mFrameLoaderCreationDisallowed = false;
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::InitializeBrowserAPI()
+{
+  MOZ_ASSERT(mFrameLoader);
+  InitBrowserElementAPI();
+  return NS_OK;
+}
--- a/dom/interfaces/html/nsIMozBrowserFrame.idl
+++ b/dom/interfaces/html/nsIMozBrowserFrame.idl
@@ -80,9 +80,15 @@ interface nsIMozBrowserFrame : nsIDOMMoz
 
   /**
    * Create a remote (i.e., out-of-process) frame loader attached to the given
    * tab parent.
    *
    * It is an error to call this method if we already have a frame loader.
    */
   void createRemoteFrameLoader(in nsITabParent aTabParent);
+
+  /**
+   * Initialize the API, and add frame message listener to listen to API
+   * invocations.
+   */
+  [noscript] void initializeBrowserAPI();
 };