1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* 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<nsIWifiListener> 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<mozilla::WifiScanner>&& 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<RefPtr<nsIWifiAccessPoint>>&& 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<nsIThread> mThread;
// Main thread only.
nsTArray<WifiListenerHolder> mListeners;
// Background thread only.
mozilla::UniquePtr<mozilla::WifiScanner> mWifiScanner;
// Background thread only. Sorted.
nsTArray<RefPtr<nsIWifiAccessPoint>> 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<uint64_t> 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
|