1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/geolocation/wifi_data_provider_common.h"
6
7#include "base/bind.h"
8#include "base/strings/stringprintf.h"
9#include "base/strings/utf_string_conversions.h"
10
11namespace content {
12
13base::string16 MacAddressAsString16(const uint8 mac_as_int[6]) {
14  // mac_as_int is big-endian. Write in byte chunks.
15  // Format is XX-XX-XX-XX-XX-XX.
16  static const char* const kMacFormatString =
17      "%02x-%02x-%02x-%02x-%02x-%02x";
18  return base::ASCIIToUTF16(base::StringPrintf(kMacFormatString,
19                                               mac_as_int[0],
20                                               mac_as_int[1],
21                                               mac_as_int[2],
22                                               mac_as_int[3],
23                                               mac_as_int[4],
24                                               mac_as_int[5]));
25}
26
27WifiDataProviderCommon::WifiDataProviderCommon()
28    : is_first_scan_complete_(false),
29      weak_factory_(this) {
30}
31
32WifiDataProviderCommon::~WifiDataProviderCommon() {
33}
34
35void WifiDataProviderCommon::StartDataProvider() {
36  DCHECK(wlan_api_ == NULL);
37  wlan_api_.reset(NewWlanApi());
38  if (wlan_api_ == NULL) {
39    // Error! Can't do scans, so don't try and schedule one.
40    is_first_scan_complete_ = true;
41    return;
42  }
43
44  DCHECK(polling_policy_ == NULL);
45  polling_policy_.reset(NewPollingPolicy());
46  DCHECK(polling_policy_ != NULL);
47
48  // Perform first scan ASAP regardless of the polling policy. If this scan
49  // fails we'll retry at a rate in line with the polling policy.
50  ScheduleNextScan(0);
51}
52
53void WifiDataProviderCommon::StopDataProvider() {
54  wlan_api_.reset();
55  polling_policy_.reset();
56}
57
58bool WifiDataProviderCommon::GetData(WifiData* data) {
59  *data = wifi_data_;
60  // If we've successfully completed a scan, indicate that we have all of the
61  // data we can get.
62  return is_first_scan_complete_;
63}
64
65void WifiDataProviderCommon::DoWifiScanTask() {
66  bool update_available = false;
67  WifiData new_data;
68  if (!wlan_api_->GetAccessPointData(&new_data.access_point_data)) {
69    ScheduleNextScan(polling_policy_->NoWifiInterval());
70  } else {
71    update_available = wifi_data_.DiffersSignificantly(new_data);
72    wifi_data_ = new_data;
73    polling_policy_->UpdatePollingInterval(update_available);
74    ScheduleNextScan(polling_policy_->PollingInterval());
75  }
76  if (update_available || !is_first_scan_complete_) {
77    is_first_scan_complete_ = true;
78    RunCallbacks();
79  }
80}
81
82void WifiDataProviderCommon::ScheduleNextScan(int interval) {
83  client_loop()->PostDelayedTask(
84      FROM_HERE,
85      base::Bind(&WifiDataProviderCommon::DoWifiScanTask,
86                 weak_factory_.GetWeakPtr()),
87      base::TimeDelta::FromMilliseconds(interval));
88}
89
90}  // namespace content
91