CloseWatcherManager.cpp (2919B)
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 "CloseWatcherManager.h" 8 9 #include "CloseWatcher.h" 10 11 namespace mozilla::dom { 12 13 NS_IMPL_CYCLE_COLLECTION(CloseWatcherManager, mGroups) 14 NS_IMPL_CYCLE_COLLECTING_ADDREF(CloseWatcherManager) 15 NS_IMPL_CYCLE_COLLECTING_RELEASE(CloseWatcherManager) 16 17 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CloseWatcherManager) 18 NS_INTERFACE_MAP_ENTRY(nsISupports) 19 NS_INTERFACE_MAP_END 20 21 // https://html.spec.whatwg.org/multipage/interaction.html#notify-the-close-watcher-manager-about-user-activation 22 void CloseWatcherManager::NotifyUserInteraction() { 23 if (mNextUserInteractionAllowsNewGroup) { 24 mAllowedNumberOfGroups += 1; 25 mNextUserInteractionAllowsNewGroup = false; 26 } 27 } 28 29 bool CloseWatcherManager::CanGrow() const { 30 return mGroups.Length() < mAllowedNumberOfGroups; 31 } 32 33 // https://html.spec.whatwg.org/multipage/interaction.html#process-close-watchers 34 MOZ_CAN_RUN_SCRIPT bool CloseWatcherManager::ProcessCloseRequest() { 35 bool processedACloseWatcher = false; 36 if (mGroups.IsEmpty()) { 37 return processedACloseWatcher; 38 } 39 auto i = mGroups.Length() - 1; 40 auto group = mGroups.ElementAt(i).Clone(); 41 for (RefPtr<CloseWatcher> watcher : group.BackwardRange()) { 42 processedACloseWatcher = true; 43 // TODO:(keithamus): https://github.com/whatwg/html/issues/10240 ? 44 if (!watcher->RequestToClose(true)) { 45 break; 46 } 47 } 48 if (mAllowedNumberOfGroups > 1) { 49 mAllowedNumberOfGroups -= 1; 50 } 51 return processedACloseWatcher; 52 } 53 54 // https://html.spec.whatwg.org/multipage/interaction.html#establish-a-close-watcher 55 // step 4-6 56 void CloseWatcherManager::Add(CloseWatcher& aWatcher) { 57 if (CanGrow()) { 58 mGroups.AppendElement()->AppendElement(&aWatcher); 59 } else { 60 MOZ_ASSERT(!mGroups.IsEmpty(), 61 "CloseWatcherManager groups must be at least 1"); 62 auto i = mGroups.Length() - 1; 63 MOZ_ASSERT(!mGroups.ElementAt(i).Contains(&aWatcher)); 64 mGroups.ElementAt(i).AppendElement(&aWatcher); 65 } 66 mNextUserInteractionAllowsNewGroup = true; 67 } 68 69 // https://html.spec.whatwg.org/multipage/interaction.html#close-watcher-destroy 70 void CloseWatcherManager::Remove(CloseWatcher& aWatcher) { 71 CloseWatcherArray::ForwardIterator iter(mGroups); 72 while (iter.HasMore()) { 73 auto& group = iter.GetNext(); 74 group.RemoveElement(&aWatcher); 75 if (group.IsEmpty()) { 76 iter.Remove(); 77 } 78 } 79 mGroups.Compact(); 80 } 81 82 bool CloseWatcherManager::Contains(const CloseWatcher& aWatcher) const { 83 for (const auto& group : mGroups.BackwardRange()) { 84 if (group.Contains(&aWatcher)) { 85 return true; 86 } 87 } 88 return false; 89 } 90 91 } // namespace mozilla::dom