diff options
author | alemate <alemate@chromium.org> | 2016-03-23 16:21:44 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-23 23:23:11 +0000 |
commit | 9af1adea25a1a643a7f849616d3f51b33a9657aa (patch) | |
tree | 256c9b65f55eac24bada6ebfbb14ef041645801c /chromeos | |
parent | 0970ff860aba75cc0b35d58e6b6133291653ac56 (diff) | |
download | chromium_src-9af1adea25a1a643a7f849616d3f51b33a9657aa.zip chromium_src-9af1adea25a1a643a7f849616d3f51b33a9657aa.tar.gz chromium_src-9af1adea25a1a643a7f849616d3f51b33a9657aa.tar.bz2 |
SimpleGeolocation should support sending WiFi AP data.
BUG=596690
TEST=unittest
Review URL: https://codereview.chromium.org/1819173002
Cr-Commit-Position: refs/heads/master@{#382968}
Diffstat (limited to 'chromeos')
-rw-r--r-- | chromeos/BUILD.gn | 2 | ||||
-rw-r--r-- | chromeos/chromeos.gyp | 2 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_provider.cc | 23 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_provider.h | 6 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_request.cc | 98 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_request.h | 23 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_request_test_monitor.cc | 19 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_request_test_monitor.h | 31 | ||||
-rw-r--r-- | chromeos/geolocation/simple_geolocation_unittest.cc | 224 | ||||
-rw-r--r-- | chromeos/network/geolocation_handler.h | 2 | ||||
-rw-r--r-- | chromeos/timezone/timezone_resolver.cc | 4 | ||||
-rw-r--r-- | chromeos/timezone/timezone_resolver.h | 2 |
12 files changed, 407 insertions, 29 deletions
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 83c04f6..fe418ee 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn @@ -93,6 +93,8 @@ static_library("test_support") { "dbus/services/service_provider_test_helper.h", "disks/mock_disk_mount_manager.cc", "disks/mock_disk_mount_manager.h", + "geolocation/simple_geolocation_request_test_monitor.cc", + "geolocation/simple_geolocation_request_test_monitor.h", "login/auth/fake_extended_authenticator.cc", "login/auth/fake_extended_authenticator.h", "login/auth/mock_auth_attempt_state_resolver.cc", diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 049a542..e4281e7 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -584,6 +584,8 @@ 'dbus/services/service_provider_test_helper.h', 'disks/mock_disk_mount_manager.cc', 'disks/mock_disk_mount_manager.h', + 'geolocation/simple_geolocation_request_test_monitor.cc', + 'geolocation/simple_geolocation_request_test_monitor.h', 'login/auth/fake_extended_authenticator.cc', 'login/auth/fake_extended_authenticator.h', 'login/auth/mock_auth_attempt_state_resolver.cc', diff --git a/chromeos/geolocation/simple_geolocation_provider.cc b/chromeos/geolocation/simple_geolocation_provider.cc index e083b3e..0a26ede 100644 --- a/chromeos/geolocation/simple_geolocation_provider.cc +++ b/chromeos/geolocation/simple_geolocation_provider.cc @@ -9,6 +9,8 @@ #include "base/bind.h" #include "chromeos/geolocation/geoposition.h" +#include "chromeos/network/geolocation_handler.h" +#include "chromeos/network/network_handler.h" #include "net/url_request/url_request_context_getter.h" namespace chromeos { @@ -16,6 +18,20 @@ namespace chromeos { namespace { const char kDefaultGeolocationProviderUrl[] = "https://www.googleapis.com/geolocation/v1/geolocate?"; + +scoped_ptr<WifiAccessPointVector> GetAccessPointData() { + if (!chromeos::NetworkHandler::Get()->geolocation_handler()->wifi_enabled()) + return nullptr; + + scoped_ptr<WifiAccessPointVector> result(new chromeos::WifiAccessPointVector); + int64_t age_ms = 0; + if (!NetworkHandler::Get()->geolocation_handler()->GetWifiAccessPoints( + result.get(), &age_ms)) { + return nullptr; + } + return result; +} + } // namespace SimpleGeolocationProvider::SimpleGeolocationProvider( @@ -30,10 +46,13 @@ SimpleGeolocationProvider::~SimpleGeolocationProvider() { void SimpleGeolocationProvider::RequestGeolocation( base::TimeDelta timeout, + bool send_wifi_access_points, SimpleGeolocationRequest::ResponseCallback callback) { DCHECK(thread_checker_.CalledOnValidThread()); - SimpleGeolocationRequest* request( - new SimpleGeolocationRequest(url_context_getter_.get(), url_, timeout)); + + SimpleGeolocationRequest* request(new SimpleGeolocationRequest( + url_context_getter_.get(), url_, timeout, + send_wifi_access_points ? GetAccessPointData() : nullptr)); requests_.push_back(request); // SimpleGeolocationProvider owns all requests. It is safe to pass unretained diff --git a/chromeos/geolocation/simple_geolocation_provider.h b/chromeos/geolocation/simple_geolocation_provider.h index 6ba20dc..245dc27 100644 --- a/chromeos/geolocation/simple_geolocation_provider.h +++ b/chromeos/geolocation/simple_geolocation_provider.h @@ -33,9 +33,11 @@ class CHROMEOS_EXPORT SimpleGeolocationProvider { const GURL& url); virtual ~SimpleGeolocationProvider(); - // Initiates new request (See SimpleGeolocationRequest for parameters - // description.) + // Initiates new request. If |send_wifi_access_points|, WiFi AP information + // will be added to the request. See SimpleGeolocationRequest for the + // description of the other parameters. void RequestGeolocation(base::TimeDelta timeout, + bool send_wifi_access_points, SimpleGeolocationRequest::ResponseCallback callback); // Returns default geolocation service URL. diff --git a/chromeos/geolocation/simple_geolocation_request.cc b/chromeos/geolocation/simple_geolocation_request.cc index 01f48a0..5a27979 100644 --- a/chromeos/geolocation/simple_geolocation_request.cc +++ b/chromeos/geolocation/simple_geolocation_request.cc @@ -10,6 +10,7 @@ #include <string> #include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" #include "base/strings/string_number_conversions.h" @@ -17,6 +18,7 @@ #include "base/time/time.h" #include "base/values.h" #include "chromeos/geolocation/simple_geolocation_provider.h" +#include "chromeos/geolocation/simple_geolocation_request_test_monitor.h" #include "google_apis/google_api_keys.h" #include "net/base/escape.h" #include "net/base/load_flags.h" @@ -38,7 +40,18 @@ namespace chromeos { namespace { // The full request text. (no parameters are supported by now) -const char kSimpleGeolocationRequestBody[] = "{\"considerIP\": \"true\"}"; +const char kSimpleGeolocationRequestBody[] = "{\"considerIp\": \"true\"}"; + +// Request data +const char kConsiderIp[] = "considerIp"; +const char kWifiAccessPoints[] = "wifiAccessPoints"; + +// WiFi access point objects. +const char kMacAddress[] = "macAddress"; +const char kSignalStrength[] = "signalStrength"; +const char kAge[] = "age"; +const char kChannel[] = "channel"; +const char kSignalToNoiseRatio[] = "signalToNoiseRatio"; // Response data. const char kLocationString[] = "location"; @@ -88,6 +101,8 @@ enum SimpleGeolocationRequestResult { SIMPLE_GEOLOCATION_REQUEST_RESULT_COUNT = 4 }; +SimpleGeolocationRequestTestMonitor* g_test_request_hook = nullptr; + // Too many requests (more than 1) mean there is a problem in implementation. void RecordUmaEvent(SimpleGeolocationRequestEvent event) { UMA_HISTOGRAM_ENUMERATION("SimpleGeolocation.Request.Event", @@ -247,6 +262,9 @@ bool GetGeolocationFromResponse(bool http_success, const std::string& response_body, const GURL& server_url, Geoposition* position) { + VLOG(1) << "GetGeolocationFromResponse(http_success=" << http_success + << ", status_code=" << status_code << "): response_body:\n" + << response_body; // HttpPost can fail for a number of reasons. Most likely this is because // we're offline, or there was no response. @@ -266,12 +284,17 @@ bool GetGeolocationFromResponse(bool http_success, return ParseServerResponse(server_url, response_body, position); } +void ReportUmaHasWiFiAccessPoints(bool value) { + UMA_HISTOGRAM_BOOLEAN("SimpleGeolocation.Request.HasWiFiAccessPoints", value); +} + } // namespace SimpleGeolocationRequest::SimpleGeolocationRequest( net::URLRequestContextGetter* url_context_getter, const GURL& service_url, - base::TimeDelta timeout) + base::TimeDelta timeout, + scoped_ptr<WifiAccessPointVector> wifi_data) : url_context_getter_(url_context_getter), service_url_(service_url), retry_sleep_on_server_error_(base::TimeDelta::FromSeconds( @@ -279,8 +302,8 @@ SimpleGeolocationRequest::SimpleGeolocationRequest( retry_sleep_on_bad_response_(base::TimeDelta::FromSeconds( kResolveGeolocationRetrySleepBadResponseSeconds)), timeout_(timeout), - retries_(0) { -} + retries_(0), + wifi_data_(wifi_data.release()) {} SimpleGeolocationRequest::~SimpleGeolocationRequest() { DCHECK(thread_checker_.CalledOnValidThread()); @@ -290,6 +313,51 @@ SimpleGeolocationRequest::~SimpleGeolocationRequest() { RecordUmaResponseTime(base::Time::Now() - request_started_at_, false); RecordUmaResult(SIMPLE_GEOLOCATION_REQUEST_RESULT_CANCELLED, retries_); } + + if (g_test_request_hook) + g_test_request_hook->OnRequestCreated(this); +} + +std::string SimpleGeolocationRequest::FormatRequestBody() const { + if (!wifi_data_) { + ReportUmaHasWiFiAccessPoints(false); + return std::string(kSimpleGeolocationRequestBody); + } + + scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue); + request->SetBooleanWithoutPathExpansion(kConsiderIp, true); + + base::ListValue* wifi_access_points(new base::ListValue); + request->SetWithoutPathExpansion(kWifiAccessPoints, wifi_access_points); + + for (const WifiAccessPoint& access_point : *wifi_data_) { + base::DictionaryValue* access_point_dictionary = new base::DictionaryValue; + wifi_access_points->Append(access_point_dictionary); + + access_point_dictionary->SetStringWithoutPathExpansion( + kMacAddress, access_point.mac_address); + access_point_dictionary->SetIntegerWithoutPathExpansion( + kSignalStrength, access_point.signal_strength); + if (!access_point.timestamp.is_null()) { + access_point_dictionary->SetStringWithoutPathExpansion( + kAge, + base::Int64ToString( + (base::Time::Now() - access_point.timestamp).InMilliseconds())); + } + + access_point_dictionary->SetIntegerWithoutPathExpansion( + kChannel, access_point.channel); + access_point_dictionary->SetIntegerWithoutPathExpansion( + kSignalToNoiseRatio, access_point.signal_to_noise); + } + std::string result; + if (!base::JSONWriter::Write(*request, &result)) { + ReportUmaHasWiFiAccessPoints(false); + return std::string(kSimpleGeolocationRequestBody); + } + ReportUmaHasWiFiAccessPoints(wifi_data_->size()); + + return result; } void SimpleGeolocationRequest::StartRequest() { @@ -297,16 +365,24 @@ void SimpleGeolocationRequest::StartRequest() { RecordUmaEvent(SIMPLE_GEOLOCATION_REQUEST_EVENT_REQUEST_START); ++retries_; + const std::string request_body = FormatRequestBody(); + VLOG(1) << "SimpleGeolocationRequest::StartRequest(): request body:\n" + << request_body; + url_fetcher_ = net::URLFetcher::Create(request_url_, net::URLFetcher::POST, this); url_fetcher_->SetRequestContext(url_context_getter_.get()); - url_fetcher_->SetUploadData("application/json", - std::string(kSimpleGeolocationRequestBody)); + url_fetcher_->SetUploadData("application/json", request_body); url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA); + + // Call test hook before asynchronous request actually starts. + if (g_test_request_hook) + g_test_request_hook->OnStart(this); + url_fetcher_->Start(); } @@ -319,6 +395,16 @@ void SimpleGeolocationRequest::MakeRequest(const ResponseCallback& callback) { StartRequest(); } +// static +void SimpleGeolocationRequest::SetTestMonitor( + SimpleGeolocationRequestTestMonitor* monitor) { + g_test_request_hook = monitor; +} + +std::string SimpleGeolocationRequest::FormatRequestBodyForTesting() const { + return FormatRequestBody(); +} + void SimpleGeolocationRequest::Retry(bool server_error) { base::TimeDelta delay(server_error ? retry_sleep_on_server_error_ : retry_sleep_on_bad_response_); diff --git a/chromeos/geolocation/simple_geolocation_request.h b/chromeos/geolocation/simple_geolocation_request.h index 8771e5d..19ff507 100644 --- a/chromeos/geolocation/simple_geolocation_request.h +++ b/chromeos/geolocation/simple_geolocation_request.h @@ -12,7 +12,9 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" +#include "chromeos/chromeos_export.h" #include "chromeos/geolocation/geoposition.h" +#include "chromeos/network/network_util.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher_delegate.h" #include "url/gurl.h" @@ -23,6 +25,8 @@ class URLRequestContextGetter; namespace chromeos { +class SimpleGeolocationRequestTestMonitor; + // Sends request to a server to get local geolocation information. // It performs formatting of the request and interpretation of the response. // Request is owned and destroyed by caller (usually SimpleGeolocationProvider). @@ -32,7 +36,10 @@ namespace chromeos { // (position.status is set to STATUS_TIMEOUT.) // - If request is destroyed while callback has not beed called yet, request // is silently cancelled. -class SimpleGeolocationRequest : private net::URLFetcherDelegate { +// +// Note: we need CHROMEOS_EXPORT for tests. +class CHROMEOS_EXPORT SimpleGeolocationRequest + : private net::URLFetcherDelegate { public: // Called when a new geo geolocation information is available. // The second argument indicates whether there was a server error or not. @@ -44,9 +51,11 @@ class SimpleGeolocationRequest : private net::URLFetcherDelegate { // |url| is the server address to which the request wil be sent. // |timeout| retry request on error until timeout. + // If wifi_data is not null, it will be sent to the geolocation server. SimpleGeolocationRequest(net::URLRequestContextGetter* url_context_getter, const GURL& service_url, - base::TimeDelta timeout); + base::TimeDelta timeout, + scoped_ptr<WifiAccessPointVector> wifi_data); ~SimpleGeolocationRequest() override; @@ -65,6 +74,11 @@ class SimpleGeolocationRequest : private net::URLFetcherDelegate { retry_sleep_on_bad_response_ = value; } + // Sets global requests monitoring object for testing. + static void SetTestMonitor(SimpleGeolocationRequestTestMonitor* monitor); + + std::string FormatRequestBodyForTesting() const; + private: // net::URLFetcherDelegate void OnURLFetchComplete(const net::URLFetcher* source) override; @@ -81,6 +95,9 @@ class SimpleGeolocationRequest : private net::URLFetcherDelegate { // Called by timeout_timer_ . void OnTimeout(); + // Returns API request body. + std::string FormatRequestBody() const; + scoped_refptr<net::URLRequestContextGetter> url_context_getter_; // Service URL from constructor arguments. @@ -114,6 +131,8 @@ class SimpleGeolocationRequest : private net::URLFetcherDelegate { // This is updated on each retry. Geoposition position_; + scoped_ptr<WifiAccessPointVector> wifi_data_; + // Creation and destruction should happen on the same thread. base::ThreadChecker thread_checker_; diff --git a/chromeos/geolocation/simple_geolocation_request_test_monitor.cc b/chromeos/geolocation/simple_geolocation_request_test_monitor.cc new file mode 100644 index 0000000..d303b8c --- /dev/null +++ b/chromeos/geolocation/simple_geolocation_request_test_monitor.cc @@ -0,0 +1,19 @@ +// Copyright 2016 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 "chromeos/geolocation/simple_geolocation_request_test_monitor.h" + +namespace chromeos { + +SimpleGeolocationRequestTestMonitor::SimpleGeolocationRequestTestMonitor() {} + +SimpleGeolocationRequestTestMonitor::~SimpleGeolocationRequestTestMonitor() {} + +void SimpleGeolocationRequestTestMonitor::OnRequestCreated( + SimpleGeolocationRequest* request) {} + +void SimpleGeolocationRequestTestMonitor::OnStart( + SimpleGeolocationRequest* request) {} + +} // namespace chromeos diff --git a/chromeos/geolocation/simple_geolocation_request_test_monitor.h b/chromeos/geolocation/simple_geolocation_request_test_monitor.h new file mode 100644 index 0000000..2213db2 --- /dev/null +++ b/chromeos/geolocation/simple_geolocation_request_test_monitor.h @@ -0,0 +1,31 @@ +// Copyright 2016 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 CHROMEOS_GEOLOCATION_SIMPLE_GEOLOCATION_REQUEST_TEST_MONITOR_H_ +#define CHROMEOS_GEOLOCATION_SIMPLE_GEOLOCATION_REQUEST_TEST_MONITOR_H_ + +#include "base/macros.h" + +namespace chromeos { + +class SimpleGeolocationRequest; + +// This is global hook, that allows to monitor SimpleGeolocationRequest +// in tests. + +class SimpleGeolocationRequestTestMonitor { + public: + SimpleGeolocationRequestTestMonitor(); + + virtual ~SimpleGeolocationRequestTestMonitor(); + virtual void OnRequestCreated(SimpleGeolocationRequest* request); + virtual void OnStart(SimpleGeolocationRequest* request); + + private: + DISALLOW_COPY_AND_ASSIGN(SimpleGeolocationRequestTestMonitor); +}; + +} // namespace chromeos + +#endif // CHROMEOS_GEOLOCATION_SIMPLE_GEOLOCATION_REQUEST_TEST_MONITOR_H_ diff --git a/chromeos/geolocation/simple_geolocation_unittest.cc b/chromeos/geolocation/simple_geolocation_unittest.cc index 6c8fb42..61c83b9 100644 --- a/chromeos/geolocation/simple_geolocation_unittest.cc +++ b/chromeos/geolocation/simple_geolocation_unittest.cc @@ -7,13 +7,21 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/shill_manager_client.h" #include "chromeos/geolocation/simple_geolocation_provider.h" +#include "chromeos/geolocation/simple_geolocation_request_test_monitor.h" +#include "chromeos/network/geolocation_handler.h" +#include "chromeos/network/network_handler.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" #include "net/url_request/test_url_fetcher_factory.h" #include "net/url_request/url_fetcher_impl.h" #include "net/url_request/url_request_status.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/cros_system_api/dbus/service_constants.h" namespace { @@ -32,6 +40,24 @@ const char kSimpleResponseBody[] = " },\n" " \"accuracy\": 1200.4\n" "}"; +const char kIPOnlyRequestBody[] = "{\"considerIp\": \"true\"}"; +const char kOneWiFiAPRequestBody[] = + "{" + "\"considerIp\":true," + "\"wifiAccessPoints\":[" + "{" + "\"channel\":1," + "\"macAddress\":\"01:00:00:00:00:00\"," + "\"signalStrength\":10," + "\"signalToNoiseRatio\":0" + "}" + "]" + "}"; +const char kExpectedPosition[] = + "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, " + "error_code=0, error_message='', status=1 (OK)"; + +const char kWiFiAP1MacAddress[] = "01:00:00:00:00:00"; } // anonymous namespace namespace chromeos { @@ -46,7 +72,7 @@ class TestGeolocationAPIURLFetcherCallback { : url_(url), require_retries_(require_retries), response_(response), - factory_(NULL), + factory_(nullptr), attempts_(0), provider_(provider) {} @@ -115,9 +141,9 @@ class GeolocationAPIFetcherFactory { SimpleGeolocationProvider* provider) { url_callback_.reset(new TestGeolocationAPIURLFetcherCallback( url, require_retries, response, provider)); - net::URLFetcherImpl::set_factory(NULL); + net::URLFetcherImpl::set_factory(nullptr); fetcher_factory_.reset(new net::FakeURLFetcherFactory( - NULL, + nullptr, base::Bind(&TestGeolocationAPIURLFetcherCallback::CreateURLFetcher, base::Unretained(url_callback_.get())))); url_callback_->Initialize(fetcher_factory_.get()); @@ -162,13 +188,31 @@ class GeolocationReceiver { scoped_ptr<base::RunLoop> message_loop_runner_; }; +class WiFiTestMonitor : public SimpleGeolocationRequestTestMonitor { + public: + WiFiTestMonitor() {} + + void OnRequestCreated(SimpleGeolocationRequest* request) override {} + void OnStart(SimpleGeolocationRequest* request) override { + last_request_body_ = request->FormatRequestBodyForTesting(); + } + + const std::string& last_request_body() const { return last_request_body_; } + + private: + std::string last_request_body_; + + DISALLOW_COPY_AND_ASSIGN(WiFiTestMonitor); +}; + class SimpleGeolocationTest : public testing::Test { private: base::MessageLoop message_loop_; }; TEST_F(SimpleGeolocationTest, ResponseOK) { - SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl)); + SimpleGeolocationProvider provider(nullptr, + GURL(kTestGeolocationProviderUrl)); GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), std::string(kSimpleResponseBody), @@ -176,21 +220,19 @@ TEST_F(SimpleGeolocationTest, ResponseOK) { &provider); GeolocationReceiver receiver; - provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), false, base::Bind(&GeolocationReceiver::OnRequestDone, base::Unretained(&receiver))); receiver.WaitUntilRequestDone(); - EXPECT_EQ( - "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, " - "error_code=0, error_message='', status=1 (OK)", - receiver.position().ToString()); + EXPECT_EQ(kExpectedPosition, receiver.position().ToString()); EXPECT_FALSE(receiver.server_error()); EXPECT_EQ(1U, url_factory.attempts()); } TEST_F(SimpleGeolocationTest, ResponseOKWithRetries) { - SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl)); + SimpleGeolocationProvider provider(nullptr, + GURL(kTestGeolocationProviderUrl)); GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), std::string(kSimpleResponseBody), @@ -198,20 +240,18 @@ TEST_F(SimpleGeolocationTest, ResponseOKWithRetries) { &provider); GeolocationReceiver receiver; - provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), false, base::Bind(&GeolocationReceiver::OnRequestDone, base::Unretained(&receiver))); receiver.WaitUntilRequestDone(); - EXPECT_EQ( - "latitude=51.000000, longitude=-0.100000, accuracy=1200.400000, " - "error_code=0, error_message='', status=1 (OK)", - receiver.position().ToString()); + EXPECT_EQ(kExpectedPosition, receiver.position().ToString()); EXPECT_FALSE(receiver.server_error()); EXPECT_EQ(4U, url_factory.attempts()); } TEST_F(SimpleGeolocationTest, InvalidResponse) { - SimpleGeolocationProvider provider(NULL, GURL(kTestGeolocationProviderUrl)); + SimpleGeolocationProvider provider(nullptr, + GURL(kTestGeolocationProviderUrl)); GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), "invalid JSON string", @@ -226,6 +266,7 @@ TEST_F(SimpleGeolocationTest, InvalidResponse) { ASSERT_GE(expected_retries, 2U); provider.RequestGeolocation(base::TimeDelta::FromSeconds(timeout_seconds), + false, base::Bind(&GeolocationReceiver::OnRequestDone, base::Unretained(&receiver))); receiver.WaitUntilRequestDone(); @@ -252,4 +293,155 @@ TEST_F(SimpleGeolocationTest, InvalidResponse) { } } +TEST_F(SimpleGeolocationTest, NoWiFi) { + // This initializes DBusThreadManager and markes it "for tests only". + DBusThreadManager::GetSetterForTesting(); + NetworkHandler::Initialize(); + + WiFiTestMonitor requests_monitor; + SimpleGeolocationRequest::SetTestMonitor(&requests_monitor); + + SimpleGeolocationProvider provider(nullptr, + GURL(kTestGeolocationProviderUrl)); + + GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), + std::string(kSimpleResponseBody), + 0 /* require_retries */, &provider); + + GeolocationReceiver receiver; + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), true, + base::Bind(&GeolocationReceiver::OnRequestDone, + base::Unretained(&receiver))); + receiver.WaitUntilRequestDone(); + EXPECT_EQ(kIPOnlyRequestBody, requests_monitor.last_request_body()); + + EXPECT_EQ(kExpectedPosition, receiver.position().ToString()); + EXPECT_FALSE(receiver.server_error()); + EXPECT_EQ(1U, url_factory.attempts()); + + NetworkHandler::Shutdown(); + DBusThreadManager::Shutdown(); +} + +// Test sending of WiFi Access points. +// (This is mostly derived from GeolocationHandlerTest.) +class SimpleGeolocationWiFiTest : public ::testing::TestWithParam<bool> { + public: + SimpleGeolocationWiFiTest() : manager_test_(nullptr) {} + + ~SimpleGeolocationWiFiTest() override {} + + void SetUp() override { + // This initializes DBusThreadManager and markes it "for tests only". + DBusThreadManager::GetSetterForTesting(); + // Get the test interface for manager / device. + manager_test_ = + DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface(); + ASSERT_TRUE(manager_test_); + geolocation_handler_.reset(new GeolocationHandler()); + geolocation_handler_->Init(); + message_loop_.RunUntilIdle(); + } + + void TearDown() override { + geolocation_handler_.reset(); + DBusThreadManager::Shutdown(); + } + + bool GetWifiAccessPoints() { + return geolocation_handler_->GetWifiAccessPoints(&wifi_access_points_, + nullptr); + } + + void AddAccessPoint(int idx) { + base::DictionaryValue properties; + std::string mac_address = + base::StringPrintf("%02X:%02X:%02X:%02X:%02X:%02X", idx, 0, 0, 0, 0, 0); + std::string channel = base::IntToString(idx); + std::string strength = base::IntToString(idx * 10); + properties.SetStringWithoutPathExpansion(shill::kGeoMacAddressProperty, + mac_address); + properties.SetStringWithoutPathExpansion(shill::kGeoChannelProperty, + channel); + properties.SetStringWithoutPathExpansion(shill::kGeoSignalStrengthProperty, + strength); + manager_test_->AddGeoNetwork(shill::kTypeWifi, properties); + message_loop_.RunUntilIdle(); + } + + protected: + base::MessageLoopForUI message_loop_; + scoped_ptr<GeolocationHandler> geolocation_handler_; + ShillManagerClient::TestInterface* manager_test_; + WifiAccessPointVector wifi_access_points_; + + private: + DISALLOW_COPY_AND_ASSIGN(SimpleGeolocationWiFiTest); +}; + +// Parameter is enable/disable sending of WiFi data. +TEST_P(SimpleGeolocationWiFiTest, WiFiExists) { + NetworkHandler::Initialize(); + + WiFiTestMonitor requests_monitor; + SimpleGeolocationRequest::SetTestMonitor(&requests_monitor); + + SimpleGeolocationProvider provider(nullptr, + GURL(kTestGeolocationProviderUrl)); + + GeolocationAPIFetcherFactory url_factory(GURL(kTestGeolocationProviderUrl), + std::string(kSimpleResponseBody), + 0 /* require_retries */, &provider); + { + GeolocationReceiver receiver; + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), GetParam(), + base::Bind(&GeolocationReceiver::OnRequestDone, + base::Unretained(&receiver))); + receiver.WaitUntilRequestDone(); + EXPECT_EQ(kIPOnlyRequestBody, requests_monitor.last_request_body()); + + EXPECT_EQ(kExpectedPosition, receiver.position().ToString()); + EXPECT_FALSE(receiver.server_error()); + EXPECT_EQ(1U, url_factory.attempts()); + } + + // Add an acces point. + AddAccessPoint(1); + message_loop_.RunUntilIdle(); + // Inititial call should return false and request access points. + EXPECT_FALSE(GetWifiAccessPoints()); + message_loop_.RunUntilIdle(); + // Second call should return true since we have an access point. + EXPECT_TRUE(GetWifiAccessPoints()); + ASSERT_EQ(1u, wifi_access_points_.size()); + EXPECT_EQ(kWiFiAP1MacAddress, wifi_access_points_[0].mac_address); + EXPECT_EQ(1, wifi_access_points_[0].channel); + + { + GeolocationReceiver receiver; + provider.RequestGeolocation(base::TimeDelta::FromSeconds(1), GetParam(), + base::Bind(&GeolocationReceiver::OnRequestDone, + base::Unretained(&receiver))); + receiver.WaitUntilRequestDone(); + if (GetParam()) { + // Sending WiFi data is enabled. + EXPECT_EQ(kOneWiFiAPRequestBody, requests_monitor.last_request_body()); + } else { + // Sending WiFi data is disabled. + EXPECT_EQ(kIPOnlyRequestBody, requests_monitor.last_request_body()); + } + + EXPECT_EQ(kExpectedPosition, receiver.position().ToString()); + EXPECT_FALSE(receiver.server_error()); + // This is total. + EXPECT_EQ(2U, url_factory.attempts()); + } + NetworkHandler::Shutdown(); +} + +// This test verifies that WiFi data is sent only if sending was requested. +INSTANTIATE_TEST_CASE_P(EnableDisableSendingWifiData, + SimpleGeolocationWiFiTest, + testing::Bool()); + } // namespace chromeos diff --git a/chromeos/network/geolocation_handler.h b/chromeos/network/geolocation_handler.h index 5720364..f962328 100644 --- a/chromeos/network/geolocation_handler.h +++ b/chromeos/network/geolocation_handler.h @@ -52,6 +52,8 @@ class CHROMEOS_EXPORT GeolocationHandler : public ShillPropertyChangedObserver { private: friend class NetworkHandler; friend class GeolocationHandlerTest; + friend class SimpleGeolocationWiFiTest; + GeolocationHandler(); void Init(); diff --git a/chromeos/timezone/timezone_resolver.cc b/chromeos/timezone/timezone_resolver.cc index c6ebfb4..9e4c7b9 100644 --- a/chromeos/timezone/timezone_resolver.cc +++ b/chromeos/timezone/timezone_resolver.cc @@ -183,6 +183,7 @@ void TZRequest::StartRequestOnNetworkAvailable() { resolver_->RecordAttempt(); resolver_->geolocation_provider()->RequestGeolocation( base::TimeDelta::FromSeconds(kRefreshTimeZoneTimeoutSeconds), + false /* send_wifi_geolocation_data */, base::Bind(&TZRequest::OnLocationResolved, AsWeakPtr())); } @@ -383,7 +384,8 @@ TimeZoneResolver::TimeZoneResolver( url_(url), apply_timezone_(apply_timezone), delay_network_call_(delay_network_call), - local_state_(local_state) { + local_state_(local_state), + send_wifi_data_to_geolocation_api_(false) { DCHECK(!apply_timezone.is_null()); } diff --git a/chromeos/timezone/timezone_resolver.h b/chromeos/timezone/timezone_resolver.h index 231575b..35e6c2e 100644 --- a/chromeos/timezone/timezone_resolver.h +++ b/chromeos/timezone/timezone_resolver.h @@ -79,6 +79,8 @@ class CHROMEOS_EXPORT TimeZoneResolver { scoped_ptr<TimeZoneResolverImpl> implementation_; + bool send_wifi_data_to_geolocation_api_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(TimeZoneResolver); |