Bug 1517368 - Expose PopupBlocker status via ChromeUtils, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 04 Jan 2019 16:16:59 +0100
changeset 509694 9dfb6ebdf897d8bab0ddefb460ece64786cbe8f6
parent 509693 ebee49cf02703325eaec9f769c60bd74bc6894ae
child 509695 e6f6dc496d61e33853d5aa71713f7b2a7416f96f
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1517368
milestone66.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 1517368 - Expose PopupBlocker status via ChromeUtils, r=smaug
dom/base/ChromeUtils.cpp
dom/base/ChromeUtils.h
dom/base/PopupBlocker.cpp
dom/base/PopupBlocker.h
dom/chrome-webidl/ChromeUtils.webidl
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -765,10 +765,39 @@ constexpr auto kSkipSelfHosted = JS::Sav
     aRv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   return ReportingHeader::HasReportingHeaderForOrigin(
       NS_ConvertUTF16toUTF8(aOrigin));
 }
 
+/* static */ PopupBlockerState ChromeUtils::GetPopupControlState(
+    GlobalObject& aGlobal) {
+  switch (PopupBlocker::GetPopupControlState()) {
+    case PopupBlocker::PopupControlState::openAllowed:
+      return PopupBlockerState::OpenAllowed;
+
+    case PopupBlocker::PopupControlState::openControlled:
+      return PopupBlockerState::OpenControlled;
+
+    case PopupBlocker::PopupControlState::openBlocked:
+      return PopupBlockerState::OpenBlocked;
+
+    case PopupBlocker::PopupControlState::openAbused:
+      return PopupBlockerState::OpenAbused;
+
+    case PopupBlocker::PopupControlState::openOverridden:
+      return PopupBlockerState::OpenOverridden;
+
+    default:
+      MOZ_CRASH(
+          "PopupBlocker::PopupControlState and PopupBlockerState are out of "
+          "sync");
+  }
+}
+
+/* static */ bool ChromeUtils::IsPopupTokenUnused(GlobalObject& aGlobal) {
+  return PopupBlocker::IsPopupOpeningTokenUnused();
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -167,14 +167,18 @@ class ChromeUtils {
 
   static void GetRootBrowsingContexts(
       GlobalObject& aGlobal,
       nsTArray<RefPtr<BrowsingContext>>& aBrowsingContexts);
 
   static bool HasReportingHeaderForOrigin(GlobalObject& global,
                                           const nsAString& aOrigin,
                                           ErrorResult& aRv);
+
+  static PopupBlockerState GetPopupControlState(GlobalObject& aGlobal);
+
+  static bool IsPopupTokenUnused(GlobalObject& aGlobal);
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_ChromeUtils__
--- a/dom/base/PopupBlocker.cpp
+++ b/dom/base/PopupBlocker.cpp
@@ -136,16 +136,20 @@ PopupBlocker::GetPopupControlState() {
   if (!sUnusedPopupToken) {
     sUnusedPopupToken = true;
     return true;
   }
 
   return false;
 }
 
+/* static */ bool PopupBlocker::IsPopupOpeningTokenUnused() {
+  return sUnusedPopupToken;
+}
+
 /* static */ void PopupBlocker::PopupStatePusherCreated() {
   ++sPopupStatePusherCount;
 }
 
 /* static */ void PopupBlocker::PopupStatePusherDestroyed() {
   MOZ_ASSERT(sPopupStatePusherCount);
 
   if (!--sPopupStatePusherCount) {
--- a/dom/base/PopupBlocker.h
+++ b/dom/base/PopupBlocker.h
@@ -15,16 +15,17 @@ namespace mozilla {
 namespace dom {
 
 class PopupBlocker final {
  public:
   // Popup control state enum. The values in this enum must go from most
   // permissive to least permissive so that it's safe to push state in
   // all situations. Pushing popup state onto the stack never makes the
   // current popup state less permissive.
+  // Keep this in sync with PopupBlockerState webidl dictionary!
   enum PopupControlState {
     openAllowed = 0,  // open that window without worries
     openControlled,   // it's a popup, but allow it
     openBlocked,      // it's a popup, but not from an allowed event
     openAbused,       // it's a popup. disallow it, but allow domain override.
     openOverridden    // disallow window open
   };
 
@@ -42,16 +43,18 @@ class PopupBlocker final {
   // permissions. In this case, the caller should not block popups.
   static bool CanShowPopupByPermission(nsIPrincipal* aPrincipal);
 
   // This method returns true if the caller is allowed to show a popup, and it
   // consumes the popup token for the current event. There is just 1 popup
   // allowed per event.
   static bool TryUsePopupOpeningToken();
 
+  static bool IsPopupOpeningTokenUnused();
+
   static PopupBlocker::PopupControlState GetEventPopupControlState(
       WidgetEvent* aEvent, Event* aDOMEvent = nullptr);
 
   static void Initialize();
   static void Shutdown();
 };
 
 }  // namespace dom
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -374,16 +374,22 @@ partial namespace ChromeUtils {
   /**
    * Returns all the root BrowsingContexts.
    */
   [ChromeOnly]
   sequence<BrowsingContext> getRootBrowsingContexts();
 
   [ChromeOnly, Throws]
   boolean hasReportingHeaderForOrigin(DOMString aOrigin);
+
+  [ChromeOnly]
+  PopupBlockerState getPopupControlState();
+
+  [ChromeOnly]
+  boolean isPopupTokenUnused();
 };
 
 /**
  * Dictionaries duplicating IPDL types in dom/ipc/DOMTypes.ipdlh
  * Used by requestPerformanceMetrics
  */
 
 dictionary MediaMemoryInfoDictionary {
@@ -532,8 +538,17 @@ enum Base64URLDecodePadding {
    */
   "reject"
 };
 
 dictionary Base64URLDecodeOptions {
   /** Specifies the padding mode for decoding the input. */
   required Base64URLDecodePadding padding;
 };
+
+// Keep this in sync with PopupBlocker::PopupControlState!
+enum PopupBlockerState {
+  "openAllowed",
+  "openControlled",
+  "openBlocked",
+  "openAbused",
+  "openOverridden",
+};