| Index: chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc
|
| diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc b/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1123e341ebc7f1aa0efe3c5461151b8b59d1e5b9
|
| --- /dev/null
|
| +++ b/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc
|
| @@ -0,0 +1,173 @@
|
| +// Copyright 2014 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/local_discovery/wifi/bootstrapping_device_lister.h"
|
| +
|
| +#include <algorithm>
|
| +#include <iterator>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "base/strings/string_util.h"
|
| +
|
| +namespace local_discovery {
|
| +
|
| +namespace wifi {
|
| +
|
| +namespace {
|
| +
|
| +const char kPrivetSuffix[] = "prv";
|
| +// 3 for prv, 3 for type, one for connection status.
|
| +const size_t kPrivetCharactersAfterSeparator = 7;
|
| +
|
| +const struct {
|
| + const char* const short_name;
|
| + const char* const long_name;
|
| +} kPrivetShortNames[] = {{"cam", "camera"}, {"pri", "printer"}};
|
| +
|
| +const struct {
|
| + char signifier;
|
| + BootstrappingDeviceDescription::ConnectionStatus status;
|
| +} kPrivetConnectionStatuses[] = {
|
| + {'C', BootstrappingDeviceDescription::CONNECTING},
|
| + {'F', BootstrappingDeviceDescription::OFFLINE},
|
| + {'L', BootstrappingDeviceDescription::LOCAL_ONLY},
|
| + {'N', BootstrappingDeviceDescription::NOT_CONFIGURED},
|
| + {'O', BootstrappingDeviceDescription::ONLINE},
|
| +};
|
| +
|
| +const char kPrivetDeviceLongName[] = "device";
|
| +
|
| +std::string ExpandDeviceKind(const std::string& device_kind_short) {
|
| + for (size_t i = 0; i < arraysize(kPrivetShortNames); i++) {
|
| + if (device_kind_short == kPrivetShortNames[i].short_name) {
|
| + return kPrivetShortNames[i].long_name;
|
| + }
|
| + }
|
| + return kPrivetDeviceLongName;
|
| +}
|
| +
|
| +BootstrappingDeviceDescription::ConnectionStatus GetConnectionStatus(
|
| + char signifier) {
|
| + for (size_t i = 0; i < arraysize(kPrivetConnectionStatuses); i++) {
|
| + if (signifier == kPrivetConnectionStatuses[i].signifier) {
|
| + return kPrivetConnectionStatuses[i].status;
|
| + }
|
| + }
|
| +
|
| + LOG(WARNING) << "Unknown WiFi connection state signifier " << signifier;
|
| + return BootstrappingDeviceDescription::NOT_CONFIGURED;
|
| +}
|
| +
|
| +// Return true if the SSID is a privet ssid and fills |description| with its
|
| +// attributes.
|
| +bool ParsePrivetSSID(const std::string& internal_id,
|
| + const std::string& ssid,
|
| + BootstrappingDeviceDescription* description) {
|
| + if (!EndsWith(ssid, kPrivetSuffix, true))
|
| + return false;
|
| +
|
| + size_t at_pos = ssid.length() - kPrivetCharactersAfterSeparator - 1;
|
| +
|
| + if (ssid[at_pos] != '@' || ssid.find('@', at_pos + 1) != std::string::npos)
|
| + return false;
|
| +
|
| + description->device_network_id = internal_id;
|
| + description->device_ssid = ssid;
|
| +
|
| + description->device_name = ssid.substr(0, at_pos);
|
| + description->device_kind = ExpandDeviceKind(ssid.substr(at_pos + 1, 3));
|
| + description->connection_status = GetConnectionStatus(ssid.at(at_pos + 4));
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +BootstrappingDeviceDescription::BootstrappingDeviceDescription()
|
| + : connection_status(NOT_CONFIGURED) {
|
| +}
|
| +
|
| +BootstrappingDeviceDescription::~BootstrappingDeviceDescription() {
|
| +}
|
| +
|
| +BootstrappingDeviceLister::BootstrappingDeviceLister(
|
| + WifiManager* wifi_manager,
|
| + const UpdateCallback& update_callback)
|
| + : wifi_manager_(wifi_manager),
|
| + update_callback_(update_callback),
|
| + started_(false),
|
| + weak_factory_(this) {
|
| +}
|
| +
|
| +BootstrappingDeviceLister::~BootstrappingDeviceLister() {
|
| + if (started_)
|
| + wifi_manager_->RemoveNetworkListObserver(this);
|
| +}
|
| +
|
| +void BootstrappingDeviceLister::Start() {
|
| + DCHECK(!started_);
|
| +
|
| + started_ = true;
|
| +
|
| + wifi_manager_->AddNetworkListObserver(this);
|
| +
|
| + wifi_manager_->GetSSIDList(
|
| + base::Bind(&BootstrappingDeviceLister::OnNetworkListChanged,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void BootstrappingDeviceLister::OnNetworkListChanged(
|
| + const std::vector<NetworkProperties>& ssids) {
|
| + ActiveDeviceList new_devices;
|
| +
|
| + for (size_t i = 0; i < ssids.size(); i++) {
|
| + new_devices.push_back(make_pair(ssids[i].ssid, ssids[i].guid));
|
| + }
|
| +
|
| + std::sort(new_devices.begin(), new_devices.end());
|
| +
|
| + base::WeakPtr<BootstrappingDeviceLister> weak_this =
|
| + weak_factory_.GetWeakPtr();
|
| + // Find new or changed SSIDs
|
| + UpdateChangedSSIDs(true, new_devices, active_devices_);
|
| + if (!weak_this)
|
| + return;
|
| +
|
| + // Find removed SSIDs
|
| + UpdateChangedSSIDs(false, active_devices_, new_devices);
|
| + if (!weak_this)
|
| + return;
|
| +
|
| + active_devices_.swap(new_devices);
|
| +}
|
| +
|
| +void BootstrappingDeviceLister::UpdateChangedSSIDs(
|
| + bool available,
|
| + const ActiveDeviceList& changed,
|
| + const ActiveDeviceList& original) {
|
| + base::WeakPtr<BootstrappingDeviceLister> weak_this =
|
| + weak_factory_.GetWeakPtr();
|
| +
|
| + ActiveDeviceList changed_devices;
|
| + std::set_difference(changed.begin(),
|
| + changed.end(),
|
| + original.begin(),
|
| + original.end(),
|
| + std::back_inserter(changed_devices));
|
| +
|
| + for (ActiveDeviceList::iterator i = changed_devices.begin();
|
| + weak_this && i != changed_devices.end();
|
| + i++) {
|
| + BootstrappingDeviceDescription description;
|
| + if (ParsePrivetSSID(i->second, i->first, &description)) {
|
| + update_callback_.Run(available, description);
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace wifi
|
| +
|
| +} // namespace local_discovery
|
|
|