/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __nsWifiMonitor__ #define __nsWifiMonitor__ #include "nsIWifiMonitor.h" #include "nsCOMPtr.h" #include "nsProxyRelease.h" #include "nsIThread.h" #include "nsIRunnable.h" #include "nsCOMArray.h" #include "nsIWifiListener.h" #include "mozilla/Atomics.h" #include "mozilla/ReentrantMonitor.h" #include "mozilla/Logging.h" #include "nsIObserver.h" #include "nsTArray.h" #include "mozilla/Attributes.h" #include "mozilla/Monitor.h" #include "WifiScanner.h" namespace mozilla { class TestWifiMonitor; } extern mozilla::LazyLogModule gWifiMonitorLog; class nsWifiAccessPoint; // Period between scans when on mobile network. #define WIFI_SCAN_INTERVAL_MS_PREF "network.wifi.scanning_period" #ifdef XP_MACOSX // Use a larger stack size for the wifi monitor thread of macOS, to // accommodate Core WLAN making large stack allocations. # define kMacOSWifiMonitorStackSize (512 * 1024) #endif struct WifiListenerHolder { RefPtr mListener; bool mShouldPoll; bool mHasSentData = false; explicit WifiListenerHolder(nsIWifiListener* aListener, bool aShouldPoll = false) : mListener(aListener), mShouldPoll(aShouldPoll) {} }; class nsWifiMonitor final : public nsIWifiMonitor, public nsIObserver { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIWIFIMONITOR NS_DECL_NSIOBSERVER explicit nsWifiMonitor( mozilla::UniquePtr&& aScanner = nullptr); private: friend class mozilla::TestWifiMonitor; ~nsWifiMonitor(); nsresult DispatchScanToBackgroundThread(uint64_t aPollingId = 0, uint32_t aWaitMs = 0); void Scan(uint64_t aPollingId); nsresult DoScan(); nsresult CallWifiListeners( nsTArray>&& aAccessPoints, bool aAccessPointsChanged); nsresult PassErrorToWifiListeners(nsresult rv); void Close(); bool IsBackgroundThread(); bool ShouldPoll() { MOZ_ASSERT(!IsBackgroundThread()); return (mShouldPollForCurrentNetwork && !mListeners.IsEmpty()) || mNumPollingListeners > 0; }; #ifdef ENABLE_TESTS // Test-only function that confirms we "should" be polling. May be wrong // if somehow the polling tasks are not set to run on the background // thread. bool IsPolling() { return mThread && mPollingId; } #endif // Main thread only. nsCOMPtr mThread; // Main thread only. nsTArray mListeners; // Background thread only. mozilla::UniquePtr mWifiScanner; // Background thread only. Sorted. nsTArray> mLastAccessPoints; // Wifi-scanning requests may poll, meaning they will run repeatedly on // a scheduled time period. If this value is 0 then polling is not running, // otherwise, it indicates the "ID" of the polling that is running. if some // other polling (with different ID) is running, it will stop, not iterate. mozilla::Atomic mPollingId; // Number of current listeners that requested that the wifi scan poll // periodically. // Main thread only. uint32_t mNumPollingListeners = 0; // True if the current network type is one that requires polling // (i.e. a "mobile" network type). // Main thread only. bool mShouldPollForCurrentNetwork = false; }; #endif