MsaaIdGenerator.cpp (2680B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=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 "MsaaIdGenerator.h" 8 9 #include "mozilla/Assertions.h" 10 #include "mozilla/ClearOnShutdown.h" 11 #include "MsaaAccessible.h" 12 #include "nsAccessibilityService.h" 13 14 namespace mozilla { 15 namespace a11y { 16 17 uint32_t MsaaIdGenerator::GetID() { 18 if (!mGetIDCalled) { 19 mGetIDCalled = true; 20 // this is a static instance, so capturing this here is safe. 21 RunOnShutdown([this] { 22 if (mReleaseIDTimer) { 23 mReleaseIDTimer->Cancel(); 24 ReleasePendingIDs(); 25 } 26 }); 27 } 28 uint32_t id = mIDSet.GetID(); 29 MOZ_ASSERT(id <= ((1UL << kNumFullIDBits) - 1UL)); 30 return ~id; 31 } 32 33 void MsaaIdGenerator::ReleasePendingIDs() { 34 for (auto id : mIDsToRelease) { 35 mIDSet.ReleaseID(~id); 36 } 37 mIDsToRelease.Clear(); 38 mReleaseIDTimer = nullptr; 39 } 40 41 void MsaaIdGenerator::ReleasePendingIdsCallback(nsITimer* aTimer, 42 void* aClosure) { 43 MsaaIdGenerator* gen = (MsaaIdGenerator*)aClosure; 44 gen->ReleasePendingIDs(); 45 } 46 47 bool MsaaIdGenerator::ReleaseID(uint32_t aID) { 48 MOZ_ASSERT(aID != MsaaAccessible::kNoID); 49 // Releasing an id means it can be reused. Reusing ids too quickly can 50 // cause problems for clients which process events asynchronously. 51 // Therefore, we release ids after a short delay. This doesn't seem to be 52 // necessary when the cache is disabled, perhaps because the COM runtime 53 // holds references to our objects for longer. 54 if (nsAccessibilityService::IsShutdown()) { 55 // If accessibility is shut down, no more Accessibles will be created. 56 // Also, if the service is shut down, it's possible XPCOM is also shutting 57 // down, in which case timers won't work. Thus, we release the id 58 // immediately. 59 mIDSet.ReleaseID(~aID); 60 return true; 61 } 62 const uint32_t kReleaseDelay = 1000; 63 mIDsToRelease.AppendElement(aID); 64 if (!mReleaseIDTimer) { 65 mReleaseIDTimer = NS_NewTimer(); 66 } 67 // mReleaseIDTimer is cancelled on shutdown and this is a static instance, 68 // so capturing this here is safe. 69 mReleaseIDTimer->InitWithNamedFuncCallback( 70 ReleasePendingIdsCallback, this, kReleaseDelay, nsITimer::TYPE_ONE_SHOT, 71 "a11y::MsaaIdGenerator::ReleaseIDDelayed"_ns); 72 73 return true; 74 } 75 76 void MsaaIdGenerator::ReleaseID(NotNull<MsaaAccessible*> aMsaaAcc) { 77 ReleaseID(aMsaaAcc->GetExistingID()); 78 } 79 80 } // namespace a11y 81 } // namespace mozilla