//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/cros/connection_manager.h"

#include <memory>
#include <set>
#include <string>

#include <base/stl_util.h>
#include <base/strings/string_util.h>
#include <policy/device_policy.h>
#include <shill/dbus-constants.h>
#include <shill/dbus-proxies.h>

#include "update_engine/common/connection_utils.h"
#include "update_engine/common/prefs.h"
#include "update_engine/common/system_state.h"
#include "update_engine/common/utils.h"
#include "update_engine/cros/shill_proxy.h"
#include "update_engine/cros/update_attempter.h"

using org::chromium::flimflam::ManagerProxyInterface;
using org::chromium::flimflam::ServiceProxyInterface;
using std::set;
using std::string;

namespace chromeos_update_engine {

namespace connection_manager {
std::unique_ptr<ConnectionManagerInterface> CreateConnectionManager() {
  return std::unique_ptr<ConnectionManagerInterface>(
      new ConnectionManager(new ShillProxy()));
}
}  // namespace connection_manager

ConnectionManager::ConnectionManager(ShillProxyInterface* shill_proxy)
    : shill_proxy_(shill_proxy) {}

bool ConnectionManager::IsUpdateAllowedOver(
    ConnectionType type, ConnectionTethering tethering) const {
  if (type != ConnectionType::kCellular) {
    if (tethering != ConnectionTethering::kConfirmed) {
      return true;
    }

    // Treat this connection as if it is a cellular connection.
    LOG(INFO)
        << "Current connection is confirmed tethered, using Cellular setting.";
  }

  const policy::DevicePolicy* device_policy =
      SystemState::Get()->device_policy();

  // The device_policy is loaded in a lazy way before an update check. Load
  // it now from the libbrillo cache if it wasn't already loaded.
  if (!device_policy) {
    UpdateAttempter* update_attempter = SystemState::Get()->update_attempter();
    if (update_attempter) {
      update_attempter->RefreshDevicePolicy();
      device_policy = SystemState::Get()->device_policy();
    }
  }

  if (!device_policy) {
    // Device policy fails to be loaded (possibly due to guest account). We
    // do not check the local user setting here, which should be checked by
    // |OmahaRequestAction| during checking for update.
    LOG(INFO) << "Allowing updates over cellular as device policy fails to be "
                 "loaded.";
    return true;
  }

  set<string> allowed_types;
  if (device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
    // The update setting is enforced by the device policy.

    // TODO(crbug.com/1054279): Use base::Contains after uprev to r680000.
    if (allowed_types.find(shill::kTypeCellular) == allowed_types.end()) {
      LOG(INFO) << "Disabling updates over cellular connection as it's not "
                   "allowed in the device policy.";
      return false;
    }

    LOG(INFO) << "Allowing updates over cellular per device policy.";
    return true;
  }

  // If there's no update setting in the device policy, we do not check
  // the local user setting here, which should be checked by
  // |OmahaRequestAction| during checking for update.
  LOG(INFO) << "Allowing updates over cellular as device policy does "
               "not include update setting.";
  return true;
}

bool ConnectionManager::IsAllowedConnectionTypesForUpdateSet() const {
  const policy::DevicePolicy* device_policy =
      SystemState::Get()->device_policy();
  if (!device_policy) {
    LOG(INFO) << "There's no device policy loaded yet.";
    return false;
  }

  set<string> allowed_types;
  if (!device_policy->GetAllowedConnectionTypesForUpdate(&allowed_types)) {
    return false;
  }

  return true;
}

bool ConnectionManager::GetConnectionProperties(
    ConnectionType* out_type, ConnectionTethering* out_tethering) {
  dbus::ObjectPath default_service_path;
  TEST_AND_RETURN_FALSE(GetDefaultServicePath(&default_service_path));
  if (!default_service_path.IsValid())
    return false;
  // Shill uses the "/" service path to indicate that it is not connected.
  if (default_service_path.value() == "/") {
    *out_type = ConnectionType::kDisconnected;
    *out_tethering = ConnectionTethering::kUnknown;
    return true;
  }
  TEST_AND_RETURN_FALSE(
      GetServicePathProperties(default_service_path, out_type, out_tethering));
  return true;
}

bool ConnectionManager::GetDefaultServicePath(dbus::ObjectPath* out_path) {
  brillo::VariantDictionary properties;
  brillo::ErrorPtr error;
  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
  if (!manager_proxy)
    return false;
  TEST_AND_RETURN_FALSE(manager_proxy->GetProperties(&properties, &error));

  const auto& prop_default_service =
      properties.find(shill::kDefaultServiceProperty);
  if (prop_default_service == properties.end())
    return false;

  *out_path = prop_default_service->second.TryGet<dbus::ObjectPath>();
  return out_path->IsValid();
}

bool ConnectionManager::GetServicePathProperties(
    const dbus::ObjectPath& path,
    ConnectionType* out_type,
    ConnectionTethering* out_tethering) {
  // We create and dispose the ServiceProxyInterface on every request.
  std::unique_ptr<ServiceProxyInterface> service =
      shill_proxy_->GetServiceForPath(path);

  brillo::VariantDictionary properties;
  brillo::ErrorPtr error;
  TEST_AND_RETURN_FALSE(service->GetProperties(&properties, &error));

  // Populate the out_tethering.
  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
  if (prop_tethering == properties.end()) {
    // Set to Unknown if not present.
    *out_tethering = ConnectionTethering::kUnknown;
  } else {
    // If the property doesn't contain a string value, the empty string will
    // become kUnknown.
    *out_tethering = connection_utils::ParseConnectionTethering(
        prop_tethering->second.TryGet<string>());
  }

  // Populate the out_type property.
  const auto& prop_type = properties.find(shill::kTypeProperty);
  if (prop_type == properties.end()) {
    // Set to Unknown if not present.
    *out_type = ConnectionType::kUnknown;
    return false;
  }

  string type_str = prop_type->second.TryGet<string>();
  if (type_str == shill::kTypeVPN) {
    const auto& prop_physical =
        properties.find(shill::kPhysicalTechnologyProperty);
    if (prop_physical == properties.end()) {
      LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
                    " connection (service: "
                 << path.value() << "). Returning default kUnknown value.";
      *out_type = ConnectionType::kUnknown;
    } else {
      *out_type = connection_utils::ParseConnectionType(
          prop_physical->second.TryGet<string>());
    }
  } else {
    *out_type = connection_utils::ParseConnectionType(type_str);
  }
  return true;
}

}  // namespace chromeos_update_engine
