Commit b1c77248 authored by Kagami Sascha Rosylight's avatar Kagami Sascha Rosylight
Browse files

Bug 1862244 - Add GlobalTeardownHelper. r=smaug, a=RyanVM

parent 1f892c76
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2610,7 +2610,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document)
    if (mql->HasListeners() &&
        NS_SUCCEEDED(mql->CheckCurrentGlobalCorrectness())) {
      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
      cb.NoteXPCOMChild(mql);
      cb.NoteXPCOMChild(static_cast<EventTarget*>(mql));
    }
  }
+73 −0
Original line number Diff line number Diff line
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "GlobalTeardownObserver.h"
#include "mozilla/Sprintf.h"
#include "mozilla/dom/Document.h"

namespace mozilla {

GlobalTeardownObserver::GlobalTeardownObserver() = default;
GlobalTeardownObserver::GlobalTeardownObserver(nsIGlobalObject* aGlobalObject,
                                               bool aHasOrHasHadOwnerWindow)
    : mHasOrHasHadOwnerWindow(aHasOrHasHadOwnerWindow) {
  BindToOwner(aGlobalObject);
}

GlobalTeardownObserver::~GlobalTeardownObserver() {
  if (mParentObject) {
    mParentObject->RemoveGlobalTeardownObserver(this);
  }
}

void GlobalTeardownObserver::BindToOwner(nsIGlobalObject* aOwner) {
  MOZ_ASSERT(!mParentObject);

  if (aOwner) {
    mParentObject = aOwner;
    aOwner->AddGlobalTeardownObserver(this);
    // Let's cache the result of this QI for fast access and off main thread
    // usage
    mOwnerWindow =
        nsCOMPtr<nsPIDOMWindowInner>(do_QueryInterface(aOwner)).get();
    if (mOwnerWindow) {
      mHasOrHasHadOwnerWindow = true;
    }
  }
}

void GlobalTeardownObserver::DisconnectFromOwner() {
  if (mParentObject) {
    mParentObject->RemoveGlobalTeardownObserver(this);
  }
  mOwnerWindow = nullptr;
  mParentObject = nullptr;
}

nsresult GlobalTeardownObserver::CheckCurrentGlobalCorrectness() const {
  NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);

  // Main-thread.
  if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
    return NS_ERROR_FAILURE;
  }

  if (NS_IsMainThread()) {
    return NS_OK;
  }

  if (!mParentObject) {
    return NS_ERROR_FAILURE;
  }

  if (mParentObject->IsDying()) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}

};  // namespace mozilla
+87 −0
Original line number Diff line number Diff line
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef DOM_BASE_GLOBALTEARDOWNOBSERVER_H_
#define DOM_BASE_GLOBALTEARDOWNOBSERVER_H_

#include "mozilla/Attributes.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/RefPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsID.h"
#include "nsIGlobalObject.h"
#include "nsIScriptGlobalObject.h"
#include "nsISupports.h"
#include "nsISupportsUtils.h"
#include "nsPIDOMWindow.h"

#define NS_GLOBALTEARDOWNOBSERVER_IID                \
  {                                                  \
    0xc31fddb9, 0xec49, 0x4f24, {                    \
      0x90, 0x16, 0xb5, 0x2b, 0x26, 0x6c, 0xb6, 0x29 \
    }                                                \
  }

namespace mozilla {

class GlobalTeardownObserver
    : public nsISupports,
      public LinkedListElement<GlobalTeardownObserver> {
 public:
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_GLOBALTEARDOWNOBSERVER_IID)

  GlobalTeardownObserver();
  explicit GlobalTeardownObserver(nsIGlobalObject* aGlobalObject,
                                  bool aHasOrHasHadOwnerWindow = false);

  nsPIDOMWindowInner* GetOwner() const { return mOwnerWindow; }
  nsIGlobalObject* GetOwnerGlobal() const { return mParentObject; }
  bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }

  void GetParentObject(nsIScriptGlobalObject** aParentObject) {
    if (mParentObject) {
      CallQueryInterface(mParentObject, aParentObject);
    } else {
      *aParentObject = nullptr;
    }
  }

  virtual void DisconnectFromOwner();

  // A global permanently becomes invalid when DisconnectEventTargetObjects() is
  // called.  Normally this means:
  // - For the main thread, when nsGlobalWindowInner::FreeInnerObjects is
  //   called.
  // - For a worker thread, when clearing the main event queue.  (Which we do
  //   slightly later than when the spec notionally calls for it to be done.)
  //
  // A global may also become temporarily invalid when:
  // - For the main thread, if the window is no longer the WindowProxy's current
  //   inner window due to being placed in the bfcache.
  nsresult CheckCurrentGlobalCorrectness() const;

 protected:
  virtual ~GlobalTeardownObserver();

  void BindToOwner(nsIGlobalObject* aOwner);

 private:
  // The parent global object.  The global will clear this when
  // it is destroyed by calling DisconnectFromOwner().
  nsIGlobalObject* MOZ_NON_OWNING_REF mParentObject = nullptr;
  // mParentObject pre QI-ed and cached (inner window)
  // (it is needed for off main thread access)
  // It is obtained in BindToOwner and reset in DisconnectFromOwner.
  nsPIDOMWindowInner* MOZ_NON_OWNING_REF mOwnerWindow = nullptr;
  bool mHasOrHasHadOwnerWindow = false;
};

NS_DEFINE_STATIC_IID_ACCESSOR(GlobalTeardownObserver,
                              NS_GLOBALTEARDOWNOBSERVER_IID)

}  // namespace mozilla

#endif
+1 −1
Original line number Diff line number Diff line
@@ -154,7 +154,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(InProcessBrowserChildMessageManager)
  NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
  NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
  NS_INTERFACE_MAP_ENTRY(ContentFrameMessageManager)
  NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentFrameMessageManager)
  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)

+8 −4
Original line number Diff line number Diff line
@@ -219,13 +219,15 @@ void VisualViewport::FireResizeEvent() {
  VVP_LOG("%p, FireResizeEvent, fire mozvisualresize\n", this);
  WidgetEvent mozEvent(true, eMozVisualResize);
  mozEvent.mFlags.mOnlySystemGroupDispatch = true;
  EventDispatcher::Dispatch(this, presContext, &mozEvent);
  EventDispatcher::Dispatch(static_cast<EventTarget*>(this), presContext,
                            &mozEvent);

  VVP_LOG("%p, FireResizeEvent, fire VisualViewport resize\n", this);
  WidgetEvent event(true, eResize);
  event.mFlags.mBubbles = false;
  event.mFlags.mCancelable = false;
  EventDispatcher::Dispatch(this, presContext, &event);
  EventDispatcher::Dispatch(static_cast<EventTarget*>(this), presContext,
                            &event);
}

/* ================= Scroll event handling ================= */
@@ -302,7 +304,8 @@ void VisualViewport::FireScrollEvent() {
      VVP_LOG("%p: FireScrollEvent, fire mozvisualscroll\n", this);
      WidgetEvent mozEvent(true, eMozVisualScroll);
      mozEvent.mFlags.mOnlySystemGroupDispatch = true;
      EventDispatcher::Dispatch(this, presContext, &mozEvent);
      EventDispatcher::Dispatch(static_cast<EventTarget*>(this), presContext,
                                &mozEvent);
    }

    // Check whether the relative visual viewport offset actually changed -
@@ -321,7 +324,8 @@ void VisualViewport::FireScrollEvent() {
      WidgetGUIEvent event(true, eScroll, nullptr);
      event.mFlags.mBubbles = false;
      event.mFlags.mCancelable = false;
      EventDispatcher::Dispatch(this, presContext, &event);
      EventDispatcher::Dispatch(static_cast<EventTarget*>(this), presContext,
                                &event);
    }
  }
}
Loading