// Copyright 2013 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/dbus/fake_shill_manager_client.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_shill_device_client.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_ipconfig_client.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/dbus/shill_property_changed_observer.h"
#include "chromeos/dbus/shill_service_client.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/values_util.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

// Allow parsed command line option 'tdls_busy' to set the fake busy count.
int s_tdls_busy_count = 0;
int s_extra_wifi_networks = 0;

// For testing dynamic WEP networks (uses wifi2).
bool s_dynamic_wep = false;

// Used to compare values for finding entries to erase in a ListValue.
// (ListValue only implements a const_iterator version of Find).
struct ValueEquals {
  explicit ValueEquals(const base::Value* first) : first_(first) {}
  bool operator()(const base::Value* second) const {
    return first_->Equals(second);
  }
  const base::Value* first_;
};

// Appends string entries from |service_list_in| whose entries in ServiceClient
// have Type |match_type| to one of the output lists based on the entry's State.
void AppendServicesForType(
    const base::ListValue* service_list_in,
    const char* match_type,
    bool technology_enabled,
    std::vector<std::string>* active_service_list_out,
    std::vector<std::string>* inactive_service_list_out,
    std::vector<std::string>* disabled_service_list_out) {
  ShillServiceClient::TestInterface* service_client =
      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
  for (base::ListValue::const_iterator iter = service_list_in->begin();
       iter != service_list_in->end(); ++iter) {
    std::string service_path;
    if (!(*iter)->GetAsString(&service_path))
      continue;
    const base::DictionaryValue* properties =
        service_client->GetServiceProperties(service_path);
    if (!properties) {
      LOG(ERROR) << "Properties not found for service: " << service_path;
      continue;
    }
    std::string type;
    properties->GetString(shill::kTypeProperty, &type);
    if (type != match_type)
      continue;
    bool visible = false;
    if (technology_enabled)
      properties->GetBoolean(shill::kVisibleProperty, &visible);
    if (!visible) {
      disabled_service_list_out->push_back(service_path);
      continue;
    }
    std::string state;
    properties->GetString(shill::kStateProperty, &state);
    if (state == shill::kStateOnline ||
        state == shill::kStateAssociation ||
        state == shill::kStateConfiguration ||
        state == shill::kStatePortal ||
        state == shill::kStateReady) {
      active_service_list_out->push_back(service_path);
    } else {
      inactive_service_list_out->push_back(service_path);
    }
  }
}

void LogErrorCallback(const std::string& error_name,
                      const std::string& error_message) {
  LOG(ERROR) << error_name << ": " << error_message;
}

bool IsConnectedState(const std::string& state) {
  return state == shill::kStateOnline || state == shill::kStatePortal ||
         state == shill::kStateReady;
}

void UpdatePortaledWifiState(const std::string& service_path) {
  DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()
      ->SetServiceProperty(service_path,
                           shill::kStateProperty,
                           base::StringValue(shill::kStatePortal));
}

bool IsCellularTechnology(const std::string& type) {
  return (type == shill::kNetworkTechnology1Xrtt ||
          type == shill::kNetworkTechnologyEvdo ||
          type == shill::kNetworkTechnologyGsm ||
          type == shill::kNetworkTechnologyGprs ||
          type == shill::kNetworkTechnologyEdge ||
          type == shill::kNetworkTechnologyUmts ||
          type == shill::kNetworkTechnologyHspa ||
          type == shill::kNetworkTechnologyHspaPlus ||
          type == shill::kNetworkTechnologyLte ||
          type == shill::kNetworkTechnologyLteAdvanced);
}

const char* kTechnologyUnavailable = "unavailable";
const char* kNetworkActivated = "activated";
const char* kNetworkDisabled = "disabled";
const char* kCellularServicePath = "/service/cellular1";
const char* kRoamingRequired = "required";

}  // namespace

// static
const char FakeShillManagerClient::kFakeEthernetNetworkGuid[] = "eth1_guid";

FakeShillManagerClient::FakeShillManagerClient()
    : interactive_delay_(0),
      cellular_technology_(shill::kNetworkTechnologyGsm),
      weak_ptr_factory_(this) {
  ParseCommandLineSwitch();
}

FakeShillManagerClient::~FakeShillManagerClient() {}

// ShillManagerClient overrides.

void FakeShillManagerClient::Init(dbus::Bus* bus) {}

void FakeShillManagerClient::AddPropertyChangedObserver(
    ShillPropertyChangedObserver* observer) {
  observer_list_.AddObserver(observer);
}

void FakeShillManagerClient::RemovePropertyChangedObserver(
    ShillPropertyChangedObserver* observer) {
  observer_list_.RemoveObserver(observer);
}

void FakeShillManagerClient::GetProperties(
    const DictionaryValueCallback& callback) {
  VLOG(1) << "Manager.GetProperties";
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&FakeShillManagerClient::PassStubProperties,
                            weak_ptr_factory_.GetWeakPtr(), callback));
}

void FakeShillManagerClient::GetNetworksForGeolocation(
    const DictionaryValueCallback& callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(&FakeShillManagerClient::PassStubGeoNetworks,
                            weak_ptr_factory_.GetWeakPtr(), callback));
}

void FakeShillManagerClient::SetProperty(const std::string& name,
                                         const base::Value& value,
                                         const base::Closure& callback,
                                         const ErrorCallback& error_callback) {
  VLOG(2) << "SetProperty: " << name;
  stub_properties_.SetWithoutPathExpansion(name, value.DeepCopy());
  CallNotifyObserversPropertyChanged(name);
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
}

void FakeShillManagerClient::RequestScan(const std::string& type,
                                         const base::Closure& callback,
                                         const ErrorCallback& error_callback) {
  VLOG(1) << "RequestScan: " << type;
  // For Stub purposes, default to a Wifi scan.
  std::string device_type = shill::kTypeWifi;
  if (!type.empty())
    device_type = type;
  ShillDeviceClient::TestInterface* device_client =
      DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
  std::string device_path = device_client->GetDevicePathForType(device_type);
  if (!device_path.empty()) {
    device_client->SetDeviceProperty(
        device_path, shill::kScanningProperty, base::FundamentalValue(true));
  }
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&FakeShillManagerClient::ScanCompleted,
                 weak_ptr_factory_.GetWeakPtr(), device_path, callback),
      base::TimeDelta::FromSeconds(interactive_delay_));
}

void FakeShillManagerClient::EnableTechnology(
    const std::string& type,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  base::ListValue* enabled_list = NULL;
  if (!stub_properties_.GetListWithoutPathExpansion(
          shill::kAvailableTechnologiesProperty, &enabled_list)) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(error_callback, "StubError", "Property not found"));
    return;
  }
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&FakeShillManagerClient::SetTechnologyEnabled,
                 weak_ptr_factory_.GetWeakPtr(), type, callback, true),
      base::TimeDelta::FromSeconds(interactive_delay_));
}

void FakeShillManagerClient::DisableTechnology(
    const std::string& type,
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  base::ListValue* enabled_list = NULL;
  if (!stub_properties_.GetListWithoutPathExpansion(
          shill::kAvailableTechnologiesProperty, &enabled_list)) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::Bind(error_callback, "StubError", "Property not found"));
    return;
  }
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&FakeShillManagerClient::SetTechnologyEnabled,
                 weak_ptr_factory_.GetWeakPtr(), type, callback, false),
      base::TimeDelta::FromSeconds(interactive_delay_));
}

void FakeShillManagerClient::ConfigureService(
    const base::DictionaryValue& properties,
    const ObjectPathCallback& callback,
    const ErrorCallback& error_callback) {
  ShillServiceClient::TestInterface* service_client =
      DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();

  std::string guid;
  std::string type;
  if (!properties.GetString(shill::kGuidProperty, &guid) ||
      !properties.GetString(shill::kTypeProperty, &type)) {
    LOG(ERROR) << "ConfigureService requires GUID and Type to be defined";
    // If the properties aren't filled out completely, then just return an empty
    // object path.
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(callback, dbus::ObjectPath()));
    return;
  }

  // For the purposes of this stub, we're going to assume that the GUID property
  // is set to the service path because we don't want to re-implement Shill's
  // property matching magic here.
  std::string service_path = guid;

  std::string ipconfig_path;
  properties.GetString(shill::kIPConfigProperty, &ipconfig_path);

  // Merge the new properties with existing properties, if any.
  const base::DictionaryValue* existing_properties =
      service_client->GetServiceProperties(service_path);
  if (!existing_properties) {
    // Add a new service to the service client stub because none exists, yet.
    // This calls AddManagerService.
    service_client->AddServiceWithIPConfig(service_path,
                                           guid /* guid */,
                                           guid /* name */,
                                           type,
                                           shill::kStateIdle,
                                           ipconfig_path,
                                           true /* visible */);
    existing_properties = service_client->GetServiceProperties(service_path);
  }

  scoped_ptr<base::DictionaryValue> merged_properties(
      existing_properties->DeepCopy());
  merged_properties->MergeDictionary(&properties);

  // Now set all the properties.
  for (base::DictionaryValue::Iterator iter(*merged_properties);
       !iter.IsAtEnd(); iter.Advance()) {
    service_client->SetServiceProperty(service_path, iter.key(), iter.value());
  }

  // If the Profile property is set, add it to ProfileClient.
  std::string profile_path;
  merged_properties->GetStringWithoutPathExpansion(shill::kProfileProperty,
                                                   &profile_path);
  if (!profile_path.empty()) {
    DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface()->
        AddService(profile_path, service_path);
  }

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(callback, dbus::ObjectPath(service_path)));
}

void FakeShillManagerClient::ConfigureServiceForProfile(
    const dbus::ObjectPath& profile_path,
    const base::DictionaryValue& properties,
    const ObjectPathCallback& callback,
    const ErrorCallback& error_callback) {
  std::string profile_property;
  properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
                                           &profile_property);
  CHECK(profile_property == profile_path.value());
  ConfigureService(properties, callback, error_callback);
}


void FakeShillManagerClient::GetService(
    const base::DictionaryValue& properties,
    const ObjectPathCallback& callback,
    const ErrorCallback& error_callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(callback, dbus::ObjectPath()));
}

void FakeShillManagerClient::VerifyDestination(
    const VerificationProperties& properties,
    const BooleanCallback& callback,
    const ErrorCallback& error_callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                base::Bind(callback, true));
}

void FakeShillManagerClient::VerifyAndEncryptCredentials(
    const VerificationProperties& properties,
    const std::string& service_path,
    const StringCallback& callback,
    const ErrorCallback& error_callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(callback, "encrypted_credentials"));
}

void FakeShillManagerClient::VerifyAndEncryptData(
    const VerificationProperties& properties,
    const std::string& data,
    const StringCallback& callback,
    const ErrorCallback& error_callback) {
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::Bind(callback, "encrypted_data"));
}

void FakeShillManagerClient::ConnectToBestServices(
    const base::Closure& callback,
    const ErrorCallback& error_callback) {
  if (best_service_.empty()) {
    VLOG(1) << "No 'best' service set.";
    return;
  }

  DBusThreadManager::Get()->GetShillServiceClient()->Connect(
      dbus::ObjectPath(best_service_), callback, error_callback);
}

ShillManagerClient::TestInterface* FakeShillManagerClient::GetTestInterface() {
  return this;
}

// ShillManagerClient::TestInterface overrides.

void FakeShillManagerClient::AddDevice(const std::string& device_path) {
  if (GetListProperty(shill::kDevicesProperty)
          ->AppendIfNotPresent(new base::StringValue(device_path))) {
    CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
  }
}

void FakeShillManagerClient::RemoveDevice(const std::string& device_path) {
  base::StringValue device_path_value(device_path);
  if (GetListProperty(shill::kDevicesProperty)->Remove(
      device_path_value, NULL)) {
    CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
  }
}

void FakeShillManagerClient::ClearDevices() {
  GetListProperty(shill::kDevicesProperty)->Clear();
  CallNotifyObserversPropertyChanged(shill::kDevicesProperty);
}

void FakeShillManagerClient::AddTechnology(const std::string& type,
                                           bool enabled) {
  if (GetListProperty(shill::kAvailableTechnologiesProperty)
          ->AppendIfNotPresent(new base::StringValue(type))) {
    CallNotifyObserversPropertyChanged(
        shill::kAvailableTechnologiesProperty);
  }
  if (enabled &&
      GetListProperty(shill::kEnabledTechnologiesProperty)
          ->AppendIfNotPresent(new base::StringValue(type))) {
    CallNotifyObserversPropertyChanged(
        shill::kEnabledTechnologiesProperty);
  }
}

void FakeShillManagerClient::RemoveTechnology(const std::string& type) {
  base::StringValue type_value(type);
  if (GetListProperty(shill::kAvailableTechnologiesProperty)->Remove(
      type_value, NULL)) {
    CallNotifyObserversPropertyChanged(
        shill::kAvailableTechnologiesProperty);
  }
  if (GetListProperty(shill::kEnabledTechnologiesProperty)->Remove(
      type_value, NULL)) {
    CallNotifyObserversPropertyChanged(
        shill::kEnabledTechnologiesProperty);
  }
}

void FakeShillManagerClient::SetTechnologyInitializing(const std::string& type,
                                                       bool initializing) {
  if (initializing) {
    if (GetListProperty(shill::kUninitializedTechnologiesProperty)
            ->AppendIfNotPresent(new base::StringValue(type))) {
      CallNotifyObserversPropertyChanged(
          shill::kUninitializedTechnologiesProperty);
    }
  } else {
    if (GetListProperty(shill::kUninitializedTechnologiesProperty)->Remove(
            base::StringValue(type), NULL)) {
      CallNotifyObserversPropertyChanged(
          shill::kUninitializedTechnologiesProperty);
    }
  }
}

void FakeShillManagerClient::AddGeoNetwork(
    const std::string& technology,
    const base::DictionaryValue& network) {
  base::ListValue* list_value = NULL;
  if (!stub_geo_networks_.GetListWithoutPathExpansion(technology,
                                                      &list_value)) {
    list_value = new base::ListValue;
    stub_geo_networks_.SetWithoutPathExpansion(technology, list_value);
  }
  list_value->Append(network.DeepCopy());
}

void FakeShillManagerClient::AddProfile(const std::string& profile_path) {
  const char* key = shill::kProfilesProperty;
  if (GetListProperty(key)
          ->AppendIfNotPresent(new base::StringValue(profile_path))) {
    CallNotifyObserversPropertyChanged(key);
  }
}

void FakeShillManagerClient::ClearProperties() {
  stub_properties_.Clear();
}

void FakeShillManagerClient::SetManagerProperty(const std::string& key,
                                                const base::Value& value) {
  SetProperty(key, value,
              base::Bind(&base::DoNothing), base::Bind(&LogErrorCallback));
}

void FakeShillManagerClient::AddManagerService(
    const std::string& service_path,
    bool notify_observers) {
  VLOG(2) << "AddManagerService: " << service_path;
  GetListProperty(shill::kServiceCompleteListProperty)
      ->AppendIfNotPresent(new base::StringValue(service_path));
  SortManagerServices(false);
  if (notify_observers)
    CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
}

void FakeShillManagerClient::RemoveManagerService(
    const std::string& service_path) {
  VLOG(2) << "RemoveManagerService: " << service_path;
  base::StringValue service_path_value(service_path);
  GetListProperty(shill::kServiceCompleteListProperty)->Remove(
      service_path_value, NULL);
  CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
}

void FakeShillManagerClient::ClearManagerServices() {
  VLOG(1) << "ClearManagerServices";
  GetListProperty(shill::kServiceCompleteListProperty)->Clear();
  CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
}

void FakeShillManagerClient::ServiceStateChanged(
    const std::string& service_path,
    const std::string& state) {
  if (service_path == default_service_ && !IsConnectedState(state)) {
    // Default service is no longer connected; clear.
    default_service_.clear();
    base::StringValue default_service_value(default_service_);
    SetManagerProperty(shill::kDefaultServiceProperty, default_service_value);
  }
}

void FakeShillManagerClient::SortManagerServices(bool notify) {
  VLOG(1) << "SortManagerServices";
  static const char* ordered_types[] = {shill::kTypeEthernet,
                                        shill::kTypeEthernetEap,
                                        shill::kTypeWifi,
                                        shill::kTypeCellular,
                                        shill::kTypeWimax,
                                        shill::kTypeVPN};

  base::ListValue* complete_list =
      GetListProperty(shill::kServiceCompleteListProperty);
  if (complete_list->empty())
    return;
  scoped_ptr<base::ListValue> prev_complete_list(complete_list->DeepCopy());

  std::vector<std::string> active_services;
  std::vector<std::string> inactive_services;
  std::vector<std::string> disabled_services;
  for (size_t i = 0; i < arraysize(ordered_types); ++i) {
    AppendServicesForType(complete_list,
                          ordered_types[i],
                          TechnologyEnabled(ordered_types[i]),
                          &active_services,
                          &inactive_services,
                          &disabled_services);
  }
  complete_list->Clear();
  for (size_t i = 0; i < active_services.size(); ++i)
    complete_list->AppendString(active_services[i]);
  for (size_t i = 0; i < inactive_services.size(); ++i)
    complete_list->AppendString(inactive_services[i]);
  for (size_t i = 0; i < disabled_services.size(); ++i)
    complete_list->AppendString(disabled_services[i]);

  if (notify && !complete_list->Equals(prev_complete_list.get()))
    CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);

  // Set the first active service as the Default service.
  std::string new_default_service;
  if (!active_services.empty()) {
    ShillServiceClient::TestInterface* service_client =
        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
    std::string service_path = active_services[0];
    const base::DictionaryValue* properties =
        service_client->GetServiceProperties(service_path);
    if (!properties) {
      LOG(ERROR) << "Properties not found for service: " << service_path;
    } else {
      std::string state;
      properties->GetString(shill::kStateProperty, &state);
      if (IsConnectedState(state))
        new_default_service = service_path;
    }
  }
  if (default_service_ != new_default_service) {
    default_service_ = new_default_service;
    base::StringValue default_service_value(default_service_);
    SetManagerProperty(shill::kDefaultServiceProperty, default_service_value);
  }
}

int FakeShillManagerClient::GetInteractiveDelay() const {
  return interactive_delay_;
}

void FakeShillManagerClient::SetBestServiceToConnect(
    const std::string& service_path) {
  best_service_ = service_path;
}

void FakeShillManagerClient::SetupDefaultEnvironment() {
  // Bail out from setup if there is no message loop. This will be the common
  // case for tests that are not testing Shill.
  if (!base::ThreadTaskRunnerHandle::IsSet())
    return;

  DBusThreadManager* dbus_manager = DBusThreadManager::Get();
  ShillServiceClient::TestInterface* services =
      dbus_manager->GetShillServiceClient()->GetTestInterface();
  DCHECK(services);
  ShillProfileClient::TestInterface* profiles =
      dbus_manager->GetShillProfileClient()->GetTestInterface();
  DCHECK(profiles);
  ShillDeviceClient::TestInterface* devices =
      dbus_manager->GetShillDeviceClient()->GetTestInterface();
  DCHECK(devices);
  ShillIPConfigClient::TestInterface* ip_configs =
      dbus_manager->GetShillIPConfigClient()->GetTestInterface();
  DCHECK(ip_configs);

  const std::string shared_profile = ShillProfileClient::GetSharedProfilePath();
  profiles->AddProfile(shared_profile, std::string());

  const bool add_to_visible = true;

  // IPConfigs
  base::DictionaryValue ipconfig_v4_dictionary;
  ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
      shill::kAddressProperty, "100.0.0.1");
  ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
      shill::kGatewayProperty, "100.0.0.2");
  ipconfig_v4_dictionary.SetIntegerWithoutPathExpansion(
      shill::kPrefixlenProperty, 1);
  ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
      shill::kMethodProperty, shill::kTypeIPv4);
  ipconfig_v4_dictionary.SetStringWithoutPathExpansion(
      shill::kWebProxyAutoDiscoveryUrlProperty, "http://wpad.com/wpad.dat");
  ip_configs->AddIPConfig("ipconfig_v4_path", ipconfig_v4_dictionary);
  base::DictionaryValue ipconfig_v6_dictionary;
  ipconfig_v6_dictionary.SetStringWithoutPathExpansion(
      shill::kAddressProperty, "0:0:0:0:100:0:0:1");
  ipconfig_v6_dictionary.SetStringWithoutPathExpansion(
      shill::kMethodProperty, shill::kTypeIPv6);
  ip_configs->AddIPConfig("ipconfig_v6_path", ipconfig_v6_dictionary);

  bool enabled;
  std::string state;

  // Ethernet
  state = GetInitialStateForType(shill::kTypeEthernet, &enabled);
  if (state == shill::kStateOnline || state == shill::kStateIdle) {
    AddTechnology(shill::kTypeEthernet, enabled);
    devices->AddDevice(
        "/device/eth1", shill::kTypeEthernet, "stub_eth_device1");
    devices->SetDeviceProperty("/device/eth1",
                               shill::kAddressProperty,
                               base::StringValue("0123456789ab"));
    base::ListValue eth_ip_configs;
    eth_ip_configs.AppendString("ipconfig_v4_path");
    eth_ip_configs.AppendString("ipconfig_v6_path");
    devices->SetDeviceProperty("/device/eth1",
                               shill::kIPConfigsProperty,
                               eth_ip_configs);
    const std::string kFakeEthernetNetworkPath = "/service/eth1";
    services->AddService(kFakeEthernetNetworkPath,
                         kFakeEthernetNetworkGuid,
                         "eth1" /* name */,
                         shill::kTypeEthernet,
                         state,
                         add_to_visible);
    profiles->AddService(shared_profile, kFakeEthernetNetworkPath);
  }

  // Wifi
  if (s_tdls_busy_count != 0) {
    DBusThreadManager::Get()
        ->GetShillDeviceClient()
        ->GetTestInterface()
        ->SetTDLSBusyCount(s_tdls_busy_count);
  }

  state = GetInitialStateForType(shill::kTypeWifi, &enabled);
  if (state != kTechnologyUnavailable) {
    bool portaled = false;
    if (state == shill::kStatePortal) {
      portaled = true;
      state = shill::kStateIdle;
    }
    AddTechnology(shill::kTypeWifi, enabled);
    devices->AddDevice("/device/wifi1", shill::kTypeWifi, "stub_wifi_device1");
    devices->SetDeviceProperty("/device/wifi1",
                               shill::kAddressProperty,
                               base::StringValue("23456789abcd"));
    base::ListValue wifi_ip_configs;
    wifi_ip_configs.AppendString("ipconfig_v4_path");
    wifi_ip_configs.AppendString("ipconfig_v6_path");
    devices->SetDeviceProperty("/device/wifi1",
                               shill::kIPConfigsProperty,
                               wifi_ip_configs);

    const std::string kWifi1Path = "/service/wifi1";
    services->AddService(kWifi1Path,
                         "wifi1_guid",
                         "wifi1" /* name */,
                         shill::kTypeWifi,
                         state,
                         add_to_visible);
    services->SetServiceProperty(kWifi1Path,
                                 shill::kSecurityClassProperty,
                                 base::StringValue(shill::kSecurityWep));
    services->SetServiceProperty(kWifi1Path,
                                 shill::kConnectableProperty,
                                 base::FundamentalValue(true));
    profiles->AddService(shared_profile, kWifi1Path);

    const std::string kWifi2Path = "/service/wifi2";
    services->AddService(kWifi2Path, "wifi2_guid",
                         s_dynamic_wep ? "wifi2_WEP" : "wifi2_PSK" /* name */,
                         shill::kTypeWifi, shill::kStateIdle, add_to_visible);
    if (s_dynamic_wep) {
      services->SetServiceProperty(kWifi2Path, shill::kSecurityClassProperty,
                                   base::StringValue(shill::kSecurityWep));
      services->SetServiceProperty(
          kWifi2Path, shill::kEapKeyMgmtProperty,
          base::StringValue(shill::kKeyManagementIEEE8021X));
      services->SetServiceProperty(kWifi2Path, shill::kEapMethodProperty,
                                   base::StringValue(shill::kEapMethodPEAP));
      services->SetServiceProperty(kWifi2Path, shill::kEapIdentityProperty,
                                   base::StringValue("John Doe"));
    } else {
      services->SetServiceProperty(kWifi2Path, shill::kSecurityClassProperty,
                                   base::StringValue(shill::kSecurityPsk));
    }
    services->SetServiceProperty(
        kWifi2Path, shill::kSignalStrengthProperty, base::FundamentalValue(80));
    profiles->AddService(shared_profile, kWifi2Path);

    const std::string kWifi3Path = "/service/wifi3";
    services->AddService(kWifi3Path,
                         "",  /* empty GUID */
                         "wifi3" /* name */,
                         shill::kTypeWifi,
                         shill::kStateIdle,
                         add_to_visible);
    services->SetServiceProperty(
        kWifi3Path, shill::kSignalStrengthProperty, base::FundamentalValue(40));

    if (portaled) {
      const std::string kPortaledWifiPath = "/service/portaled_wifi";
      services->AddService(kPortaledWifiPath, "portaled_wifi_guid",
                           "Portaled Wifi" /* name */, shill::kTypeWifi,
                           shill::kStateIdle, add_to_visible);
      services->SetServiceProperty(kPortaledWifiPath,
                                   shill::kSecurityClassProperty,
                                   base::StringValue(shill::kSecurityNone));
      services->SetConnectBehavior(
          kPortaledWifiPath,
          base::Bind(&UpdatePortaledWifiState, kPortaledWifiPath));
      services->SetServiceProperty(kPortaledWifiPath,
                                   shill::kConnectableProperty,
                                   base::FundamentalValue(true));
      profiles->AddService(shared_profile, kPortaledWifiPath);
    }

    for (int i = 0; i < s_extra_wifi_networks; ++i) {
      int id = 4 + i;
      std::string path = base::StringPrintf("/service/wifi%d", id);
      std::string guid = base::StringPrintf("wifi%d_guid", id);
      std::string name = base::StringPrintf("wifi%d", id);
      services->AddService(path, guid, name, shill::kTypeWifi,
                           shill::kStateIdle, add_to_visible);
    }
  }

  // Wimax
  const std::string kWimaxPath = "/service/wimax1";
  state = GetInitialStateForType(shill::kTypeWimax, &enabled);
  if (state != kTechnologyUnavailable) {
    AddTechnology(shill::kTypeWimax, enabled);
    devices->AddDevice(
        "/device/wimax1", shill::kTypeWimax, "stub_wimax_device1");

    services->AddService(kWimaxPath, "wimax1_guid", "wimax1" /* name */,
                         shill::kTypeWimax, state, add_to_visible);
    services->SetServiceProperty(kWimaxPath, shill::kConnectableProperty,
                                 base::FundamentalValue(true));
    base::FundamentalValue strength_value(80);
    services->SetServiceProperty(kWimaxPath, shill::kSignalStrengthProperty,
                                 strength_value);
    profiles->AddService(shared_profile, kWimaxPath);
  }

  // Cellular
  state = GetInitialStateForType(shill::kTypeCellular, &enabled);
  if (state != kTechnologyUnavailable) {
    bool activated = false;
    if (state == kNetworkActivated) {
      activated = true;
      state = shill::kStateOnline;
    }
    AddTechnology(shill::kTypeCellular, enabled);
    devices->AddDevice(
        "/device/cellular1", shill::kTypeCellular, "stub_cellular_device1");
    devices->SetDeviceProperty("/device/cellular1",
                               shill::kCarrierProperty,
                               base::StringValue(shill::kCarrierSprint));
    base::ListValue carrier_list;
    carrier_list.AppendString(shill::kCarrierSprint);
    carrier_list.AppendString(shill::kCarrierGenericUMTS);
    devices->SetDeviceProperty("/device/cellular1",
                               shill::kSupportedCarriersProperty,
                               carrier_list);
    devices->SetDeviceProperty("/device/cellular1",
                               shill::kSupportNetworkScanProperty,
                               base::FundamentalValue(true));
    if (roaming_state_ == kRoamingRequired) {
      devices->SetDeviceProperty("/device/cellular1",
                                 shill::kProviderRequiresRoamingProperty,
                                 base::FundamentalValue(true));
    }
    if (cellular_technology_ == shill::kNetworkTechnologyGsm) {
      devices->SetDeviceProperty("/device/cellular1",
                                 shill::kSIMPresentProperty,
                                 base::FundamentalValue(true));
      devices->SetSimLocked("/device/cellular1", false);
    }

    services->AddService(kCellularServicePath,
                         "cellular1_guid",
                         "cellular1" /* name */,
                         shill::kTypeCellular,
                         state,
                         add_to_visible);
    base::StringValue technology_value(cellular_technology_);
    devices->SetDeviceProperty("/device/cellular1",
                               shill::kTechnologyFamilyProperty,
                               technology_value);
    services->SetServiceProperty(kCellularServicePath,
                                 shill::kNetworkTechnologyProperty,
                                 technology_value);

    if (activated) {
      services->SetServiceProperty(
          kCellularServicePath,
          shill::kActivationStateProperty,
          base::StringValue(shill::kActivationStateActivated));
      services->SetServiceProperty(kCellularServicePath,
                                   shill::kConnectableProperty,
                                   base::FundamentalValue(true));
    } else {
      services->SetServiceProperty(
          kCellularServicePath,
          shill::kActivationStateProperty,
          base::StringValue(shill::kActivationStateNotActivated));
    }

    std::string shill_roaming_state;
    if (roaming_state_ == kRoamingRequired)
      shill_roaming_state = shill::kRoamingStateRoaming;
    else if (roaming_state_.empty())
      shill_roaming_state = shill::kRoamingStateHome;
    else  // |roaming_state_| is expected to be a valid Shill state.
      shill_roaming_state = roaming_state_;
    services->SetServiceProperty(kCellularServicePath,
                                 shill::kRoamingStateProperty,
                                 base::StringValue(shill_roaming_state));

    base::DictionaryValue apn;
    apn.SetStringWithoutPathExpansion(shill::kApnProperty, "testapn");
    apn.SetStringWithoutPathExpansion(shill::kApnNameProperty, "Test APN");
    apn.SetStringWithoutPathExpansion(shill::kApnLocalizedNameProperty,
                                      "Localized Test APN");
    apn.SetStringWithoutPathExpansion(shill::kApnUsernameProperty, "User1");
    apn.SetStringWithoutPathExpansion(shill::kApnPasswordProperty, "password");
    base::DictionaryValue apn2;
    apn2.SetStringWithoutPathExpansion(shill::kApnProperty, "testapn2");
    services->SetServiceProperty(kCellularServicePath,
                                 shill::kCellularApnProperty, apn);
    services->SetServiceProperty(kCellularServicePath,
                                 shill::kCellularLastGoodApnProperty, apn);
    base::ListValue apn_list;
    apn_list.Append(apn.DeepCopy());
    apn_list.Append(apn2.DeepCopy());
    devices->SetDeviceProperty("/device/cellular1",
                               shill::kCellularApnListProperty, apn_list);

    profiles->AddService(shared_profile, kCellularServicePath);
  }

  // VPN
  state = GetInitialStateForType(shill::kTypeVPN, &enabled);
  if (state != kTechnologyUnavailable) {
    // Set the "Provider" dictionary properties. Note: when setting these in
    // Shill, "Provider.Type", etc keys are used, but when reading the values
    // "Provider" . "Type", etc keys are used. Here we are setting the values
    // that will be read (by the UI, tests, etc).
    base::DictionaryValue provider_properties_openvpn;
    provider_properties_openvpn.SetString(shill::kTypeProperty,
                                          shill::kProviderOpenVpn);
    provider_properties_openvpn.SetString(shill::kHostProperty, "vpn_host");

    services->AddService("/service/vpn1",
                         "vpn1_guid",
                         "vpn1" /* name */,
                         shill::kTypeVPN,
                         state,
                         add_to_visible);
    services->SetServiceProperty(
        "/service/vpn1", shill::kProviderProperty, provider_properties_openvpn);
    profiles->AddService(shared_profile, "/service/vpn1");

    base::DictionaryValue provider_properties_l2tp;
    provider_properties_l2tp.SetString(shill::kTypeProperty,
                                       shill::kProviderL2tpIpsec);
    provider_properties_l2tp.SetString(shill::kHostProperty, "vpn_host2");

    services->AddService("/service/vpn2",
                         "vpn2_guid",
                         "vpn2" /* name */,
                         shill::kTypeVPN,
                         shill::kStateIdle,
                         add_to_visible);
    services->SetServiceProperty(
        "/service/vpn2", shill::kProviderProperty, provider_properties_l2tp);
  }

  // Additional device states
  for (DevicePropertyMap::iterator iter1 = shill_device_property_map_.begin();
       iter1 != shill_device_property_map_.end(); ++iter1) {
    std::string device_type = iter1->first;
    std::string device_path = devices->GetDevicePathForType(device_type);
    for (ShillPropertyMap::iterator iter2 = iter1->second.begin();
         iter2 != iter1->second.end(); ++iter2) {
      devices->SetDeviceProperty(device_path, iter2->first, *(iter2->second));
      delete iter2->second;
    }
  }

  SortManagerServices(true);
}

// Private methods

void FakeShillManagerClient::PassStubProperties(
    const DictionaryValueCallback& callback) const {
  scoped_ptr<base::DictionaryValue> stub_properties(
      stub_properties_.DeepCopy());
  stub_properties->SetWithoutPathExpansion(
      shill::kServiceCompleteListProperty,
      GetEnabledServiceList(shill::kServiceCompleteListProperty));
  callback.Run(DBUS_METHOD_CALL_SUCCESS, *stub_properties);
}

void FakeShillManagerClient::PassStubGeoNetworks(
    const DictionaryValueCallback& callback) const {
  callback.Run(DBUS_METHOD_CALL_SUCCESS, stub_geo_networks_);
}

void FakeShillManagerClient::CallNotifyObserversPropertyChanged(
    const std::string& property) {
  // Avoid unnecessary delayed task if we have no observers (e.g. during
  // initial setup).
  if (!observer_list_.might_have_observers())
    return;
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&FakeShillManagerClient::NotifyObserversPropertyChanged,
                 weak_ptr_factory_.GetWeakPtr(), property));
}

void FakeShillManagerClient::NotifyObserversPropertyChanged(
    const std::string& property) {
  VLOG(1) << "NotifyObserversPropertyChanged: " << property;
  base::Value* value = NULL;
  if (!stub_properties_.GetWithoutPathExpansion(property, &value)) {
    LOG(ERROR) << "Notify for unknown property: " << property;
    return;
  }
  if (property == shill::kServiceCompleteListProperty) {
    scoped_ptr<base::ListValue> services(GetEnabledServiceList(property));
    FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
                      observer_list_,
                      OnPropertyChanged(property, *(services.get())));
    return;
  }
  FOR_EACH_OBSERVER(ShillPropertyChangedObserver,
                    observer_list_,
                    OnPropertyChanged(property, *value));
}

base::ListValue* FakeShillManagerClient::GetListProperty(
    const std::string& property) {
  base::ListValue* list_property = NULL;
  if (!stub_properties_.GetListWithoutPathExpansion(
      property, &list_property)) {
    list_property = new base::ListValue;
    stub_properties_.SetWithoutPathExpansion(property, list_property);
  }
  return list_property;
}

bool FakeShillManagerClient::TechnologyEnabled(const std::string& type) const {
  if (type == shill::kTypeVPN)
    return true;  // VPN is always "enabled" since there is no associated device
  if (type == shill::kTypeEthernetEap)
    return true;
  bool enabled = false;
  const base::ListValue* technologies;
  if (stub_properties_.GetListWithoutPathExpansion(
          shill::kEnabledTechnologiesProperty, &technologies)) {
    base::StringValue type_value(type);
    if (technologies->Find(type_value) != technologies->end())
      enabled = true;
  }
  return enabled;
}

void FakeShillManagerClient::SetTechnologyEnabled(
    const std::string& type,
    const base::Closure& callback,
    bool enabled) {
  base::ListValue* enabled_list =
      GetListProperty(shill::kEnabledTechnologiesProperty);
  if (enabled)
    enabled_list->AppendIfNotPresent(new base::StringValue(type));
  else
    enabled_list->Remove(base::StringValue(type), NULL);
  CallNotifyObserversPropertyChanged(
      shill::kEnabledTechnologiesProperty);
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
  // May affect available services.
  SortManagerServices(true);
}

base::ListValue* FakeShillManagerClient::GetEnabledServiceList(
    const std::string& property) const {
  base::ListValue* new_service_list = new base::ListValue;
  const base::ListValue* service_list;
  if (stub_properties_.GetListWithoutPathExpansion(property, &service_list)) {
    ShillServiceClient::TestInterface* service_client =
        DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
    for (base::ListValue::const_iterator iter = service_list->begin();
         iter != service_list->end(); ++iter) {
      std::string service_path;
      if (!(*iter)->GetAsString(&service_path))
        continue;
      const base::DictionaryValue* properties =
          service_client->GetServiceProperties(service_path);
      if (!properties) {
        LOG(ERROR) << "Properties not found for service: " << service_path;
        continue;
      }
      std::string type;
      properties->GetString(shill::kTypeProperty, &type);
      if (TechnologyEnabled(type))
        new_service_list->Append((*iter)->DeepCopy());
    }
  }
  return new_service_list;
}

void FakeShillManagerClient::ScanCompleted(const std::string& device_path,
                                           const base::Closure& callback) {
  if (!device_path.empty()) {
    DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface()->
        SetDeviceProperty(device_path,
                          shill::kScanningProperty,
                          base::FundamentalValue(false));
  }
  VLOG(1) << "ScanCompleted";
  CallNotifyObserversPropertyChanged(shill::kServiceCompleteListProperty);
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
}

void FakeShillManagerClient::ParseCommandLineSwitch() {
  // Default setup
  SetInitialNetworkState(shill::kTypeEthernet, shill::kStateOnline);
  SetInitialNetworkState(shill::kTypeWifi, shill::kStateOnline);
  SetInitialNetworkState(shill::kTypeCellular, shill::kStateIdle);
  SetInitialNetworkState(shill::kTypeVPN, shill::kStateIdle);

  // Parse additional options
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (!command_line->HasSwitch(switches::kShillStub))
    return;

  std::string option_str =
      command_line->GetSwitchValueASCII(switches::kShillStub);
  VLOG(1) << "Parsing command line:" << option_str;
  base::StringPairs string_pairs;
  base::SplitStringIntoKeyValuePairs(option_str, '=', ',', &string_pairs);
  for (base::StringPairs::iterator iter = string_pairs.begin();
       iter != string_pairs.end(); ++iter) {
    ParseOption((*iter).first, (*iter).second);
  }
}

bool FakeShillManagerClient::ParseOption(const std::string& arg0,
                                         const std::string& arg1) {
  VLOG(1) << "Parsing command line option: '" << arg0 << "=" << arg1 << "'";
  if ((arg0 == "clear" || arg0 == "reset") && arg1 == "1") {
    shill_initial_state_map_.clear();
    return true;
  } else if (arg0 == "interactive") {
    int seconds = 3;
    if (!arg1.empty())
      base::StringToInt(arg1, &seconds);
    interactive_delay_ = seconds;
    return true;
  } else if (arg0 == "sim_lock") {
    bool locked = (arg1 == "1");
    base::DictionaryValue* simlock_dict = new base::DictionaryValue;
    simlock_dict->SetBoolean(shill::kSIMLockEnabledProperty, true);
    std::string lock_type = locked ? shill::kSIMLockPin : "";
    simlock_dict->SetString(shill::kSIMLockTypeProperty, lock_type);
    if (locked) {
      simlock_dict->SetInteger(shill::kSIMLockRetriesLeftProperty,
                               FakeShillDeviceClient::kSimPinRetryCount);
    }
    shill_device_property_map_[shill::kTypeCellular]
                              [shill::kSIMLockStatusProperty] = simlock_dict;
    shill_device_property_map_
        [shill::kTypeCellular][shill::kTechnologyFamilyProperty] =
            new base::StringValue(shill::kNetworkTechnologyGsm);
    return true;
  } else if (arg0 == "sim_present") {
    bool present = (arg1 == "1");
    base::FundamentalValue* sim_present = new base::FundamentalValue(present);
    shill_device_property_map_[shill::kTypeCellular]
                              [shill::kSIMPresentProperty] = sim_present;
    return true;
  } else if (arg0 == "tdls_busy") {
    if (!arg1.empty())
      base::StringToInt(arg1, &s_tdls_busy_count);
    else
      s_tdls_busy_count = 1;
    return true;
  } else if (arg0 == "roaming") {
    // "home", "roaming", or "required"
    roaming_state_ = arg1;
    return true;
  } else if (arg0 == "dynamic_wep" && arg1 == "1") {
    s_dynamic_wep = true;
    return true;
  }
  return SetInitialNetworkState(arg0, arg1);
}

bool FakeShillManagerClient::SetInitialNetworkState(
    std::string type_arg,
    const std::string& state_arg) {
  int state_arg_as_int = -1;
  base::StringToInt(state_arg, &state_arg_as_int);

  std::string state;
  if (state_arg.empty() || state_arg == "1" || state_arg == "on" ||
      state_arg == "enabled" || state_arg == "connected" ||
      state_arg == "online") {
    // Enabled and connected (default value)
    state = shill::kStateOnline;
  } else if (state_arg == "0" || state_arg == "off" ||
             state_arg == "inactive" || state_arg == shill::kStateIdle) {
    // Technology enabled, services are created but are not connected.
    state = shill::kStateIdle;
  } else if (type_arg == shill::kTypeWifi && state_arg_as_int > 1) {
    // Enabled and connected, add extra wifi networks.
    state = shill::kStateOnline;
    s_extra_wifi_networks = state_arg_as_int - 1;
  } else if (state_arg == "disabled" || state_arg == "disconnect") {
    // Technology disabled but available, services created but not connected.
    state = kNetworkDisabled;
  } else if (state_arg == "none" || state_arg == "offline") {
    // Technology not available, do not create services.
    state = kTechnologyUnavailable;
  } else if (state_arg == "portal") {
    // Technology is enabled, a service is connected and in Portal state.
    state = shill::kStatePortal;
  } else if (state_arg == "active" || state_arg == "activated") {
    // Technology is enabled, a service is connected and Activated.
    state = kNetworkActivated;
  } else if (type_arg == shill::kTypeCellular &&
             IsCellularTechnology(state_arg)) {
    state = shill::kStateOnline;
    cellular_technology_ = state_arg;
  } else if (type_arg == shill::kTypeCellular && state_arg == "LTEAdvanced") {
    // Special case, Shill name contains a ' '.
    state = shill::kStateOnline;
    cellular_technology_ = shill::kNetworkTechnologyLteAdvanced;
  } else {
    LOG(ERROR) << "Unrecognized initial state: " << type_arg << "="
               << state_arg;
    return false;
  }

  // Special cases
  if (type_arg == "wireless") {
    shill_initial_state_map_[shill::kTypeWifi] = state;
    shill_initial_state_map_[shill::kTypeCellular] = state;
    return true;
  }
  // Convenience synonyms.
  if (type_arg == "eth")
    type_arg = shill::kTypeEthernet;

  if (type_arg != shill::kTypeEthernet &&
      type_arg != shill::kTypeWifi &&
      type_arg != shill::kTypeCellular &&
      type_arg != shill::kTypeWimax &&
      type_arg != shill::kTypeVPN) {
    LOG(WARNING) << "Unrecognized Shill network type: " << type_arg;
    return false;
  }

  // Disabled ethernet is the same as unavailable.
  if (type_arg == shill::kTypeEthernet && state == kNetworkDisabled)
    state = kTechnologyUnavailable;

  shill_initial_state_map_[type_arg] = state;
  return true;
}

std::string FakeShillManagerClient::GetInitialStateForType(
    const std::string& type,
    bool* enabled) {
  std::string result;
  std::map<std::string, std::string>::const_iterator iter =
      shill_initial_state_map_.find(type);
  if (iter == shill_initial_state_map_.end()) {
    *enabled = false;
    result = kTechnologyUnavailable;
  } else {
    std::string state = iter->second;
    if (state == kNetworkDisabled) {
      *enabled = false;
      result = shill::kStateIdle;
    } else {
      *enabled = true;
      result = state;
    }
    if ((state == shill::kStatePortal && type != shill::kTypeWifi) ||
        (state == kNetworkActivated && type != shill::kTypeCellular)) {
      LOG(WARNING) << "Invalid state: " << state << " for " << type;
      result = shill::kStateIdle;
    }
  }
  VLOG(1) << "Initial state for: " << type << " = " << result
          << " Enabled: " << *enabled;
  return result;
}

}  // namespace chromeos
