1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/wifi/nsWifiMonitor.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,250 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsCOMPtr.h" 1.9 +#include "nsProxyRelease.h" 1.10 +#include "nsComponentManagerUtils.h" 1.11 +#include "nsServiceManagerUtils.h" 1.12 +#include "nsThreadUtils.h" 1.13 +#include "nsXPCOM.h" 1.14 +#include "nsXPCOMCID.h" 1.15 +#include "nsIObserver.h" 1.16 +#include "nsIObserverService.h" 1.17 +#include "nsWifiMonitor.h" 1.18 +#include "nsWifiAccessPoint.h" 1.19 + 1.20 +#include "nsServiceManagerUtils.h" 1.21 +#include "nsComponentManagerUtils.h" 1.22 +#include "mozilla/Services.h" 1.23 + 1.24 +using namespace mozilla; 1.25 + 1.26 +#if defined(PR_LOGGING) 1.27 +PRLogModuleInfo *gWifiMonitorLog; 1.28 +#endif 1.29 + 1.30 +NS_IMPL_ISUPPORTS(nsWifiMonitor, 1.31 + nsIRunnable, 1.32 + nsIObserver, 1.33 + nsIWifiMonitor) 1.34 + 1.35 +nsWifiMonitor::nsWifiMonitor() 1.36 +: mKeepGoing(true) 1.37 +, mReentrantMonitor("nsWifiMonitor.mReentrantMonitor") 1.38 +{ 1.39 +#if defined(PR_LOGGING) 1.40 + gWifiMonitorLog = PR_NewLogModule("WifiMonitor"); 1.41 +#endif 1.42 + 1.43 + nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); 1.44 + if (obsSvc) 1.45 + obsSvc->AddObserver(this, "xpcom-shutdown", false); 1.46 + 1.47 + LOG(("@@@@@ wifimonitor created\n")); 1.48 +} 1.49 + 1.50 +nsWifiMonitor::~nsWifiMonitor() 1.51 +{ 1.52 +} 1.53 + 1.54 +NS_IMETHODIMP 1.55 +nsWifiMonitor::Observe(nsISupports *subject, const char *topic, 1.56 + const char16_t *data) 1.57 +{ 1.58 + if (!strcmp(topic, "xpcom-shutdown")) { 1.59 + LOG(("Shutting down\n")); 1.60 + mKeepGoing = false; 1.61 + 1.62 + ReentrantMonitorAutoEnter mon(mReentrantMonitor); 1.63 + mon.Notify(); 1.64 + } 1.65 + return NS_OK; 1.66 +} 1.67 + 1.68 + 1.69 +NS_IMETHODIMP nsWifiMonitor::StartWatching(nsIWifiListener *aListener) 1.70 +{ 1.71 + if (!aListener) 1.72 + return NS_ERROR_NULL_POINTER; 1.73 + 1.74 + nsresult rv = NS_OK; 1.75 + if (!mThread) { 1.76 + rv = NS_NewThread(getter_AddRefs(mThread), this); 1.77 + if (NS_FAILED(rv)) 1.78 + return rv; 1.79 + } 1.80 + 1.81 + ReentrantMonitorAutoEnter mon(mReentrantMonitor); 1.82 + 1.83 + mKeepGoing = true; 1.84 + 1.85 + mListeners.AppendElement(nsWifiListener(new nsMainThreadPtrHolder<nsIWifiListener>(aListener))); 1.86 + 1.87 + // tell ourselves that we have a new watcher. 1.88 + mon.Notify(); 1.89 + return NS_OK; 1.90 +} 1.91 + 1.92 +NS_IMETHODIMP nsWifiMonitor::StopWatching(nsIWifiListener *aListener) 1.93 +{ 1.94 + if (!aListener) 1.95 + return NS_ERROR_NULL_POINTER; 1.96 + 1.97 + LOG(("removing listener\n")); 1.98 + 1.99 + ReentrantMonitorAutoEnter mon(mReentrantMonitor); 1.100 + 1.101 + for (uint32_t i = 0; i < mListeners.Length(); i++) { 1.102 + 1.103 + if (mListeners[i].mListener == aListener) { 1.104 + mListeners.RemoveElementAt(i); 1.105 + break; 1.106 + } 1.107 + } 1.108 + 1.109 + if (mListeners.Length() == 0) { 1.110 + mKeepGoing = false; 1.111 + mon.Notify(); 1.112 + mThread = nullptr; 1.113 + } 1.114 + 1.115 + return NS_OK; 1.116 +} 1.117 + 1.118 +typedef nsTArray<nsMainThreadPtrHandle<nsIWifiListener> > WifiListenerArray; 1.119 + 1.120 +class nsPassErrorToWifiListeners MOZ_FINAL : public nsIRunnable 1.121 +{ 1.122 + public: 1.123 + NS_DECL_THREADSAFE_ISUPPORTS 1.124 + NS_DECL_NSIRUNNABLE 1.125 + 1.126 + nsPassErrorToWifiListeners(nsAutoPtr<WifiListenerArray> aListeners, 1.127 + nsresult aResult) 1.128 + : mListeners(aListeners), 1.129 + mResult(aResult) 1.130 + {} 1.131 + 1.132 + private: 1.133 + nsAutoPtr<WifiListenerArray> mListeners; 1.134 + nsresult mResult; 1.135 +}; 1.136 + 1.137 +NS_IMPL_ISUPPORTS(nsPassErrorToWifiListeners, 1.138 + nsIRunnable) 1.139 + 1.140 +NS_IMETHODIMP nsPassErrorToWifiListeners::Run() 1.141 +{ 1.142 + LOG(("About to send error to the wifi listeners\n")); 1.143 + for (size_t i = 0; i < mListeners->Length(); i++) { 1.144 + (*mListeners)[i]->OnError(mResult); 1.145 + } 1.146 + return NS_OK; 1.147 +} 1.148 + 1.149 +NS_IMETHODIMP nsWifiMonitor::Run() 1.150 +{ 1.151 + LOG(("@@@@@ wifi monitor run called\n")); 1.152 + 1.153 + PR_SetCurrentThreadName("Wifi Monitor"); 1.154 + 1.155 + nsresult rv = DoScan(); 1.156 + 1.157 + if (mKeepGoing && NS_FAILED(rv)) { 1.158 + nsAutoPtr<WifiListenerArray> currentListeners( 1.159 + new WifiListenerArray(mListeners.Length())); 1.160 + if (!currentListeners) 1.161 + return NS_ERROR_OUT_OF_MEMORY; 1.162 + 1.163 + for (uint32_t i = 0; i < mListeners.Length(); i++) 1.164 + currentListeners->AppendElement(mListeners[i].mListener); 1.165 + 1.166 + nsCOMPtr<nsIThread> thread = do_GetMainThread(); 1.167 + if (!thread) 1.168 + return NS_ERROR_UNEXPECTED; 1.169 + 1.170 + nsCOMPtr<nsIRunnable> runnable(new nsPassErrorToWifiListeners(currentListeners, rv)); 1.171 + if (!runnable) 1.172 + return NS_ERROR_OUT_OF_MEMORY; 1.173 + 1.174 + thread->Dispatch(runnable, NS_DISPATCH_SYNC); 1.175 + } 1.176 + 1.177 + return NS_OK; 1.178 +} 1.179 + 1.180 +class nsCallWifiListeners MOZ_FINAL : public nsIRunnable 1.181 +{ 1.182 + public: 1.183 + NS_DECL_THREADSAFE_ISUPPORTS 1.184 + NS_DECL_NSIRUNNABLE 1.185 + 1.186 + nsCallWifiListeners(nsAutoPtr<WifiListenerArray> aListeners, 1.187 + nsAutoPtr<nsTArray<nsIWifiAccessPoint*> > aAccessPoints) 1.188 + : mListeners(aListeners), 1.189 + mAccessPoints(aAccessPoints) 1.190 + {} 1.191 + 1.192 + private: 1.193 + nsAutoPtr<WifiListenerArray> mListeners; 1.194 + nsAutoPtr<nsTArray<nsIWifiAccessPoint*> > mAccessPoints; 1.195 +}; 1.196 + 1.197 +NS_IMPL_ISUPPORTS(nsCallWifiListeners, 1.198 + nsIRunnable) 1.199 + 1.200 +NS_IMETHODIMP nsCallWifiListeners::Run() 1.201 +{ 1.202 + LOG(("About to send data to the wifi listeners\n")); 1.203 + for (size_t i = 0; i < mListeners->Length(); i++) { 1.204 + (*mListeners)[i]->OnChange(mAccessPoints->Elements(), mAccessPoints->Length()); 1.205 + } 1.206 + return NS_OK; 1.207 +} 1.208 + 1.209 +nsresult 1.210 +nsWifiMonitor::CallWifiListeners(const nsCOMArray<nsWifiAccessPoint> &aAccessPoints, 1.211 + bool aAccessPointsChanged) 1.212 +{ 1.213 + nsAutoPtr<WifiListenerArray> currentListeners( 1.214 + new WifiListenerArray(mListeners.Length())); 1.215 + if (!currentListeners) 1.216 + return NS_ERROR_OUT_OF_MEMORY; 1.217 + 1.218 + { 1.219 + ReentrantMonitorAutoEnter mon(mReentrantMonitor); 1.220 + 1.221 + for (uint32_t i = 0; i < mListeners.Length(); i++) { 1.222 + if (!mListeners[i].mHasSentData || aAccessPointsChanged) { 1.223 + mListeners[i].mHasSentData = true; 1.224 + currentListeners->AppendElement(mListeners[i].mListener); 1.225 + } 1.226 + } 1.227 + } 1.228 + 1.229 + if (currentListeners->Length() > 0) 1.230 + { 1.231 + uint32_t resultCount = aAccessPoints.Count(); 1.232 + nsAutoPtr<nsTArray<nsIWifiAccessPoint*> > accessPoints( 1.233 + new nsTArray<nsIWifiAccessPoint *>(resultCount)); 1.234 + if (!accessPoints) 1.235 + return NS_ERROR_OUT_OF_MEMORY; 1.236 + 1.237 + for (uint32_t i = 0; i < resultCount; i++) 1.238 + accessPoints->AppendElement(aAccessPoints[i]); 1.239 + 1.240 + nsCOMPtr<nsIThread> thread = do_GetMainThread(); 1.241 + if (!thread) 1.242 + return NS_ERROR_UNEXPECTED; 1.243 + 1.244 + nsCOMPtr<nsIRunnable> runnable( 1.245 + new nsCallWifiListeners(currentListeners, accessPoints)); 1.246 + if (!runnable) 1.247 + return NS_ERROR_OUT_OF_MEMORY; 1.248 + 1.249 + thread->Dispatch(runnable, NS_DISPATCH_SYNC); 1.250 + } 1.251 + 1.252 + return NS_OK; 1.253 +}