diff options
author | joth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-28 12:24:24 +0000 |
---|---|---|
committer | joth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-28 12:24:24 +0000 |
commit | 4048ddb92790b16b99a6757dd978393688348e9f (patch) | |
tree | b0f27c2569e4bc26ca67e341fef5ea0b2fbb092c /chrome/browser | |
parent | 57db02ecc7aa07b64fde0739b37534bc00dc0f53 (diff) | |
download | chromium_src-4048ddb92790b16b99a6757dd978393688348e9f.zip chromium_src-4048ddb92790b16b99a6757dd978393688348e9f.tar.gz chromium_src-4048ddb92790b16b99a6757dd978393688348e9f.tar.bz2 |
Update Gears wifi data providers to Chrome style & APIs.
Add wifi data provider to project.
Add tests for windows provider. (More to follow)
BUG=11246
TEST=unit_tests - wifi_data_provider_win_unittest.cc
Review URL: http://codereview.chromium.org/543174
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37396 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
18 files changed, 806 insertions, 789 deletions
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 29e9dce..855116c 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -28,9 +28,3 @@ include_rules = [ # structure for these includes. "+chrome/renderer", ] - -# checkdeps needs to skip geolocation as it is unmodified gears code. -# TODO(joth): remove in next patch when this code is ported to chromium. -skip_child_includes = [ - "geolocation" -] diff --git a/chrome/browser/geolocation/device_data_provider.h b/chrome/browser/geolocation/device_data_provider.h index 6d5740e..cef140c 100644 --- a/chrome/browser/geolocation/device_data_provider.h +++ b/chrome/browser/geolocation/device_data_provider.h @@ -1,28 +1,7 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // A device data provider provides data from the device that is used by a // NetworkLocationProvider to obtain a position fix. This data may be either // cell radio data or wifi data. For a given type of data, we use a singleton @@ -40,18 +19,20 @@ // This file also declares the data structures used to represent cell radio data // and wifi data. -#ifndef GEARS_GEOLOCATION_DEVICE_DATA_PROVIDER_H__ -#define GEARS_GEOLOCATION_DEVICE_DATA_PROVIDER_H__ +#ifndef CHROME_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ +#define CHROME_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ #include <algorithm> +#include <functional> #include <set> +#include <string> #include <vector> -#include "gears/base/common/basictypes.h" // For int64 -#include "gears/base/common/common.h" -#include "gears/base/common/mutex.h" -#include "gears/base/common/scoped_refptr.h" // For RefCount -#include "gears/base/common/string16.h" -#include "third_party/scoped_ptr/scoped_ptr.h" + +#include "base/basictypes.h" +#include "base/lock.h" +#include "base/string16.h" +#include "base/string_util.h" +#include "base/scoped_ptr.h" // The following data structures are used to store cell radio data and wifi // data. See the Geolocation API design document at @@ -128,12 +109,12 @@ struct RadioData { return !Matches(other); } - std::string16 device_id; + string16 device_id; std::vector<CellData> cell_data; int home_mobile_network_code; // For the device's home network. int home_mobile_country_code; // For the device's home network. RadioType radio_type; // Mobile radio type. - std::string16 carrier; // Carrier name. + string16 carrier; // Carrier name. }; // Wifi data relating to a single access point. @@ -144,19 +125,19 @@ struct AccessPointData { channel(kint32min), signal_to_noise(kint32min) {} - std::string16 mac_address; + string16 mac_address; int radio_signal_strength; // Measured in dBm int age; // Milliseconds since this access point was detected int channel; int signal_to_noise; // Ratio in dB - std::string16 ssid; // Network identifier + string16 ssid; // Network identifier }; // This is to allow AccessPointData to be used in std::set. We order // lexicographically by MAC address. struct AccessPointDataLess : public std::less<AccessPointData> { - bool operator()(const AccessPointData &data1, - const AccessPointData &data2) const { + bool operator()(const AccessPointData& data1, + const AccessPointData& data2) const { return data1.mac_address < data2.mac_address; } }; @@ -207,23 +188,25 @@ class DeviceDataProviderImplBase { DeviceDataProviderImplBase() : container_(NULL) {} virtual ~DeviceDataProviderImplBase() {} - virtual bool GetData(DataType *data) = 0; + virtual bool StartDataProvider() = 0; + + virtual bool GetData(DataType* data) = 0; // Sets the container of this class, which is of type DeviceDataProvider. // This is required to pass as a parameter when making the callback to // listeners. - void SetContainer(DeviceDataProvider<DataType> *container) { + void SetContainer(DeviceDataProvider<DataType>* container) { container_ = container; } typedef typename DeviceDataProvider<DataType>::ListenerInterface ListenerInterface; - void AddListener(ListenerInterface *listener) { - MutexLock mutex(&listeners_mutex_); + void AddListener(ListenerInterface* listener) { + AutoLock mutex(listeners_mutex_); listeners_.insert(listener); } - bool RemoveListener(ListenerInterface *listener) { - MutexLock mutex(&listeners_mutex_); + bool RemoveListener(ListenerInterface* listener) { + AutoLock mutex(listeners_mutex_); typename ListenersSet::iterator iter = find(listeners_.begin(), listeners_.end(), listener); @@ -238,7 +221,7 @@ class DeviceDataProviderImplBase { // Calls DeviceDataUpdateAvailable() on all registered listeners. typedef std::set<ListenerInterface*> ListenersSet; void NotifyListeners() { - MutexLock lock(&listeners_mutex_); + AutoLock lock(listeners_mutex_); for (typename ListenersSet::const_iterator iter = listeners_.begin(); iter != listeners_.end(); ++iter) { @@ -247,13 +230,16 @@ class DeviceDataProviderImplBase { } private: - DeviceDataProvider<DataType> *container_; + DeviceDataProvider<DataType>* container_; // The listeners to this class and their mutex. + // TODO(joth): Once we've established the client is always single threaded, + // remove mutex and instead capture client's MessageLoop to stage the + // NotifyListeners callback via. ListenersSet listeners_; - Mutex listeners_mutex_; + Lock listeners_mutex_; - DISALLOW_EVIL_CONSTRUCTORS(DeviceDataProviderImplBase); + DISALLOW_COPY_AND_ASSIGN(DeviceDataProviderImplBase); }; typedef DeviceDataProviderImplBase<RadioData> RadioDataProviderImplBase; @@ -270,8 +256,10 @@ class DeviceDataProvider { // Interface to be implemented by listeners to a device data provider. class ListenerInterface { public: + // NOTE this may be called back in the context of the implementation private + // worker thread. (TODO Is there a naming convention to use for this?) virtual void DeviceDataUpdateAvailable( - DeviceDataProvider<DataType> *provider) = 0; + DeviceDataProvider<DataType>* provider) = 0; virtual ~ListenerInterface() {} }; @@ -279,7 +267,7 @@ class DeviceDataProvider { // implementation used by the singleton instance. This factory approach is // used to abastract accross both platform-specific implementation and to // inject mock implementations for testing. - typedef DeviceDataProviderImplBase<DataType> *(*ImplFactoryFunction)(void); + typedef DeviceDataProviderImplBase<DataType>* (*ImplFactoryFunction)(void); static void SetFactory(ImplFactoryFunction factory_function_in) { factory_function_ = factory_function_in; } @@ -290,14 +278,16 @@ class DeviceDataProvider { // Adds a listener, which will be called back with DeviceDataUpdateAvailable // whenever new data is available. Returns the singleton instance. - static DeviceDataProvider *Register(ListenerInterface *listener) { + static DeviceDataProvider* Register(ListenerInterface* listener) { + // TODO(joth): The following comment applied when this was used in Gears; + // revisit if this is still needed once usage is established in Chromium. // We protect against Register and Unregister being called asynchronously // from different threads. This is the case when a device data provider is // used by a NetworkLocationProvider object. Register is always called from // the JavaScript thread. Unregister is called when NetworkLocationProvider // objects are destructed, which happens asynchronously once the // NetworkLocationProvider HTTP request has completed. - MutexLock mutex(&instance_mutex_); + AutoLock mutex(instance_mutex_); if (!instance_) { instance_ = new DeviceDataProvider(); } @@ -309,8 +299,8 @@ class DeviceDataProvider { // Removes a listener. If this is the last listener, deletes the singleton // instance. Return value indicates success. - static bool Unregister(ListenerInterface *listener) { - MutexLock mutex(&instance_mutex_); + static bool Unregister(ListenerInterface* listener) { + AutoLock mutex(instance_mutex_); if (!instance_->RemoveListener(listener)) { return false; } @@ -324,41 +314,44 @@ class DeviceDataProvider { // Provides whatever data the provider has, which may be nothing. Return // value indicates whether this is all the data the provider could ever // obtain. - bool GetData(DataType *data) { + bool GetData(DataType* data) { return impl_->GetData(data); } private: // Private constructor and destructor, callers access singleton through // Register and Unregister. - DeviceDataProvider() { + DeviceDataProvider() : count_(0) { assert(factory_function_); impl_.reset((*factory_function_)()); impl_->SetContainer(this); + bool started = impl_->StartDataProvider(); + assert(started); } virtual ~DeviceDataProvider() {} void Ref() { - count_.Ref(); + ++count_; } // Returns true when the ref count transitions from 1 to 0. bool Unref() { - return count_.Unref(); + --count_; + return count_ == 0; } - void AddListener(ListenerInterface *listener) { + void AddListener(ListenerInterface* listener) { impl_->AddListener(listener); } - bool RemoveListener(ListenerInterface *listener) { + bool RemoveListener(ListenerInterface* listener) { return impl_->RemoveListener(listener); } - static DeviceDataProviderImplBase<DataType> *DefaultFactoryFunction(); + static DeviceDataProviderImplBase<DataType>* DefaultFactoryFunction(); // The singleton instance of this class and its mutex. - static DeviceDataProvider *instance_; - static Mutex instance_mutex_; + static DeviceDataProvider* instance_; + static Lock instance_mutex_; // The factory function used to create the singleton instance. static ImplFactoryFunction factory_function_; @@ -366,19 +359,18 @@ class DeviceDataProvider { // The internal implementation. scoped_ptr<DeviceDataProviderImplBase<DataType> > impl_; - RefCount count_; + int count_; DISALLOW_EVIL_CONSTRUCTORS(DeviceDataProvider); }; // static template<typename DataType> -Mutex DeviceDataProvider<DataType>::instance_mutex_; +Lock DeviceDataProvider<DataType>::instance_mutex_; // static template<typename DataType> -DeviceDataProvider<DataType> *DeviceDataProvider<DataType>::instance_ = - NULL; +DeviceDataProvider<DataType>* DeviceDataProvider<DataType>::instance_ = NULL; // static template<typename DataType> @@ -388,4 +380,4 @@ typename DeviceDataProvider<DataType>::ImplFactoryFunction typedef DeviceDataProvider<RadioData> RadioDataProvider; typedef DeviceDataProvider<WifiData> WifiDataProvider; -#endif // GEARS_GEOLOCATION_DEVICE_DATA_PROVIDER_H__ +#endif // CHROME_BROWSER_GEOLOCATION_DEVICE_DATA_PROVIDER_H_ diff --git a/chrome/browser/geolocation/empty_device_data_provider.cc b/chrome/browser/geolocation/empty_device_data_provider.cc index 9da8e831..f6286a6 100644 --- a/chrome/browser/geolocation/empty_device_data_provider.cc +++ b/chrome/browser/geolocation/empty_device_data_provider.cc @@ -1,39 +1,11 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -// Win32, Linux and OSX use the empty device data provider for radio data. -#if (defined(WIN32) && !defined(OS_WINCE)) || \ - defined(LINUX) || \ - defined(OS_MACOSX) - -#include "gears/geolocation/empty_device_data_provider.h" +#include "chrome/browser/geolocation/empty_device_data_provider.h" // static template<> RadioDataProviderImplBase *RadioDataProvider::DefaultFactoryFunction() { return new EmptyDeviceDataProvider<RadioData>(); } - -#endif // (WIN32 && !OS_WINCE) || LINUX || OS_MACOSX diff --git a/chrome/browser/geolocation/empty_device_data_provider.h b/chrome/browser/geolocation/empty_device_data_provider.h index 8c6097c..cf0d209 100644 --- a/chrome/browser/geolocation/empty_device_data_provider.h +++ b/chrome/browser/geolocation/empty_device_data_provider.h @@ -1,32 +1,11 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#ifndef GEARS_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H__ -#define GEARS_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H__ +#ifndef CHROME_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_ +#define CHROME_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_ -#include "gears/geolocation/device_data_provider.h" +#include "chrome/browser/geolocation/device_data_provider.h" // An implementation of DeviceDataProviderImplBase that does not provide any // data. Used on platforms where a given data type is not available. @@ -38,6 +17,7 @@ class EmptyDeviceDataProvider : public DeviceDataProviderImplBase<DataType> { virtual ~EmptyDeviceDataProvider() {} // DeviceDataProviderImplBase implementation + virtual bool StartDataProvider() { return true; } virtual bool GetData(DataType *data) { assert(data); // This is all the data we can get - nothing. @@ -45,7 +25,7 @@ class EmptyDeviceDataProvider : public DeviceDataProviderImplBase<DataType> { } private: - DISALLOW_EVIL_CONSTRUCTORS(EmptyDeviceDataProvider); + DISALLOW_COPY_AND_ASSIGN(EmptyDeviceDataProvider); }; -#endif // GEARS_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H__ +#endif // CHROME_BROWSER_GEOLOCATION_EMPTY_DEVICE_DATA_PROVIDER_H_ diff --git a/chrome/browser/geolocation/wifi_data_provider_common.cc b/chrome/browser/geolocation/wifi_data_provider_common.cc index 7068bc4..07724d5 100644 --- a/chrome/browser/geolocation/wifi_data_provider_common.cc +++ b/chrome/browser/geolocation/wifi_data_provider_common.cc @@ -1,95 +1,17 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -#include "gears/geolocation/wifi_data_provider_common.h" +#include "chrome/browser/geolocation/wifi_data_provider_common.h" -#include <assert.h> +#include "base/string_util.h" -#if defined(WIN32) || defined(OS_MACOSX) - -#if defined(WIN32) -#include <windows.h> -#elif defined(OS_MACOSX) -#include <CoreFoundation/CoreFoundation.h> -#include "gears/base/common/string_utils_osx.h" -#include "gears/base/safari/scoped_cf.h" -#include "third_party/scoped_ptr/scoped_ptr.h" // For scoped_array -#endif - -std::string16 MacAddressAsString16(const uint8 mac_as_int[6]) { +string16 MacAddressAsString16(const uint8 mac_as_int[6]) { // mac_as_int is big-endian. Write in byte chunks. // Format is XX-XX-XX-XX-XX-XX. - static const char16 *kMacFormatString = - STRING16(L"%02x-%02x-%02x-%02x-%02x-%02x"); -#ifdef OS_MACOSX - scoped_cftype<CFStringRef> format_string(CFStringCreateWithCharacters( - kCFAllocatorDefault, - kMacFormatString, - std::char_traits<char16>::length(kMacFormatString))); - scoped_cftype<CFStringRef> mac_string(CFStringCreateWithFormat( - kCFAllocatorDefault, - NULL, // not implemented - format_string.get(), - mac_as_int[0], mac_as_int[1], mac_as_int[2], - mac_as_int[3], mac_as_int[4], mac_as_int[5])); - std::string16 mac; - CFStringRefToString16(mac_string.get(), &mac); - return mac; -#else - char16 mac[18]; -#ifdef DEBUG - int num_characters = -#endif - wsprintf(mac, kMacFormatString, - mac_as_int[0], mac_as_int[1], mac_as_int[2], - mac_as_int[3], mac_as_int[4], mac_as_int[5]); - assert(num_characters == 17); - return mac; -#endif -} - -#endif // WIN32 || OS_MACOSX - -#if defined(WIN32) || defined(OS_MACOSX) || defined(LINUX) - -// These constants are defined for each platfrom in wifi_data_provider_xxx.cc. -extern const int kDefaultPollingInterval; -extern const int kNoChangePollingInterval; -extern const int kTwoNoChangePollingInterval; - -int UpdatePollingInterval(int polling_interval, bool scan_results_differ) { - if (scan_results_differ) { - return kDefaultPollingInterval; - } - if (polling_interval == kDefaultPollingInterval) { - return kNoChangePollingInterval; - } else { - assert(polling_interval == kNoChangePollingInterval || - polling_interval == kTwoNoChangePollingInterval); - return kTwoNoChangePollingInterval; - } + static const wchar_t* const kMacFormatString = + L"%02x-%02x-%02x-%02x-%02x-%02x"; + return WideToUTF16(StringPrintf(kMacFormatString, + mac_as_int[0], mac_as_int[1], mac_as_int[2], + mac_as_int[3], mac_as_int[4], mac_as_int[5])); } - -#endif // WIN32 || OS_MACOSX || LINUX diff --git a/chrome/browser/geolocation/wifi_data_provider_common.h b/chrome/browser/geolocation/wifi_data_provider_common.h index a8074b9..f8b9a41 100644 --- a/chrome/browser/geolocation/wifi_data_provider_common.h +++ b/chrome/browser/geolocation/wifi_data_provider_common.h @@ -1,39 +1,52 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_H__ -#define GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_H__ - -#include "gears/base/common/string16.h" -#include "gears/base/common/basictypes.h" +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_H_ +#define CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_H_ + +#include <assert.h> + +#include "base/string16.h" +#include "base/basictypes.h" // Converts a MAC address stored as an array of uint8 to a string. -std::string16 MacAddressAsString16(const uint8 mac_as_int[6]); +string16 MacAddressAsString16(const uint8 mac_as_int[6]); + +// Allows sharing and mocking of the update polling policy function. +class PollingPolicyInterface { + public: + virtual ~PollingPolicyInterface() {} + // Calculates the new polling interval for wiFi scans, given the previous + // interval and whether the last scan produced new results. + virtual void UpdatePollingInterval(bool scan_results_differ) = 0; + virtual int PollingInterval() = 0; +}; + +// Generic polling policy, constants are compile-time parameterized to allow +// tuning on a per-platform basis. +template<int DEFAULT_INTERVAL, + int NO_CHANGE_INTERVAL, + int TWO_NO_CHANGE_INTERVAL> +class GenericPollingPolicy : public PollingPolicyInterface { + public: + GenericPollingPolicy() : polling_interval_(DEFAULT_INTERVAL) {} + // PollingPolicyInterface + virtual void UpdatePollingInterval(bool scan_results_differ) { + if (scan_results_differ) { + polling_interval_ = DEFAULT_INTERVAL; + } else if (polling_interval_ == DEFAULT_INTERVAL) { + polling_interval_ = NO_CHANGE_INTERVAL; + } else { + assert(polling_interval_ == NO_CHANGE_INTERVAL || + polling_interval_ == TWO_NO_CHANGE_INTERVAL); + polling_interval_ = TWO_NO_CHANGE_INTERVAL; + } + } + virtual int PollingInterval() { return polling_interval_; } -// Calculates the new polling interval for wiFi scans, given the previous -// interval and whether the last scan produced new results. -int UpdatePollingInterval(int polling_interval, bool scan_results_differ); + private: + int polling_interval_; +}; -#endif // GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_H__ +#endif // CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_H_ diff --git a/chrome/browser/geolocation/wifi_data_provider_common_win.cc b/chrome/browser/geolocation/wifi_data_provider_common_win.cc new file mode 100644 index 0000000..211cbcd --- /dev/null +++ b/chrome/browser/geolocation/wifi_data_provider_common_win.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/geolocation/wifi_data_provider_common_win.h" + +#include <assert.h> + +#include "base/utf_string_conversions.h" +#include "chrome/browser/geolocation/device_data_provider.h" +#include "chrome/browser/geolocation/wifi_data_provider_common.h" + +bool ConvertToAccessPointData(const NDIS_WLAN_BSSID& data, + AccessPointData *access_point_data) { + // Currently we get only MAC address, signal strength and SSID. + // TODO(steveblock): Work out how to get age, channel and signal-to-noise. + assert(access_point_data); + access_point_data->mac_address = MacAddressAsString16(data.MacAddress); + access_point_data->radio_signal_strength = data.Rssi; + // Note that _NDIS_802_11_SSID::Ssid::Ssid is not null-terminated. + UTF8ToUTF16(reinterpret_cast<const char*>(data.Ssid.Ssid), + data.Ssid.SsidLength, + &access_point_data->ssid); + return true; +} + +int GetDataFromBssIdList(const NDIS_802_11_BSSID_LIST& bss_id_list, + int list_size, + WifiData::AccessPointDataSet* data) { + // Walk through the BSS IDs. + int found = 0; + const uint8 *iterator = reinterpret_cast<const uint8*>(&bss_id_list.Bssid[0]); + const uint8 *end_of_buffer = + reinterpret_cast<const uint8*>(&bss_id_list) + list_size; + for (int i = 0; i < static_cast<int>(bss_id_list.NumberOfItems); ++i) { + const NDIS_WLAN_BSSID *bss_id = + reinterpret_cast<const NDIS_WLAN_BSSID*>(iterator); + // Check that the length of this BSS ID is reasonable. + if (bss_id->Length < sizeof(NDIS_WLAN_BSSID) || + iterator + bss_id->Length > end_of_buffer) { + break; + } + AccessPointData access_point_data; + if (ConvertToAccessPointData(*bss_id, &access_point_data)) { + data->insert(access_point_data); + ++found; + } + // Move to the next BSS ID. + iterator += bss_id->Length; + } + return found; +} diff --git a/chrome/browser/geolocation/wifi_data_provider_common_win.h b/chrome/browser/geolocation/wifi_data_provider_common_win.h new file mode 100644 index 0000000..15a0740 --- /dev/null +++ b/chrome/browser/geolocation/wifi_data_provider_common_win.h @@ -0,0 +1,20 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_WIN_H_ +#define CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_WIN_H_ + +#include <windows.h> +#include <ntddndis.h> +#include <vector> +#include "chrome/browser/geolocation/device_data_provider.h" + +// Extracts access point data from the NDIS_802_11_BSSID_LIST structure and +// appends it to the data vector. Returns the number of access points for which +// data was extracted. +int GetDataFromBssIdList(const NDIS_802_11_BSSID_LIST& bss_id_list, + int list_size, + WifiData::AccessPointDataSet* data); + +#endif // CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_COMMON_WIN_H_ diff --git a/chrome/browser/geolocation/wifi_data_provider_linux.cc b/chrome/browser/geolocation/wifi_data_provider_linux.cc index fd95a2c..0ccff5f 100644 --- a/chrome/browser/geolocation/wifi_data_provider_linux.cc +++ b/chrome/browser/geolocation/wifi_data_provider_linux.cc @@ -1,28 +1,7 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // WiFi card drivers for Linux implement the Wireless Extensions interface. // This interface is part of the Linux kernel. // @@ -65,9 +44,8 @@ // TODO(steveblock): Investigate the possibility of the author of Wireless Tools // releasing libiw under a Gears-compatible license. -// TODO(cprince): remove platform-specific #ifdef guards when OS-specific -// sources (e.g. WIN32_CPPSRCS) are implemented -#if defined(LINUX) && !defined(OS_MACOSX) +// TODO(joth): port to chromium +#if 0 #include "gears/geolocation/wifi_data_provider_linux.h" @@ -276,4 +254,4 @@ static bool GetAccessPointData(WifiData::AccessPointDataSet *access_points) { access_points); } -#endif // LINUX && !OS_MACOSX +#endif // 0 diff --git a/chrome/browser/geolocation/wifi_data_provider_linux.h b/chrome/browser/geolocation/wifi_data_provider_linux.h index f635246..31db8fc 100644 --- a/chrome/browser/geolocation/wifi_data_provider_linux.h +++ b/chrome/browser/geolocation/wifi_data_provider_linux.h @@ -1,30 +1,12 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_LINUX_H__ -#define GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_LINUX_H__ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_LINUX_H_ +#define CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_LINUX_H_ + +// TODO(joth): port to chromium +#if 0 #include "gears/base/common/common.h" #include "gears/base/common/event.h" @@ -53,7 +35,9 @@ class LinuxWifiDataProvider // Whether we've successfully completed a scan for WiFi data. bool is_first_scan_complete_; - DISALLOW_EVIL_CONSTRUCTORS(LinuxWifiDataProvider); + DISALLOW_COPY_AND_ASSIGN(LinuxWifiDataProvider); }; -#endif // GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_LINUX_H__ +#endif // 0 + +#endif // CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_LINUX_H_ diff --git a/chrome/browser/geolocation/wifi_data_provider_osx.cc b/chrome/browser/geolocation/wifi_data_provider_mac.cc index 8dfa15d..f2692dd 100644 --- a/chrome/browser/geolocation/wifi_data_provider_osx.cc +++ b/chrome/browser/geolocation/wifi_data_provider_mac.cc @@ -1,36 +1,14 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // We use the OSX system API function WirelessScanSplit. This function is not // documented or included in the SDK, so we use a reverse-engineered header, // osx_wifi_.h. This file is taken from the iStumbler project // (http://www.istumbler.net). -// TODO(cprince): remove platform-specific #ifdef guards when OS-specific -// sources (e.g. WIN32_CPPSRCS) are implemented -#ifdef OS_MACOSX +// TODO(joth): port to chromium +#if 0 #include "gears/geolocation/wifi_data_provider_osx.h" @@ -88,7 +66,7 @@ void OsxWifiDataProvider::Run() { assert(WirelessAttach_function_ && WirelessScanSplit_function_ && WirelessDetach_function_); - + if ((*WirelessAttach_function_)(&wifi_context_, 0) != noErr) { is_first_scan_complete_ = true; return; @@ -129,7 +107,7 @@ void OsxWifiDataProvider::GetAccessPointData( 0) != noErr) { return; } - + if (managed_access_points == NULL) { return; } @@ -141,7 +119,7 @@ void OsxWifiDataProvider::GetAccessPointData( CFDataGetBytePtr( reinterpret_cast<const CFDataRef>( CFArrayGetValueAtIndex(managed_access_points, i)))); - + // Currently we get only MAC address, signal strength, channel // signal-to-noise and SSID // TODO(steveblock): Work out how to get age. @@ -154,7 +132,7 @@ void OsxWifiDataProvider::GetAccessPointData( // WirelessNetworkInfo::noise appears to be noise floor in dBm. access_point_data.signal_to_noise = access_point_info->signal - access_point_info->noise; - std::string16 ssid; + string16 ssid; if (UTF8ToString16(reinterpret_cast<const char*>(access_point_info->name), access_point_info->nameLen, &ssid)) { @@ -165,4 +143,4 @@ void OsxWifiDataProvider::GetAccessPointData( } } -#endif // OS_MACOSX +#endif // 0 diff --git a/chrome/browser/geolocation/wifi_data_provider_mac.h b/chrome/browser/geolocation/wifi_data_provider_mac.h new file mode 100644 index 0000000..10b8aa9 --- /dev/null +++ b/chrome/browser/geolocation/wifi_data_provider_mac.h @@ -0,0 +1,55 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_MAC_H_ +#define CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_MAC_H_ + +// TODO(joth): port to chromium +#if 0 + +#include "gears/base/common/common.h" +#include "gears/base/common/event.h" +#include "gears/base/common/mutex.h" +#include "gears/base/common/thread.h" +#include "gears/geolocation/device_data_provider.h" +#include "gears/geolocation/osx_wifi.h" + +class OsxWifiDataProvider + : public WifiDataProviderImplBase, + public Thread { + public: + OsxWifiDataProvider(); + virtual ~OsxWifiDataProvider(); + + // WifiDataProviderImplBase implementation. + virtual bool GetData(WifiData *data); + + private: + // Thread implementation. + virtual void Run(); + + void GetAccessPointData(WifiData::AccessPointDataSet *access_points); + + // Context and function pointers for Apple80211 library. + WirelessContextPtr wifi_context_; + WirelessAttachFunction WirelessAttach_function_; + WirelessScanSplitFunction WirelessScanSplit_function_; + WirelessDetachFunction WirelessDetach_function_; + + WifiData wifi_data_; + Mutex data_mutex_; + + // Event signalled to shut down the thread that polls for wifi data. + Event stop_event_; + + // Whether we've successfully completed a scan for WiFi data (or the polling + // thread has terminated early). + bool is_first_scan_complete_; + + DISALLOW_COPY_AND_ASSIGN(OsxWifiDataProvider); +}; + +#endif // 0 + +#endif // CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_MAC_H_ diff --git a/chrome/browser/geolocation/wifi_data_provider_osx.h b/chrome/browser/geolocation/wifi_data_provider_osx.h deleted file mode 100644 index 69fc7828..0000000 --- a/chrome/browser/geolocation/wifi_data_provider_osx.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_OSX_H__ -#define GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_OSX_H__ - -#include "gears/base/common/common.h" -#include "gears/base/common/event.h" -#include "gears/base/common/mutex.h" -#include "gears/base/common/thread.h" -#include "gears/geolocation/device_data_provider.h" -#include "gears/geolocation/osx_wifi.h" - -class OsxWifiDataProvider - : public WifiDataProviderImplBase, - public Thread { - public: - OsxWifiDataProvider(); - virtual ~OsxWifiDataProvider(); - - // WifiDataProviderImplBase implementation. - virtual bool GetData(WifiData *data); - - private: - // Thread implementation. - virtual void Run(); - - void GetAccessPointData(WifiData::AccessPointDataSet *access_points); - - // Context and function pointers for Apple80211 library. - WirelessContextPtr wifi_context_; - WirelessAttachFunction WirelessAttach_function_; - WirelessScanSplitFunction WirelessScanSplit_function_; - WirelessDetachFunction WirelessDetach_function_; - - WifiData wifi_data_; - Mutex data_mutex_; - - // Event signalled to shut down the thread that polls for wifi data. - Event stop_event_; - - // Whether we've successfully completed a scan for WiFi data (or the polling - // thread has terminated early). - bool is_first_scan_complete_; - - DISALLOW_EVIL_CONSTRUCTORS(OsxWifiDataProvider); -}; - -#endif // GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_OSX_H__ diff --git a/chrome/browser/geolocation/wifi_data_provider_unittest_win.cc b/chrome/browser/geolocation/wifi_data_provider_unittest_win.cc new file mode 100644 index 0000000..b5dc608 --- /dev/null +++ b/chrome/browser/geolocation/wifi_data_provider_unittest_win.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/geolocation/wifi_data_provider_win.h" + +#include <vector> + +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "chrome/browser/geolocation/wifi_data_provider_common.h" +#include "chrome/test/ui_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +class MockWlanApi : public Win32WifiDataProvider::WlanApiInterface { + public: + MockWlanApi() : calls_(0), bool_return_(true) { + } + virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) { + ++calls_; + *data = data_out_; + return bool_return_; + } + int calls_; + bool bool_return_; + WifiData::AccessPointDataSet data_out_; +}; + +class MockPollingPolicy : public PollingPolicyInterface { + public: + virtual void UpdatePollingInterval(bool scan_results_differ) { + results_differed_.push_back(scan_results_differ); + } + virtual int PollingInterval() { return 1; } + std::vector<bool> results_differed_; +}; + +// Stops the specified (nested) message loop when the listener is called back. +class MessageLoopQuitListener + : public Win32WifiDataProvider::ListenerInterface { + public: + explicit MessageLoopQuitListener(MessageLoop* message_loop) + : message_loop_to_quit_(message_loop) { + assert(message_loop_to_quit_ != NULL); + } + // ListenerInterface + virtual void DeviceDataUpdateAvailable( + DeviceDataProvider<WifiData>* provider) { + // We expect the callback to come from the provider's internal worker + // thread. This is not a strict requirement, just a lot of the complexity + // here is predicated on the need to cope with this scenario! + EXPECT_NE(MessageLoop::current(), message_loop_to_quit_); + provider_ = provider; + // Can't call Quit() directly on another thread's message loop. + message_loop_to_quit_->PostTask(FROM_HERE, new MessageLoop::QuitTask); + } + MessageLoop* message_loop_to_quit_; + DeviceDataProvider<WifiData>* provider_; +}; + +// Main test fixture +class Win32WifiDataProviderTest : public testing::Test { + public: + static Win32WifiDataProvider* CreateWin32WifiDataProvider( + MockWlanApi** wlan_api_out) { + Win32WifiDataProvider* provider = new Win32WifiDataProvider; + *wlan_api_out = new MockWlanApi; + provider->inject_mock_wlan_api(*wlan_api_out); // Takes ownership. + provider->inject_mock_polling_policy(new MockPollingPolicy); // ditto + return provider; + } + virtual void SetUp() { + provider_.reset(CreateWin32WifiDataProvider(&wlan_api_)); + } + virtual void TearDown() { + provider_.reset(NULL); + } + + protected: + MessageLoop main_message_loop_; + scoped_ptr<Win32WifiDataProvider> provider_; + MockWlanApi* wlan_api_; +}; + +WifiDataProviderImplBase* CreateWin32WifiDataProviderStatic() { + MockWlanApi* wlan_api; + return Win32WifiDataProviderTest::CreateWin32WifiDataProvider(&wlan_api); +} +} // namespace + +TEST_F(Win32WifiDataProviderTest, CreateDestroy) { + // Test fixture members were SetUp correctly. + EXPECT_EQ(&main_message_loop_, MessageLoop::current()); + EXPECT_TRUE(NULL != provider_.get()); + EXPECT_TRUE(NULL != wlan_api_); +} + +TEST_F(Win32WifiDataProviderTest, StartThread) { + EXPECT_TRUE(provider_->StartDataProvider()); + provider_.reset(NULL); // Stop()s the thread. + SUCCEED(); +} + +TEST_F(Win32WifiDataProviderTest, DoAnEmptyScan) { + MessageLoopQuitListener quit_listener(&main_message_loop_); + provider_->AddListener(&quit_listener); + EXPECT_TRUE(provider_->StartDataProvider()); + main_message_loop_.Run(); + EXPECT_EQ(1, wlan_api_->calls_); + WifiData data; + EXPECT_TRUE(provider_->GetData(&data)); + EXPECT_EQ(0, data.access_point_data.size()); +} + +TEST_F(Win32WifiDataProviderTest, DoScanWithResults) { + MessageLoopQuitListener quit_listener(&main_message_loop_); + provider_->AddListener(&quit_listener); + AccessPointData single_access_point; + single_access_point.age = 1; + single_access_point.channel = 2; + single_access_point.mac_address = 3; + single_access_point.radio_signal_strength = 4; + single_access_point.signal_to_noise = 5; + single_access_point.ssid = L"foossid"; + wlan_api_->data_out_.insert(single_access_point); + + EXPECT_TRUE(provider_->StartDataProvider()); + main_message_loop_.Run(); + EXPECT_EQ(1, wlan_api_->calls_); + WifiData data; + EXPECT_TRUE(provider_->GetData(&data)); + EXPECT_EQ(1, data.access_point_data.size()); + EXPECT_EQ(single_access_point.age, data.access_point_data.begin()->age); + EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid); +} + +TEST_F(Win32WifiDataProviderTest, StartThreadViaDeviceDataProvider) { + MessageLoopQuitListener quit_listener(&main_message_loop_); + DeviceDataProvider<WifiData>::SetFactory(CreateWin32WifiDataProviderStatic); + DeviceDataProvider<WifiData>::Register(&quit_listener); + main_message_loop_.Run(); + DeviceDataProvider<WifiData>::Unregister(&quit_listener); + DeviceDataProvider<WifiData>::ResetFactory(); +} diff --git a/chrome/browser/geolocation/wifi_data_provider_win.cc b/chrome/browser/geolocation/wifi_data_provider_win.cc index 1e42105..e7d52e2 100644 --- a/chrome/browser/geolocation/wifi_data_provider_win.cc +++ b/chrome/browser/geolocation/wifi_data_provider_win.cc @@ -1,28 +1,7 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // Windows Vista uses the Native Wifi (WLAN) API for accessing WiFi cards. See // http://msdn.microsoft.com/en-us/library/ms705945(VS.85).aspx. Windows XP // Service Pack 3 (and Windows XP Service Pack 2, if upgraded with a hot fix) @@ -33,7 +12,7 @@ // // Windows XP from Service Pack 2 onwards supports the Wireless Zero // Configuration (WZC) programming interface. See -// http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx. +// http://msdn.microsoft.com/en-us/library/ms706587(VS.85).aspx. // // The MSDN recommends that one use the WLAN API where available, and WZC // otherwise. @@ -42,75 +21,180 @@ // not to work on XP SP3. So we use WLAN on Vista, and use NDIS directly // otherwise. -// TODO(cprince): remove platform-specific #ifdef guards when OS-specific -// sources (e.g. WIN32_CPPSRCS) are implemented -#if defined(WIN32) && !defined(OS_WINCE) - -#include "gears/geolocation/wifi_data_provider_win32.h" +#include "chrome/browser/geolocation/wifi_data_provider_win.h" #include <windows.h> -#include <ntddndis.h> // For IOCTL_NDIS_QUERY_GLOBAL_STATS -#include "gears/base/common/string_utils.h" -#include "gears/base/common/vista_utils.h" -#include "gears/geolocation/wifi_data_provider_common.h" -#include "gears/geolocation/wifi_data_provider_windows_common.h" +#include <winioctl.h> +#include <wlanapi.h> +#include "base/utf_string_conversions.h" +#include "chrome/browser/geolocation/wifi_data_provider_common.h" +#include "chrome/browser/geolocation/wifi_data_provider_common_win.h" + +#ifdef _MSC_VER +#pragma warning(disable:4355) // 'this' : used in base member initializer list +#endif // Taken from ndis.h for WinCE. #define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L) #define NDIS_STATUS_BUFFER_TOO_SHORT ((NDIS_STATUS)0xC0010016L) +namespace { // The limits on the size of the buffer used for the OID query. -static const int kInitialBufferSize = 2 << 12; // Good for about 50 APs. -static const int kMaximumBufferSize = 2 << 20; // 2MB +const int kInitialBufferSize = 2 << 12; // Good for about 50 APs. +const int kMaximumBufferSize = 2 << 20; // 2MB // Length for generic string buffers passed to Win32 APIs. -static const int kStringLength = 512; +const int kStringLength = 512; // The time periods, in milliseconds, between successive polls of the wifi data. -extern const int kDefaultPollingInterval = 10000; // 10s -extern const int kNoChangePollingInterval = 120000; // 2 mins -extern const int kTwoNoChangePollingInterval = 600000; // 10 mins - -// Local functions +const int kDefaultPollingInterval = 10000; // 10s +const int kNoChangePollingInterval = 120000; // 2 mins +const int kTwoNoChangePollingInterval = 600000; // 10 mins + +// WlanOpenHandle +typedef DWORD (WINAPI *WlanOpenHandleFunction)(DWORD dwClientVersion, + PVOID pReserved, + PDWORD pdwNegotiatedVersion, + PHANDLE phClientHandle); + +// WlanEnumInterfaces +typedef DWORD (WINAPI *WlanEnumInterfacesFunction)( + HANDLE hClientHandle, + PVOID pReserved, + PWLAN_INTERFACE_INFO_LIST *ppInterfaceList); + +// WlanGetNetworkBssList +typedef DWORD (WINAPI *WlanGetNetworkBssListFunction)( + HANDLE hClientHandle, + const GUID *pInterfaceGuid, + const PDOT11_SSID pDot11Ssid, + DOT11_BSS_TYPE dot11BssType, + BOOL bSecurityEnabled, + PVOID pReserved, + PWLAN_BSS_LIST *ppWlanBssList +); + +// WlanFreeMemory +typedef VOID (WINAPI *WlanFreeMemoryFunction)(PVOID pMemory); + +// WlanCloseHandle +typedef DWORD (WINAPI *WlanCloseHandleFunction)(HANDLE hClientHandle, + PVOID pReserved); + + +// Local classes and functions +class WindowsWlanApi : public Win32WifiDataProvider::WlanApiInterface { + public: + ~WindowsWlanApi(); + // Factory function. Will return NULL if this API is unavailable. + static WindowsWlanApi* Create(); + + // WlanApiInterface + virtual bool GetAccessPointData(WifiData::AccessPointDataSet *data); + + private: + // Takes ownership of the library handle. + explicit WindowsWlanApi(HINSTANCE library); + + // Loads the required functions from the DLL. + void GetWLANFunctions(HINSTANCE wlan_library); + int GetInterfaceDataWLAN(HANDLE wlan_handle, + const GUID &interface_id, + WifiData::AccessPointDataSet *data); + + // Handle to the wlanapi.dll library. + HINSTANCE library_; + + // Function pointers for WLAN + WlanOpenHandleFunction WlanOpenHandle_function_; + WlanEnumInterfacesFunction WlanEnumInterfaces_function_; + WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_; + WlanFreeMemoryFunction WlanFreeMemory_function_; + WlanCloseHandleFunction WlanCloseHandle_function_; +}; + +class WindowsNdisApi : public Win32WifiDataProvider::WlanApiInterface { + public: + ~WindowsNdisApi(); + static WindowsNdisApi* Create(); + + // WlanApiInterface + virtual bool GetAccessPointData(WifiData::AccessPointDataSet *data); + + private: + static bool GetInterfacesNDIS( + std::vector<string16>* interface_service_names_out); + + // Swaps in content of the vector passed + explicit WindowsNdisApi(std::vector<string16>* interface_service_names); + + bool GetInterfaceDataNDIS(HANDLE adapter_handle, + WifiData::AccessPointDataSet *data); + // NDIS variables. + std::vector<string16> interface_service_names_; + + // Remembers scan result buffer size across calls. + int oid_buffer_size_; +}; + + +// TODO(joth): Share with the N other copies of this method. +bool IsRunningOnVistaOrNewer(); // Extracts data for an access point and converts to Gears format. -static bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry, - AccessPointData *access_point_data); -bool UndefineDosDevice(const std::string16 &device_name); -bool DefineDosDeviceIfNotExists(const std::string16 &device_name); -HANDLE GetFileHandle(const std::string16 &device_name); +bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry, + AccessPointData *access_point_data); +bool UndefineDosDevice(const string16 &device_name); +bool DefineDosDeviceIfNotExists(const string16 &device_name); +HANDLE GetFileHandle(const string16 &device_name); // Makes the OID query and returns a Win32 error code. int PerformQuery(HANDLE adapter_handle, BYTE *buffer, DWORD buffer_size, DWORD *bytes_out); -bool ResizeBuffer(int requested_size, BYTE **buffer); +bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer); // Gets the system directory and appends a trailing slash if not already // present. -bool GetSystemDirectory(std::string16 *path); +bool GetSystemDirectory(string16 *path); +} // namespace -// static template<> WifiDataProviderImplBase *WifiDataProvider::DefaultFactoryFunction() { return new Win32WifiDataProvider(); } - Win32WifiDataProvider::Win32WifiDataProvider() - : oid_buffer_size_(kInitialBufferSize), - is_first_scan_complete_(false) { - // Start the polling thread. - Start(); + : Thread(__FILE__), + is_first_scan_complete_(false), + task_factory_(this) { } Win32WifiDataProvider::~Win32WifiDataProvider() { - stop_event_.Signal(); - Join(); + // Base class auto-stops the thread, however we need to do it here so our + // override of CleanUp still exists whilst the thread is shutting down. + Stop(); +} + +void Win32WifiDataProvider::inject_mock_wlan_api(WlanApiInterface* wlan_api) { + assert(wlan_api_ == NULL); + assert(wlan_api); + wlan_api_.reset(wlan_api); +} + +void Win32WifiDataProvider::inject_mock_polling_policy( + PollingPolicyInterface* policy) { + assert(polling_policy_ == NULL); + assert(policy); + polling_policy_.reset(policy); +} + +bool Win32WifiDataProvider::StartDataProvider() { + return base::Thread::Start(); } bool Win32WifiDataProvider::GetData(WifiData *data) { assert(data); - MutexLock lock(&data_mutex_); + AutoLock lock(data_mutex_); *data = wifi_data_; // If we've successfully completed a scan, indicate that we have all of the // data we can get. @@ -118,63 +202,94 @@ bool Win32WifiDataProvider::GetData(WifiData *data) { } // Thread implementation -void Win32WifiDataProvider::Run() { - // We use an absolute path to load the DLL to avoid DLL preloading attacks. - HINSTANCE library = NULL; - std::string16 system_directory; - if (GetSystemDirectory(&system_directory)) { - assert(!system_directory.empty()); - std::string16 dll_path = system_directory + L"wlanapi.dll"; - library = LoadLibraryEx(dll_path.c_str(), - NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); - } - +void Win32WifiDataProvider::Init() { // Use the WLAN interface if we're on Vista and if it's available. Otherwise, // use NDIS. - typedef bool (Win32WifiDataProvider::*GetAccessPointDataFunction)( - WifiData::AccessPointDataSet *data); - GetAccessPointDataFunction get_access_point_data_function = NULL; - if (VistaUtils::IsRunningOnVista() && library) { - GetWLANFunctions(library); - get_access_point_data_function = - &Win32WifiDataProvider::GetAccessPointDataWLAN; - } else { - // We assume the list of interfaces doesn't change while Gears is running. - if (!GetInterfacesNDIS()) { + if (wlan_api_ == NULL) { + wlan_api_.reset(WindowsWlanApi::Create()); + } + if (wlan_api_ == NULL) { + wlan_api_.reset(WindowsNdisApi::Create()); + } + if (wlan_api_ == NULL) { + // Error! Can't do scans, so don't try and schedule one. + is_first_scan_complete_ = true; + return; + } + + if (polling_policy_ == NULL) { + polling_policy_.reset( + new GenericPollingPolicy<kDefaultPollingInterval, + kNoChangePollingInterval, + kTwoNoChangePollingInterval>); + } + assert(polling_policy_ != NULL); + + ScheduleNextScan(); +} + +void Win32WifiDataProvider::CleanUp() { + // Destroy the wlan api instance in the thread in which it was created. + wlan_api_.reset(NULL); +} + +void Win32WifiDataProvider::DoWifiScanTask() { + WifiData new_data; + if (wlan_api_->GetAccessPointData(&new_data.access_point_data)) { + bool update_available; + data_mutex_.Acquire(); + update_available = wifi_data_.DiffersSignificantly(new_data); + wifi_data_ = new_data; + data_mutex_.Release(); + polling_policy_->UpdatePollingInterval(update_available); + if (update_available) { is_first_scan_complete_ = true; - return; + NotifyListeners(); } - get_access_point_data_function = - &Win32WifiDataProvider::GetAccessPointDataNDIS; } - assert(get_access_point_data_function); - - int polling_interval = kDefaultPollingInterval; - // Regularly get the access point data. - do { - WifiData new_data; - if ((this->*get_access_point_data_function)(&new_data.access_point_data)) { - bool update_available; - data_mutex_.Lock(); - update_available = wifi_data_.DiffersSignificantly(new_data); - wifi_data_ = new_data; - data_mutex_.Unlock(); - polling_interval = - UpdatePollingInterval(polling_interval, update_available); - if (update_available) { - is_first_scan_complete_ = true; - NotifyListeners(); - } - } - } while (!stop_event_.WaitWithTimeout(polling_interval)); + ScheduleNextScan(); +} + +void Win32WifiDataProvider::ScheduleNextScan() { + message_loop()->PostDelayedTask(FROM_HERE, + task_factory_.NewRunnableMethod(&Win32WifiDataProvider::DoWifiScanTask), + polling_policy_->PollingInterval()); +} + +// Local classes and functions +namespace { - FreeLibrary(library); +// WindowsWlanApi +WindowsWlanApi::WindowsWlanApi(HINSTANCE library) + : library_(library) { + GetWLANFunctions(library_); } -// WLAN functions +WindowsWlanApi::~WindowsWlanApi() { + FreeLibrary(library_); +} + +WindowsWlanApi* WindowsWlanApi::Create() { + // We use an absolute path to load the DLL to avoid DLL preloading attacks. + string16 system_directory; + if (!IsRunningOnVistaOrNewer()) { + return NULL; + } + if (!GetSystemDirectory(&system_directory)) { + return NULL; + } + assert(!system_directory.empty()); + string16 dll_path = system_directory + L"wlanapi.dll"; + HINSTANCE library = LoadLibraryEx(dll_path.c_str(), + NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); + if (!library) { + return NULL; + } + return new WindowsWlanApi(library); +} -void Win32WifiDataProvider::GetWLANFunctions(HINSTANCE wlan_library) { +void WindowsWlanApi::GetWLANFunctions(HINSTANCE wlan_library) { assert(wlan_library); WlanOpenHandle_function_ = reinterpret_cast<WlanOpenHandleFunction>( GetProcAddress(wlan_library, "WlanOpenHandle")); @@ -194,7 +309,7 @@ void Win32WifiDataProvider::GetWLANFunctions(HINSTANCE wlan_library) { WlanCloseHandle_function_); } -bool Win32WifiDataProvider::GetAccessPointDataWLAN( +bool WindowsWlanApi::GetAccessPointData( WifiData::AccessPointDataSet *data) { assert(data); @@ -241,7 +356,7 @@ bool Win32WifiDataProvider::GetAccessPointDataWLAN( // Appends the data for a single interface to the data vector. Returns the // number of access points found, or -1 on error. -int Win32WifiDataProvider::GetInterfaceDataWLAN( +int WindowsWlanApi::GetInterfaceDataWLAN( const HANDLE wlan_handle, const GUID &interface_id, WifiData::AccessPointDataSet *data) { @@ -251,7 +366,7 @@ int Win32WifiDataProvider::GetInterfaceDataWLAN( if ((*WlanGetNetworkBssList_function_)(wlan_handle, &interface_id, NULL, // Use all SSIDs. - DOT11_BSS_TYPE_UNUSED, + dot11_BSS_type_any, false, // bSecurityEnabled - unused NULL, // reserved &bss_list) != ERROR_SUCCESS) { @@ -272,9 +387,62 @@ int Win32WifiDataProvider::GetInterfaceDataWLAN( return found; } -// NDIS functions +// WindowsNdisApi +WindowsNdisApi::WindowsNdisApi( + std::vector<string16>* interface_service_names) + : oid_buffer_size_(kInitialBufferSize) { + assert(!interface_service_names->empty()); + interface_service_names_.swap(*interface_service_names); +} + +WindowsNdisApi::~WindowsNdisApi() { +} -bool Win32WifiDataProvider::GetInterfacesNDIS() { +WindowsNdisApi* WindowsNdisApi::Create() { + std::vector<string16> interface_service_names; + if (GetInterfacesNDIS(&interface_service_names)) { + return new WindowsNdisApi(&interface_service_names); + } + return NULL; +} + +bool WindowsNdisApi::GetAccessPointData(WifiData::AccessPointDataSet *data) { + assert(data); + int interfaces_failed = 0; + int interfaces_succeeded = 0; + + for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) { + // First, check that we have a DOS device for this adapter. + if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) { + continue; + } + + // Get the handle to the device. This will fail if the named device is not + // valid. + HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]); + if (adapter_handle == INVALID_HANDLE_VALUE) { + continue; + } + + // Get the data. + if (GetInterfaceDataNDIS(adapter_handle, data)) { + ++interfaces_succeeded; + } else { + ++interfaces_failed; + } + + // Clean up. + CloseHandle(adapter_handle); + UndefineDosDevice(interface_service_names_[i]); + } + + // Return true if at least one interface succeeded, or at the very least none + // failed. + return interfaces_succeeded > 0 || interfaces_failed == 0; +} + +bool WindowsNdisApi::GetInterfacesNDIS( + std::vector<string16>* interface_service_names_out) { HKEY network_cards_key = NULL; if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, @@ -316,7 +484,7 @@ bool Win32WifiDataProvider::GetInterfacesNDIS() { &type, reinterpret_cast<LPBYTE>(service_name), &service_name_size) == ERROR_SUCCESS) { - interface_service_names_.push_back(service_name); + interface_service_names_out->push_back(service_name); } RegCloseKey(hardware_key); } @@ -325,40 +493,13 @@ bool Win32WifiDataProvider::GetInterfacesNDIS() { return true; } -bool Win32WifiDataProvider::GetAccessPointDataNDIS( - WifiData::AccessPointDataSet *data) { - assert(data); - - for (int i = 0; i < static_cast<int>(interface_service_names_.size()); ++i) { - // First, check that we have a DOS device for this adapter. - if (!DefineDosDeviceIfNotExists(interface_service_names_[i])) { - continue; - } - // Get the handle to the device. This will fail if the named device is not - // valid. - HANDLE adapter_handle = GetFileHandle(interface_service_names_[i]); - if (adapter_handle == INVALID_HANDLE_VALUE) { - continue; - } - - // Get the data. - GetInterfaceDataNDIS(adapter_handle, data); - - // Clean up. - CloseHandle(adapter_handle); - UndefineDosDevice(interface_service_names_[i]); - } - - return true; -} - -bool Win32WifiDataProvider::GetInterfaceDataNDIS( - HANDLE adapter_handle, - WifiData::AccessPointDataSet *data) { +bool WindowsNdisApi::GetInterfaceDataNDIS(HANDLE adapter_handle, + WifiData::AccessPointDataSet *data) { assert(data); - BYTE *buffer = reinterpret_cast<BYTE*>(malloc(oid_buffer_size_)); + scoped_ptr_malloc<BYTE> buffer( + reinterpret_cast<BYTE*>(malloc(oid_buffer_size_))); if (buffer == NULL) { return false; } @@ -368,7 +509,8 @@ bool Win32WifiDataProvider::GetInterfaceDataNDIS( while (true) { bytes_out = 0; - result = PerformQuery(adapter_handle, buffer, oid_buffer_size_, &bytes_out); + result = PerformQuery(adapter_handle, buffer.get(), + oid_buffer_size_, &bytes_out); if (result == ERROR_GEN_FAILURE || // Returned by some Intel cards. result == ERROR_INSUFFICIENT_BUFFER || result == ERROR_MORE_DATA || @@ -390,49 +532,53 @@ bool Win32WifiDataProvider::GetInterfaceDataNDIS( break; } } - assert(buffer); + assert(buffer.get()); if (result == ERROR_SUCCESS) { NDIS_802_11_BSSID_LIST* bssid_list = - reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer); + reinterpret_cast<NDIS_802_11_BSSID_LIST*>(buffer.get()); GetDataFromBssIdList(*bssid_list, oid_buffer_size_, data); } - free(buffer); return true; } -// Local functions +bool IsRunningOnVistaOrNewer() { + OSVERSIONINFO info = {0}; + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&info); + return (info.dwMajorVersion >=6); +} -static bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry, +bool GetNetworkData(const WLAN_BSS_ENTRY &bss_entry, AccessPointData *access_point_data) { // Currently we get only MAC address, signal strength and SSID. assert(access_point_data); access_point_data->mac_address = MacAddressAsString16(bss_entry.dot11Bssid); access_point_data->radio_signal_strength = bss_entry.lRssi; // bss_entry.dot11Ssid.ucSSID is not null-terminated. - UTF8ToString16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID), - static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength), - &access_point_data->ssid); + UTF8ToUTF16(reinterpret_cast<const char*>(bss_entry.dot11Ssid.ucSSID), + static_cast<ULONG>(bss_entry.dot11Ssid.uSSIDLength), + &access_point_data->ssid); // TODO(steveblock): Is it possible to get the following? - //access_point_data->signal_to_noise - //access_point_data->age - //access_point_data->channel + // access_point_data->signal_to_noise + // access_point_data->age + // access_point_data->channel return true; } -bool UndefineDosDevice(const std::string16 &device_name) { +bool UndefineDosDevice(const string16 &device_name) { // We remove only the mapping we use, that is \Device\<device_name>. - std::string16 target_path = L"\\Device\\" + device_name; + string16 target_path = L"\\Device\\" + device_name; return DefineDosDevice( DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE, device_name.c_str(), target_path.c_str()) == TRUE; } -bool DefineDosDeviceIfNotExists(const std::string16 &device_name) { +bool DefineDosDeviceIfNotExists(const string16 &device_name) { // We create a DOS device name for the device at \Device\<device_name>. - std::string16 target_path = L"\\Device\\" + device_name; + string16 target_path = L"\\Device\\" + device_name; TCHAR target[kStringLength]; if (QueryDosDevice(device_name.c_str(), target, kStringLength) > 0 && @@ -456,10 +602,10 @@ bool DefineDosDeviceIfNotExists(const std::string16 &device_name) { target_path.compare(target) == 0; } -HANDLE GetFileHandle(const std::string16 &device_name) { +HANDLE GetFileHandle(const string16 &device_name) { // We access a device with DOS path \Device\<device_name> at // \\.\<device_name>. - std::string16 formatted_device_name = L"\\\\.\\" + device_name; + string16 formatted_device_name = L"\\\\.\\" + device_name; return CreateFile(formatted_device_name.c_str(), GENERIC_READ, @@ -488,35 +634,30 @@ int PerformQuery(HANDLE adapter_handle, return ERROR_SUCCESS; } -bool ResizeBuffer(int requested_size, BYTE **buffer) { +bool ResizeBuffer(int requested_size, scoped_ptr_malloc<BYTE>* buffer) { + assert(requested_size > 0); + assert(buffer); if (requested_size > kMaximumBufferSize) { - free(*buffer); - *buffer = NULL; - return false; - } - - BYTE *new_buffer = reinterpret_cast<BYTE*>(realloc(*buffer, requested_size)); - if (new_buffer == NULL) { - free(*buffer); - *buffer = NULL; + buffer->reset(NULL); return false; } - *buffer = new_buffer; - return true; + buffer->reset(reinterpret_cast<BYTE*>( + realloc(buffer->release(), requested_size))); + return buffer != NULL; } -bool GetSystemDirectory(std::string16 *path) { +bool GetSystemDirectory(string16 *path) { assert(path); // Return value includes terminating NULL. - int buffer_size = GetSystemDirectory(NULL, 0); + int buffer_size = ::GetSystemDirectory(NULL, 0); if (buffer_size == 0) { return false; } char16 *buffer = new char16[buffer_size]; // Return value excludes terminating NULL. - int characters_written = GetSystemDirectory(buffer, buffer_size); + int characters_written = ::GetSystemDirectory(buffer, buffer_size); if (characters_written == 0) { return false; } @@ -530,5 +671,4 @@ bool GetSystemDirectory(std::string16 *path) { } return true; } - -#endif // WIN32 && !OS_WINCE +} // namespace diff --git a/chrome/browser/geolocation/wifi_data_provider_win.h b/chrome/browser/geolocation/wifi_data_provider_win.h index 81b2274..d5f28d8 100644 --- a/chrome/browser/geolocation/wifi_data_provider_win.h +++ b/chrome/browser/geolocation/wifi_data_provider_win.h @@ -1,87 +1,71 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_WIN32_H__ -#define GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_WIN32_H__ - -#include <vector> -#include "gears/base/common/common.h" -#include "gears/base/common/thread.h" -#include "gears/geolocation/device_data_provider.h" -#include "gears/geolocation/wlanapi.h" +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_WIN_H_ +#define CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_WIN_H_ + +#include "base/task.h" +#include "base/thread.h" +#include "chrome/browser/geolocation/device_data_provider.h" + +class PollingPolicyInterface; class Win32WifiDataProvider : public WifiDataProviderImplBase, - public Thread { + private base::Thread { public: + // Interface to abstract the low level data OS library call, and to allow + // mocking (hence public). + class WlanApiInterface { + public: + virtual ~WlanApiInterface() {} + // Gets wifi data for all visible access points. + virtual bool GetAccessPointData(WifiData::AccessPointDataSet *data) = 0; + }; + Win32WifiDataProvider(); virtual ~Win32WifiDataProvider(); + // Takes ownership of wlan_api. Must be called before Start(). + void inject_mock_wlan_api(WlanApiInterface* wlan_api); + + // Takes ownership of polic. Must be called before Start(). + void inject_mock_polling_policy(PollingPolicyInterface* policy); + // WifiDataProviderImplBase implementation + virtual bool StartDataProvider(); virtual bool GetData(WifiData *data); private: // Thread implementation - virtual void Run(); - - // WLAN methods - // Loads the required functions from the DLL. - void GetWLANFunctions(HINSTANCE wlan_library); - // Gets wifi data for all visible access points. - bool GetAccessPointDataWLAN(WifiData::AccessPointDataSet *data); - int GetInterfaceDataWLAN(HANDLE wlan_handle, - const GUID &interface_id, - WifiData::AccessPointDataSet *data); - - // NDIS methods. - bool GetInterfacesNDIS(); - bool GetAccessPointDataNDIS(WifiData::AccessPointDataSet *data); - bool GetInterfaceDataNDIS(HANDLE adapter_handle, - WifiData::AccessPointDataSet *data); - - // Function pointers for WLAN - WlanOpenHandleFunction WlanOpenHandle_function_; - WlanEnumInterfacesFunction WlanEnumInterfaces_function_; - WlanGetNetworkBssListFunction WlanGetNetworkBssList_function_; - WlanFreeMemoryFunction WlanFreeMemory_function_; - WlanCloseHandleFunction WlanCloseHandle_function_; - - // NDIS variables. - std::vector<std::string16> interface_service_names_; - int oid_buffer_size_; + virtual void Init(); + // Called just after the message loop ends + virtual void CleanUp(); + + // Task which run in the child thread. + void DoWifiScanTask(); + + // Will schedule a scan; i.e. enqueue DoWifiScanTask deferred task. + void ScheduleNextScan(); WifiData wifi_data_; - Mutex data_mutex_; - // Events signalled to shut down the thread that polls for wifi data. - Event stop_event_; + Lock data_mutex_; // Whether we've successfully completed a scan for WiFi data (or the polling // thread has terminated early). bool is_first_scan_complete_; - DISALLOW_EVIL_CONSTRUCTORS(Win32WifiDataProvider); + // Underlying OS wifi API. + scoped_ptr<WlanApiInterface> wlan_api_; + + // Controls the polling update interval. + scoped_ptr<PollingPolicyInterface> polling_policy_; + + // Holder for the tasks which run on the thread; takes care of cleanup. + ScopedRunnableMethodFactory<Win32WifiDataProvider> task_factory_; + + DISALLOW_COPY_AND_ASSIGN(Win32WifiDataProvider); }; -#endif // GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_WIN32_H__ +#endif // CHROME_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_WIN_H_ diff --git a/chrome/browser/geolocation/wifi_data_provider_windows_common.cc b/chrome/browser/geolocation/wifi_data_provider_windows_common.cc deleted file mode 100644 index d367c90..0000000 --- a/chrome/browser/geolocation/wifi_data_provider_windows_common.cc +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#if defined(WIN32) || defined(OS_WINCE) - -#include "gears/geolocation/wifi_data_provider_windows_common.h" - -#include <assert.h> -#include "gears/base/common/string_utils.h" -#include "gears/geolocation/device_data_provider.h" -#include "gears/geolocation/wifi_data_provider_common.h" - -bool ConvertToGearsFormat(const NDIS_WLAN_BSSID &data, - AccessPointData *access_point_data) { - // Currently we get only MAC address, signal strength and SSID. - // TODO(steveblock): Work out how to get age, channel and signal-to-noise. - assert(access_point_data); - access_point_data->mac_address = MacAddressAsString16(data.MacAddress); - access_point_data->radio_signal_strength = data.Rssi; - // Note that _NDIS_802_11_SSID::Ssid::Ssid is not null-terminated. - UTF8ToString16(reinterpret_cast<const char*>(data.Ssid.Ssid), - data.Ssid.SsidLength, - &access_point_data->ssid); - return true; -} - -int GetDataFromBssIdList(const NDIS_802_11_BSSID_LIST &bss_id_list, - int list_size, - WifiData::AccessPointDataSet *data) { - // Walk through the BSS IDs. - int found = 0; - const uint8 *iterator = reinterpret_cast<const uint8*>(&bss_id_list.Bssid[0]); - const uint8 *end_of_buffer = - reinterpret_cast<const uint8*>(&bss_id_list) + list_size; - for (int i = 0; i < static_cast<int>(bss_id_list.NumberOfItems); ++i) { - const NDIS_WLAN_BSSID *bss_id = - reinterpret_cast<const NDIS_WLAN_BSSID*>(iterator); - // Check that the length of this BSS ID is reasonable. - if (bss_id->Length < sizeof(NDIS_WLAN_BSSID) || - iterator + bss_id->Length > end_of_buffer) { - break; - } - AccessPointData access_point_data; - if (ConvertToGearsFormat(*bss_id, &access_point_data)) { - data->insert(access_point_data); - ++found; - } - // Move to the next BSS ID. - iterator += bss_id->Length; - } - return found; -} - -#endif // WIN32 || OS_WINCE diff --git a/chrome/browser/geolocation/wifi_data_provider_windows_common.h b/chrome/browser/geolocation/wifi_data_provider_windows_common.h deleted file mode 100644 index e2e0873..0000000 --- a/chrome/browser/geolocation/wifi_data_provider_windows_common.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2008, Google Inc. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// 3. Neither the name of Google Inc. nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// This file contains functions which are common to both the WIN32 and WINCE -// implementations of the wifi data provider. - -#ifndef GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_WINDOWS_COMMON_H__ -#define GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_WINDOWS_COMMON_H__ - -#include <windows.h> -#include <ntddndis.h> -#include <vector> -#include "gears/geolocation/device_data_provider.h" - - -// Extracts access point data from the NDIS_802_11_BSSID_LIST structure and -// appends it to the data vector. Returns the number of access points for which -// data was extracted. -int GetDataFromBssIdList(const NDIS_802_11_BSSID_LIST &bss_id_list, - int list_size, - WifiData::AccessPointDataSet *data); - -#endif // GEARS_GEOLOCATION_WIFI_DATA_PROVIDER_WINDOWS_COMMON_H__ |