Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "nsCOMPtr.h"
6 #include "nsProxyRelease.h"
7 #include "nsComponentManagerUtils.h"
8 #include "nsServiceManagerUtils.h"
9 #include "nsThreadUtils.h"
10 #include "nsXPCOM.h"
11 #include "nsXPCOMCID.h"
12 #include "nsIObserver.h"
13 #include "nsIObserverService.h"
14 #include "nsWifiMonitor.h"
15 #include "nsWifiAccessPoint.h"
17 #include "nsServiceManagerUtils.h"
18 #include "nsComponentManagerUtils.h"
19 #include "mozilla/Services.h"
21 using namespace mozilla;
23 #if defined(PR_LOGGING)
24 PRLogModuleInfo *gWifiMonitorLog;
25 #endif
27 NS_IMPL_ISUPPORTS(nsWifiMonitor,
28 nsIRunnable,
29 nsIObserver,
30 nsIWifiMonitor)
32 nsWifiMonitor::nsWifiMonitor()
33 : mKeepGoing(true)
34 , mReentrantMonitor("nsWifiMonitor.mReentrantMonitor")
35 {
36 #if defined(PR_LOGGING)
37 gWifiMonitorLog = PR_NewLogModule("WifiMonitor");
38 #endif
40 nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
41 if (obsSvc)
42 obsSvc->AddObserver(this, "xpcom-shutdown", false);
44 LOG(("@@@@@ wifimonitor created\n"));
45 }
47 nsWifiMonitor::~nsWifiMonitor()
48 {
49 }
51 NS_IMETHODIMP
52 nsWifiMonitor::Observe(nsISupports *subject, const char *topic,
53 const char16_t *data)
54 {
55 if (!strcmp(topic, "xpcom-shutdown")) {
56 LOG(("Shutting down\n"));
57 mKeepGoing = false;
59 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
60 mon.Notify();
61 }
62 return NS_OK;
63 }
66 NS_IMETHODIMP nsWifiMonitor::StartWatching(nsIWifiListener *aListener)
67 {
68 if (!aListener)
69 return NS_ERROR_NULL_POINTER;
71 nsresult rv = NS_OK;
72 if (!mThread) {
73 rv = NS_NewThread(getter_AddRefs(mThread), this);
74 if (NS_FAILED(rv))
75 return rv;
76 }
78 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
80 mKeepGoing = true;
82 mListeners.AppendElement(nsWifiListener(new nsMainThreadPtrHolder<nsIWifiListener>(aListener)));
84 // tell ourselves that we have a new watcher.
85 mon.Notify();
86 return NS_OK;
87 }
89 NS_IMETHODIMP nsWifiMonitor::StopWatching(nsIWifiListener *aListener)
90 {
91 if (!aListener)
92 return NS_ERROR_NULL_POINTER;
94 LOG(("removing listener\n"));
96 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
98 for (uint32_t i = 0; i < mListeners.Length(); i++) {
100 if (mListeners[i].mListener == aListener) {
101 mListeners.RemoveElementAt(i);
102 break;
103 }
104 }
106 if (mListeners.Length() == 0) {
107 mKeepGoing = false;
108 mon.Notify();
109 mThread = nullptr;
110 }
112 return NS_OK;
113 }
115 typedef nsTArray<nsMainThreadPtrHandle<nsIWifiListener> > WifiListenerArray;
117 class nsPassErrorToWifiListeners MOZ_FINAL : public nsIRunnable
118 {
119 public:
120 NS_DECL_THREADSAFE_ISUPPORTS
121 NS_DECL_NSIRUNNABLE
123 nsPassErrorToWifiListeners(nsAutoPtr<WifiListenerArray> aListeners,
124 nsresult aResult)
125 : mListeners(aListeners),
126 mResult(aResult)
127 {}
129 private:
130 nsAutoPtr<WifiListenerArray> mListeners;
131 nsresult mResult;
132 };
134 NS_IMPL_ISUPPORTS(nsPassErrorToWifiListeners,
135 nsIRunnable)
137 NS_IMETHODIMP nsPassErrorToWifiListeners::Run()
138 {
139 LOG(("About to send error to the wifi listeners\n"));
140 for (size_t i = 0; i < mListeners->Length(); i++) {
141 (*mListeners)[i]->OnError(mResult);
142 }
143 return NS_OK;
144 }
146 NS_IMETHODIMP nsWifiMonitor::Run()
147 {
148 LOG(("@@@@@ wifi monitor run called\n"));
150 PR_SetCurrentThreadName("Wifi Monitor");
152 nsresult rv = DoScan();
154 if (mKeepGoing && NS_FAILED(rv)) {
155 nsAutoPtr<WifiListenerArray> currentListeners(
156 new WifiListenerArray(mListeners.Length()));
157 if (!currentListeners)
158 return NS_ERROR_OUT_OF_MEMORY;
160 for (uint32_t i = 0; i < mListeners.Length(); i++)
161 currentListeners->AppendElement(mListeners[i].mListener);
163 nsCOMPtr<nsIThread> thread = do_GetMainThread();
164 if (!thread)
165 return NS_ERROR_UNEXPECTED;
167 nsCOMPtr<nsIRunnable> runnable(new nsPassErrorToWifiListeners(currentListeners, rv));
168 if (!runnable)
169 return NS_ERROR_OUT_OF_MEMORY;
171 thread->Dispatch(runnable, NS_DISPATCH_SYNC);
172 }
174 return NS_OK;
175 }
177 class nsCallWifiListeners MOZ_FINAL : public nsIRunnable
178 {
179 public:
180 NS_DECL_THREADSAFE_ISUPPORTS
181 NS_DECL_NSIRUNNABLE
183 nsCallWifiListeners(nsAutoPtr<WifiListenerArray> aListeners,
184 nsAutoPtr<nsTArray<nsIWifiAccessPoint*> > aAccessPoints)
185 : mListeners(aListeners),
186 mAccessPoints(aAccessPoints)
187 {}
189 private:
190 nsAutoPtr<WifiListenerArray> mListeners;
191 nsAutoPtr<nsTArray<nsIWifiAccessPoint*> > mAccessPoints;
192 };
194 NS_IMPL_ISUPPORTS(nsCallWifiListeners,
195 nsIRunnable)
197 NS_IMETHODIMP nsCallWifiListeners::Run()
198 {
199 LOG(("About to send data to the wifi listeners\n"));
200 for (size_t i = 0; i < mListeners->Length(); i++) {
201 (*mListeners)[i]->OnChange(mAccessPoints->Elements(), mAccessPoints->Length());
202 }
203 return NS_OK;
204 }
206 nsresult
207 nsWifiMonitor::CallWifiListeners(const nsCOMArray<nsWifiAccessPoint> &aAccessPoints,
208 bool aAccessPointsChanged)
209 {
210 nsAutoPtr<WifiListenerArray> currentListeners(
211 new WifiListenerArray(mListeners.Length()));
212 if (!currentListeners)
213 return NS_ERROR_OUT_OF_MEMORY;
215 {
216 ReentrantMonitorAutoEnter mon(mReentrantMonitor);
218 for (uint32_t i = 0; i < mListeners.Length(); i++) {
219 if (!mListeners[i].mHasSentData || aAccessPointsChanged) {
220 mListeners[i].mHasSentData = true;
221 currentListeners->AppendElement(mListeners[i].mListener);
222 }
223 }
224 }
226 if (currentListeners->Length() > 0)
227 {
228 uint32_t resultCount = aAccessPoints.Count();
229 nsAutoPtr<nsTArray<nsIWifiAccessPoint*> > accessPoints(
230 new nsTArray<nsIWifiAccessPoint *>(resultCount));
231 if (!accessPoints)
232 return NS_ERROR_OUT_OF_MEMORY;
234 for (uint32_t i = 0; i < resultCount; i++)
235 accessPoints->AppendElement(aAccessPoints[i]);
237 nsCOMPtr<nsIThread> thread = do_GetMainThread();
238 if (!thread)
239 return NS_ERROR_UNEXPECTED;
241 nsCOMPtr<nsIRunnable> runnable(
242 new nsCallWifiListeners(currentListeners, accessPoints));
243 if (!runnable)
244 return NS_ERROR_OUT_OF_MEMORY;
246 thread->Dispatch(runnable, NS_DISPATCH_SYNC);
247 }
249 return NS_OK;
250 }