netwerk/wifi/nsWifiMonitor.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial