tor-browser

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

CloseWatcher.cpp (4983B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 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 "CloseWatcher.h"
      8 
      9 #include "mozilla/RefPtr.h"
     10 #include "mozilla/dom/CloseWatcherBinding.h"
     11 #include "mozilla/dom/CloseWatcherManager.h"
     12 #include "mozilla/dom/Event.h"
     13 #include "mozilla/dom/EventBinding.h"
     14 #include "mozilla/dom/ToJSValue.h"
     15 #include "mozilla/dom/WindowContext.h"
     16 #include "nsGlobalWindowInner.h"
     17 
     18 namespace mozilla::dom {
     19 
     20 NS_IMPL_ISUPPORTS_INHERITED0(CloseWatcher, DOMEventTargetHelper)
     21 
     22 already_AddRefed<CloseWatcher> CloseWatcher::Constructor(
     23    const GlobalObject& aGlobal, const CloseWatcherOptions& aOptions,
     24    ErrorResult& aRv) {
     25  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
     26  RefPtr<nsPIDOMWindowInner> window = global->GetAsInnerWindow();
     27  if (!window || !window->IsFullyActive()) {
     28    aRv.ThrowInvalidStateError("The document is not fully active.");
     29    return nullptr;
     30  }
     31 
     32  RefPtr<CloseWatcher> watcher = new CloseWatcher(window);
     33 
     34  AbortSignal* signal = nullptr;
     35  if (aOptions.mSignal.WasPassed()) {
     36    signal = &aOptions.mSignal.Value();
     37  }
     38  if (signal && signal->Aborted()) {
     39    return watcher.forget();
     40  }
     41  if (signal) {
     42    watcher->Follow(signal);
     43  }
     44 
     45  watcher->AddToWindowsCloseWatcherManager();
     46  return watcher.forget();
     47 }
     48 
     49 JSObject* CloseWatcher::WrapObject(JSContext* aCx,
     50                                   JS::Handle<JSObject*> aGivenProto) {
     51  return CloseWatcher_Binding::Wrap(aCx, this, aGivenProto);
     52 }
     53 
     54 // https://html.spec.whatwg.org/multipage/interaction.html#close-watcher-request-close
     55 bool CloseWatcher::RequestToClose(bool aRequireHistoryActionActivation) {
     56  // 1. If closeWatcher is not active, then return true.
     57  // 2. If the result of running closeWatcher's get enabled state is false, then
     58  // return true.
     59  // 3. If closeWatcher's is running cancel action is true, then return true.
     60  // 4. Let window be closeWatcher's window.
     61  // 5. If window's associated Document is not fully active, then return true.
     62  if (!IsActive() || mIsRunningCancelAction) {
     63    return true;
     64  }
     65  MOZ_ASSERT(GetOwnerWindow());
     66  RefPtr<WindowContext> winCtx = GetOwnerWindow()->GetWindowContext();
     67  RefPtr<CloseWatcherManager> manager =
     68      GetOwnerWindow()->EnsureCloseWatcherManager();
     69  EventInit init;
     70  init.mBubbles = false;
     71  // 6. Let canPreventClose be true if window's close watcher manager's groups's
     72  // size is less than window's close watcher manager's allowed number of
     73  // groups, and window has history-action activation; otherwise false.
     74  init.mCancelable =
     75      !aRequireHistoryActionActivation ||
     76      (manager->CanGrow() && winCtx->HasValidHistoryActivation());
     77  RefPtr<Event> event = Event::Constructor(this, u"cancel"_ns, init);
     78  event->SetTrusted(true);
     79  // 7. Set closeWatcher's is running cancel action to true.
     80  mIsRunningCancelAction = true;
     81  // 8. Let shouldContinue be the result of running closeWatcher's cancel action
     82  // given canPreventClose.
     83  DispatchEvent(*event);
     84  // 9. Set closeWatcher's is running cancel action to false.
     85  mIsRunningCancelAction = false;
     86  // 10. If shouldContinue is false, then:
     87  if (event->DefaultPrevented()) {
     88    // 10.2. Consume history-action user activation given window.
     89    winCtx->ConsumeHistoryActivation();
     90    // 10.3. Return false.
     91    return false;
     92  }
     93  // 11. Close closeWatcher.
     94  Close();
     95  // 12. Return true.
     96  return true;
     97 }
     98 
     99 // https://html.spec.whatwg.org/multipage/interaction.html#close-watcher-close
    100 void CloseWatcher::Close() {
    101  // 1. If closeWatcher is not active, then return.
    102  // 2. If the result of running closeWatcher's get enabled state is false, then
    103  // return true.
    104  // 3. If closeWatcher's window's associated Document is not fully active, then
    105  // return.
    106  if (!IsActive()) {
    107    return;
    108  }
    109  // 4. Destroy closeWatcher.
    110  Destroy();
    111  EventInit init;
    112  init.mBubbles = false;
    113  init.mCancelable = false;
    114  RefPtr<Event> event = Event::Constructor(this, u"close"_ns, init);
    115  event->SetTrusted(true);
    116  DispatchEvent(*event);
    117 }
    118 
    119 void CloseWatcher::AddToWindowsCloseWatcherManager() {
    120  if (auto* window = GetOwnerWindow()) {
    121    window->EnsureCloseWatcherManager()->Add(*this);
    122    window->NotifyCloseWatcherAdded();
    123  }
    124 }
    125 
    126 void CloseWatcher::Destroy() {
    127  if (auto* window = GetOwnerWindow()) {
    128    window->EnsureCloseWatcherManager()->Remove(*this);
    129    window->NotifyCloseWatcherRemoved();
    130  }
    131 }
    132 
    133 bool CloseWatcher::IsActive() const {
    134  if (!mEnabled) {
    135    return false;
    136  }
    137  if (auto* window = GetOwnerWindow()) {
    138    return window->IsFullyActive() &&
    139           window->EnsureCloseWatcherManager()->Contains(*this);
    140  }
    141  return false;
    142 }
    143 
    144 void CloseWatcher::RunAbortAlgorithm() { Destroy(); }
    145 
    146 }  // namespace mozilla::dom