tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PopupQueue.cpp (2692B)


      1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
      2 /* vim: set sw=2 ts=8 et tw=80 : */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "PopupQueue.h"
      8 
      9 #include "mozilla/StaticPtr.h"
     10 #include "mozilla/dom/Element.h"
     11 #include "nsThreadUtils.h"
     12 
     13 using namespace mozilla;
     14 
     15 void PopupQueue::Enqueue(Element* aPopup,
     16                         MoveOnlyFunction<void(Element*)>&& aCallback) {
     17  if (!aCallback) {
     18    return;
     19  }
     20 
     21  if (Store(aPopup, false, std::move(aCallback)) && !mShowing) {
     22    MaybeShowNext();
     23  }
     24 }
     25 
     26 void PopupQueue::Show(Element* aPopup,
     27                      MoveOnlyFunction<void(Element*)>&& aCallback) {
     28  if (!aCallback) {
     29    return;
     30  }
     31 
     32  MoveOnlyFunction<void(Element*)> callback = std::move(aCallback);
     33 
     34  if (Store(aPopup, true, nullptr)) {
     35    ++mShowing;
     36    callback(aPopup);
     37  }
     38 }
     39 
     40 bool PopupQueue::Store(Element* aPopup, bool aShown,
     41                       MoveOnlyFunction<void(Element*)>&& aCallback) {
     42  // Let's avoid the same popup shown multiple time, if it's already on screen.
     43  if (!aShown) {
     44    for (const PendingPopup& popup : mQueue) {
     45      if (popup.mPopup == aPopup) {
     46        return false;
     47      }
     48    }
     49  }
     50 
     51  mQueue.AppendElement(PendingPopup{aPopup,
     52                                    /* if not shown, it's qeueable */ !aShown,
     53                                    aShown, std::move(aCallback)});
     54  return true;
     55 }
     56 
     57 void PopupQueue::NotifyDismissed(Element* aPopup, bool aRemoveAll) {
     58  if (mQueue.IsEmpty()) {
     59    return;
     60  }
     61 
     62  for (uint32_t i = 0; i < mQueue.Length();) {
     63    if (mQueue[i].mPopup == aPopup) {
     64      if (mShowing && mQueue[i].mShown) {
     65        --mShowing;
     66      }
     67 
     68      mQueue.RemoveElementAt(i);
     69 
     70      if (!aRemoveAll) {
     71        break;
     72      }
     73 
     74      continue;
     75    }
     76 
     77    ++i;
     78  }
     79 
     80  if (!mQueue.IsEmpty() && !mShowing) {
     81    NS_DispatchToMainThread(NewRunnableMethod("PopupQueue::MaybeShowNext", this,
     82                                              &PopupQueue::MaybeShowNext));
     83  }
     84 }
     85 
     86 void PopupQueue::MaybeShowNext() {
     87  if (mQueue.IsEmpty() || mShowing) {
     88    return;
     89  }
     90 
     91  PendingPopup& popup = mQueue[0];
     92 
     93  ++mShowing;
     94  MOZ_ASSERT(!popup.mShown);
     95  popup.mShown = true;
     96 
     97  MoveOnlyFunction<void(Element*)> callback = std::move(popup.mCallback);
     98  MOZ_ASSERT(!popup.mCallback);
     99 
    100  callback(mQueue[0].mPopup);
    101 }
    102 
    103 PopupQueue::Element* PopupQueue::RetrieveQueueableShownPopup() const {
    104  for (auto& popup : mQueue) {
    105    if (popup.mQueueable && popup.mShown) {
    106      return popup.mPopup;
    107    }
    108  }
    109 
    110  return nullptr;
    111 }