michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsXPCOM.h" michael@0: #include "nsXPCOMCID.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsWifiMonitor.h" michael@0: #include "nsWifiAccessPoint.h" michael@0: michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "mozilla/Services.h" michael@0: michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIInterfaceRequestorUtils.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: #if defined(PR_LOGGING) michael@0: PRLogModuleInfo *gWifiMonitorLog; michael@0: #endif michael@0: michael@0: NS_IMPL_ISUPPORTS(nsWifiMonitor, michael@0: nsIWifiMonitor, michael@0: nsIObserver, michael@0: nsIWifiScanResultsReady) michael@0: michael@0: nsWifiMonitor::nsWifiMonitor() michael@0: { michael@0: #if defined(PR_LOGGING) michael@0: gWifiMonitorLog = PR_NewLogModule("WifiMonitor"); michael@0: #endif michael@0: michael@0: nsCOMPtr obsSvc = mozilla::services::GetObserverService(); michael@0: if (obsSvc) { michael@0: obsSvc->AddObserver(this, "xpcom-shutdown", false); michael@0: } michael@0: LOG(("@@@@@ wifimonitor created\n")); michael@0: } michael@0: michael@0: nsWifiMonitor::~nsWifiMonitor() michael@0: { michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsWifiMonitor::StartWatching(nsIWifiListener *aListener) michael@0: { michael@0: LOG(("@@@@@ nsWifiMonitor::StartWatching\n")); michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: if (!aListener) { michael@0: return NS_ERROR_NULL_POINTER; michael@0: } michael@0: michael@0: mListeners.AppendElement(nsWifiListener(new nsMainThreadPtrHolder(aListener))); michael@0: michael@0: if (!mTimer) { michael@0: mTimer = do_CreateInstance("@mozilla.org/timer;1"); michael@0: mTimer->Init(this, 5000, nsITimer::TYPE_REPEATING_SLACK); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsWifiMonitor::StopWatching(nsIWifiListener *aListener) michael@0: { michael@0: LOG(("@@@@@ nsWifiMonitor::StopWatching\n")); michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: if (!aListener) { michael@0: return NS_ERROR_NULL_POINTER; michael@0: } michael@0: michael@0: for (uint32_t i = 0; i < mListeners.Length(); i++) { michael@0: if (mListeners[i].mListener == aListener) { michael@0: mListeners.RemoveElementAt(i); michael@0: break; michael@0: } michael@0: } michael@0: michael@0: if (mListeners.Length() == 0) { michael@0: ClearTimer(); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsWifiMonitor::Observe(nsISupports *subject, const char *topic, michael@0: const char16_t *data) michael@0: { michael@0: if (!strcmp(topic, "timer-callback")) { michael@0: LOG(("timer callback\n")); michael@0: michael@0: nsCOMPtr ir = do_GetService("@mozilla.org/telephony/system-worker-manager;1"); michael@0: nsCOMPtr wifi = do_GetInterface(ir); michael@0: if (!wifi) { michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: wifi->GetWifiScanResults(this); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (!strcmp(topic, "xpcom-shutdown")) { michael@0: LOG(("Shutting down\n")); michael@0: ClearTimer(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsWifiMonitor::Onready(uint32_t count, nsIWifiScanResult **results) michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: LOG(("@@@@@ About to send data to the wifi listeners\n")); michael@0: michael@0: nsCOMArray accessPoints; michael@0: michael@0: for (uint32_t i = 0; i < count; i++) { michael@0: nsRefPtr ap = new nsWifiAccessPoint(); michael@0: michael@0: nsString temp; michael@0: results[i]->GetBssid(temp); michael@0: // 00:00:00:00:00:00 --> 00-00-00-00-00-00 michael@0: for (int32_t x=0; x<6; x++) { michael@0: temp.ReplaceSubstring(NS_LITERAL_STRING(":"), NS_LITERAL_STRING("-")); // would it be too much to ask for a ReplaceAll()? michael@0: } michael@0: michael@0: nsCString mac; michael@0: mac.AssignWithConversion(temp); michael@0: michael@0: results[i]->GetSsid(temp); michael@0: michael@0: nsCString ssid; michael@0: ssid.AssignWithConversion(temp); michael@0: michael@0: uint32_t signal; michael@0: results[i]->GetSignalStrength(&signal); michael@0: michael@0: ap->setSignal(signal); michael@0: ap->setMacRaw(mac.get()); michael@0: ap->setSSIDRaw(ssid.get(), ssid.Length()); michael@0: michael@0: accessPoints.AppendObject(ap); michael@0: } michael@0: michael@0: bool accessPointsChanged = !AccessPointsEqual(accessPoints, mLastAccessPoints); michael@0: ReplaceArray(mLastAccessPoints, accessPoints); michael@0: michael@0: nsTArray ac; michael@0: uint32_t resultCount = mLastAccessPoints.Count(); michael@0: for (uint32_t i = 0; i < resultCount; i++) { michael@0: ac.AppendElement(mLastAccessPoints[i]); michael@0: } michael@0: michael@0: for (uint32_t i = 0; i < mListeners.Length(); i++) { michael@0: if (!mListeners[i].mHasSentData || accessPointsChanged) { michael@0: mListeners[i].mHasSentData = true; michael@0: mListeners[i].mListener->OnChange(ac.Elements(), ac.Length()); michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsWifiMonitor::Onfailure() michael@0: { michael@0: NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); michael@0: LOG(("@@@@@ About to send error to the wifi listeners\n")); michael@0: for (uint32_t i = 0; i < mListeners.Length(); i++) { michael@0: mListeners[i].mListener->OnError(NS_ERROR_UNEXPECTED); michael@0: } michael@0: michael@0: ClearTimer(); michael@0: return NS_OK; michael@0: }