15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/fake_access_token_store.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/geolocation/location_arbitrator_impl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/geolocation/network_location_provider.h"
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/browser/geolocation/wifi_data_provider.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/test_url_fetcher_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constants used in multiple tests.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestServerUrl[] = "https://www.geolocation.test/service";
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAccessTokenString[] = "accessToken";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Using #define so we can easily paste this into various other strings.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REFERENCE_ACCESS_TOKEN "2:k7j3G6LaL6u_lafw:4iXOeOpTh1glSXe"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stops the specified (nested) message loop when the listener is called back.
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class MessageLoopQuitListener {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoopQuitListener()
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : client_message_loop_(base::MessageLoop::current()),
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        updated_provider_(NULL) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(client_message_loop_);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void OnLocationUpdate(const LocationProvider* provider,
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        const Geoposition& position) {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_EQ(client_message_loop_, base::MessageLoop::current());
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updated_provider_ = provider;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_message_loop_->Quit();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop* client_message_loop_;
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const LocationProvider* updated_provider_;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// A mock implementation of WifiDataProvider for testing. Adapted from
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation_test.cc
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class MockWifiDataProvider : public WifiDataProvider {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Factory method for use with WifiDataProvider::SetFactoryForTesting.
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  static WifiDataProvider* GetInstance() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(instance_);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return instance_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  static MockWifiDataProvider* CreateInstance() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(!instance_);
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    instance_ = new MockWifiDataProvider;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return instance_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  MockWifiDataProvider() : start_calls_(0), stop_calls_(0), got_data_(true) {}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // WifiDataProvider implementation.
69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void StartDataProvider() OVERRIDE {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++start_calls_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual void StopDataProvider() OVERRIDE {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++stop_calls_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  virtual bool GetData(WifiData* data_out) OVERRIDE {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(data_out);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *data_out = data_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return got_data_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  void SetData(const WifiData& new_data) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    got_data_ = true;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool differs = data_.DiffersSignificantly(new_data);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_ = new_data;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (differs)
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      this->RunCallbacks();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_got_data(bool got_data) { got_data_ = got_data; }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int start_calls_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int stop_calls_;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual ~MockWifiDataProvider() {
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    CHECK(this == instance_);
98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    instance_ = NULL;
99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  static MockWifiDataProvider* instance_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  WifiData data_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool got_data_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MockWifiDataProvider);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)MockWifiDataProvider* MockWifiDataProvider::instance_ = NULL;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main test fixture
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GeolocationNetworkProviderTest : public testing::Test {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_server_url_ = GURL(kTestServerUrl);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    access_token_store_ = new FakeAccessTokenStore;
11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    wifi_data_provider_ = MockWifiDataProvider::CreateInstance();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual void TearDown() { WifiDataProviderManager::ResetFactoryForTesting(); }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  LocationProvider* CreateProvider(bool set_permission_granted) {
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    LocationProvider* provider = NewNetworkLocationProvider(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        access_token_store_.get(),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NULL,  // No URLContextGetter needed, as using test urlfecther factory.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        test_server_url_,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        access_token_store_->access_token_set_[test_server_url_]);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (set_permission_granted)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      provider->OnPermissionGranted();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return provider;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GeolocationNetworkProviderTest() {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(joth): Really these should be in SetUp, not here, but they take no
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // effect on Mac OS Release builds if done there. I kid not. Figure out why.
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    WifiDataProviderManager::SetFactoryForTesting(
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        MockWifiDataProvider::GetInstance);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the current url fetcher (if any) and advances the id ready for the
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // next test step.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* get_url_fetcher_and_advance_id() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetworkLocationRequest::url_fetcher_id_for_tests);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fetcher)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++NetworkLocationRequest::url_fetcher_id_for_tests;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return fetcher;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int IndexToChannel(int index) { return index + 4; }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates wifi data containing the specified number of access points, with
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // some differentiating charactistics in each.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static WifiData CreateReferenceWifiScanData(int ap_count) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WifiData data;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < ap_count; ++i) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AccessPointData ap;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap.mac_address =
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::ASCIIToUTF16(base::StringPrintf("%02d-34-56-78-54-32", i));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap.radio_signal_strength = ap_count - i;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap.channel = IndexToChannel(i);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap.signal_to_noise = i + 42;
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ap.ssid = base::ASCIIToUTF16("Some nice+network|name\\");
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.access_point_data.insert(ap);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return data;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void CreateReferenceWifiScanDataJson(
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int ap_count, int start_index, base::ListValue* wifi_access_point_list) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> wifi_data;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < ap_count; ++i) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::DictionaryValue* ap = new base::DictionaryValue();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap->SetString("macAddress", base::StringPrintf("%02d-34-56-78-54-32", i));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap->SetInteger("signalStrength", start_index + ap_count - i);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap->SetInteger("age", 0);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap->SetInteger("channel", IndexToChannel(i));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ap->SetInteger("signalToNoiseRatio", i + 42);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wifi_access_point_list->Append(ap);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Geoposition CreateReferencePosition(int id) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Geoposition pos;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos.latitude = id;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos.longitude = -(id + 1);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos.altitude = 2 * id;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pos.timestamp = base::Time::Now();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pos;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static std::string PrettyJson(const base::Value& value) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string pretty;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::JSONWriter::WriteWithOptions(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &value, base::JSONWriter::OPTIONS_PRETTY_PRINT, &pretty);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pretty;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static testing::AssertionResult JsonGetList(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& field,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::DictionaryValue& dict,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::ListValue** output_list) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!dict.GetList(field, output_list))
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return testing::AssertionFailure() << "Dictionary " << PrettyJson(dict)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         << " is missing list field " << field;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return testing::AssertionSuccess();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static testing::AssertionResult JsonFieldEquals(
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& field,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::DictionaryValue& expected,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::DictionaryValue& actual) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Value* expected_value;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Value* actual_value;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!expected.Get(field, &expected_value))
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return testing::AssertionFailure()
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Expected dictionary " << PrettyJson(expected)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " is missing field " << field;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!expected.Get(field, &actual_value))
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return testing::AssertionFailure()
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Actual dictionary " << PrettyJson(actual)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " is missing field " << field;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!expected_value->Equals(actual_value))
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return testing::AssertionFailure()
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Field " << field << " mismatch: " << PrettyJson(*expected_value)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " != " << PrettyJson(*actual_value);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return testing::AssertionSuccess();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static GURL UrlWithoutQuery(const GURL& url) {
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    url::Replacements<char> replacements;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    replacements.ClearQuery();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return url.ReplaceComponents(replacements);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  testing::AssertionResult IsTestServerUrl(const GURL& request_url) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL a(UrlWithoutQuery(test_server_url_));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL b(UrlWithoutQuery(request_url));
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (a == b)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return testing::AssertionSuccess();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return testing::AssertionFailure() << a << " != " << b;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckRequestIsValid(const net::TestURLFetcher& request,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int expected_routers,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int expected_wifi_aps,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int wifi_start_index,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const std::string& expected_access_token) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& request_url = request.GetOriginalURL();
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(IsTestServerUrl(request_url));
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check to see that the api key is being appended for the default
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // network provider url.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_default_url = UrlWithoutQuery(request_url) ==
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        UrlWithoutQuery(LocationArbitratorImpl::DefaultNetworkProviderURL());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(is_default_url, !request_url.query().empty());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& upload_data = request.upload_data();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(upload_data.empty());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string json_parse_error_msg;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::Value> parsed_json(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::JSONReader::ReadAndReturnError(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            upload_data,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::JSON_PARSE_RFC,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NULL,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &json_parse_error_msg));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(json_parse_error_msg.empty());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(parsed_json.get() != NULL);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::DictionaryValue* request_json;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(parsed_json->GetAsDictionary(&request_json));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!is_default_url) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (expected_access_token.empty())
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_FALSE(request_json->HasKey(kAccessTokenString));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string access_token;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE(request_json->GetString(kAccessTokenString, &access_token));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(expected_access_token, access_token);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_wifi_aps) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ListValue expected_wifi_aps_json;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateReferenceWifiScanDataJson(
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          expected_wifi_aps,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wifi_start_index,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &expected_wifi_aps_json);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(size_t(expected_wifi_aps), expected_wifi_aps_json.GetSize());
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::ListValue* wifi_aps_json;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(JsonGetList("wifiAccessPoints", *request_json,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              &wifi_aps_json));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < expected_wifi_aps_json.GetSize(); ++i ) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const base::DictionaryValue* expected_json;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(expected_wifi_aps_json.GetDictionary(i, &expected_json));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const base::DictionaryValue* actual_json;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(wifi_aps_json->GetDictionary(i, &actual_json));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(JsonFieldEquals("macAddress", *expected_json,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    *actual_json));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(JsonFieldEquals("signalStrength", *expected_json,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    *actual_json));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(JsonFieldEquals("channel", *expected_json, *actual_json));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASSERT_TRUE(JsonFieldEquals("signalToNoiseRatio", *expected_json,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    *actual_json));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_FALSE(request_json->HasKey("wifiAccessPoints"));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(request_url.is_valid());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL test_server_url_;
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop main_message_loop_;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<FakeAccessTokenStore> access_token_store_;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcherFactory url_fetcher_factory_;
31903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_refptr<MockWifiDataProvider> wifi_data_provider_;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, CreateDestroy) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test fixture members were SetUp correctly.
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(&main_message_loop_, base::MessageLoop::current());
3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(NULL != provider.get());
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider.reset();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SUCCEED();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, StartProvider) {
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckRequestIsValid(*fetcher, 0, 0, 0, std::string());
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, StartProviderDefaultUrl) {
34058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  test_server_url_ = LocationArbitratorImpl::DefaultNetworkProviderURL();
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckRequestIsValid(*fetcher, 0, 0, 0, std::string());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, StartProviderLongRequest) {
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kFirstScanAps = 20;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(kFirstScanAps));
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request url should have been shortened to less than 2048 characters
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in length by not including access points with the lowest signal strength
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the request.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(fetcher->GetOriginalURL().spec().size(), size_t(2048));
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckRequestIsValid(*fetcher, 0, 16, 4, std::string());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
3647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsTestServerUrl(fetcher->GetOriginalURL()));
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Complete the network request with bad position fix.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* kNoFixNetworkResponse =
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{"
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"status\": \"ZERO_RESULTS\""
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_url(test_server_url_);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_status(net::URLRequestStatus());
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_response_code(200);  // OK
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetResponseString(kNoFixNetworkResponse);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->delegate()->OnURLFetchComplete(fetcher);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Geoposition position;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->GetPosition(&position);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(position.Validate());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now wifi data arrives -- SetData will notify listeners.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kFirstScanAps = 6;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(kFirstScanAps));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request should have the wifi data.
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CheckRequestIsValid(*fetcher, 0, kFirstScanAps, 0, std::string());
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send a reply with good position fix.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* kReferenceNetworkResponse =
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{"
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"accessToken\": \"" REFERENCE_ACCESS_TOKEN "\","
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"accuracy\": 1200.4,"
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  \"location\": {"
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    \"lat\": 51.0,"
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "    \"lng\": -0.1"
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "  }"
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "}";
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_url(test_server_url_);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_status(net::URLRequestStatus());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_response_code(200);  // OK
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->SetResponseString(kReferenceNetworkResponse);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->delegate()->OnURLFetchComplete(fetcher);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->GetPosition(&position);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(51.0, position.latitude);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-0.1, position.longitude);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1200.4, position.accuracy);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(position.timestamp.is_null());
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(position.Validate());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Token should be in the store.
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(base::UTF8ToUTF16(REFERENCE_ACCESS_TOKEN),
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            access_token_store_->access_token_set_[test_server_url_]);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wifi updated again, with one less AP. This is 'close enough' to the
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous scan, so no new request made.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSecondScanAps = kFirstScanAps - 1;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(kSecondScanAps));
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(fetcher);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->GetPosition(&position);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(51.0, position.latitude);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-0.1, position.longitude);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(position.Validate());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now a third scan with more than twice the original amount -> new request.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kThirdScanAps = kFirstScanAps * 2 + 1;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(kThirdScanAps));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(fetcher);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckRequestIsValid(*fetcher, 0, kThirdScanAps, 0, REFERENCE_ACCESS_TOKEN);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ...reply with a network error.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_url(test_server_url_);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::FAILED, -1));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->set_response_code(200);  // should be ignored
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fetcher->SetResponseString(std::string());
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher->delegate()->OnURLFetchComplete(fetcher);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Error means we now no longer have a fix.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->GetPosition(&position);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(position.Validate());
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wifi scan returns to original set: should be serviced from cache.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(kFirstScanAps));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(get_url_fetcher_and_advance_id());  // No new request created.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->GetPosition(&position);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(51.0, position.latitude);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(-0.1, position.longitude);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(position.Validate());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, NoRequestOnStartupUntilWifiData) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoopQuitListener listener;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->set_got_data(false);
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  provider->SetUpdateCallback(base::Bind(
4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      &MessageLoopQuitListener::OnLocationUpdate, base::Unretained(&listener)));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(get_url_fetcher_and_advance_id())
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Network request should not be created right away on startup when "
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "wifi data has not yet arrived";
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(1));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(get_url_fetcher_and_advance_id());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, NewDataReplacesExistingNetworkRequest) {
485424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Send initial request with empty data
4867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(true));
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(fetcher);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now wifi data arrives; new request should be sent.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(4));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(fetcher);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, NetworkRequestDeferredForPermission) {
4997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(false));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(fetcher);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->OnPermissionGranted();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsTestServerUrl(fetcher->GetOriginalURL()));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       NetworkRequestWithWifiDataDeferredForPermission) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  access_token_store_->access_token_set_[test_server_url_] =
5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF8ToUTF16(REFERENCE_ACCESS_TOKEN);
5157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  scoped_ptr<LocationProvider> provider(CreateProvider(false));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(provider->StartProvider(false));
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::TestURLFetcher* fetcher = get_url_fetcher_and_advance_id();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(fetcher);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kScanCount = 4;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wifi_data_provider_->SetData(CreateReferenceWifiScanData(kScanCount));
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  main_message_loop_.RunUntilIdle();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(fetcher);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider->OnPermissionGranted();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher = get_url_fetcher_and_advance_id();
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(fetcher != NULL);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckRequestIsValid(*fetcher, 0, kScanCount, 0, REFERENCE_ACCESS_TOKEN);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(GeolocationNetworkProviderTest, NetworkPositionCache) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkLocationProvider::PositionCache cache;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kCacheSize = NetworkLocationProvider::PositionCache::kMaximumSize;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < kCacheSize * 2 + 1; ++i) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Geoposition pos = CreateReferencePosition(i);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ret = cache.CachePosition(CreateReferenceWifiScanData(i), pos);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(ret)  << i;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Geoposition* item =
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cache.FindPosition(CreateReferenceWifiScanData(i));
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(item) << i;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(pos.latitude, item->latitude)  << i;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(pos.longitude, item->longitude)  << i;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i <= kCacheSize) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Nothing should have spilled yet; check oldest item is still there.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(cache.FindPosition(CreateReferenceWifiScanData(1)));
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int evicted = i - kCacheSize;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(cache.FindPosition(CreateReferenceWifiScanData(evicted)));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(cache.FindPosition(CreateReferenceWifiScanData(evicted + 1)));
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
560