// Copyright (c) 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 "dbus/object_manager.h"

#include <stddef.h>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner_util.h"
#include "dbus/bus.h"
#include "dbus/dbus_statistics.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "dbus/property.h"
#include "dbus/scoped_dbus_error.h"
#include "dbus/util.h"

namespace dbus {

ObjectManager::Object::Object()
  : object_proxy(nullptr) {
}

ObjectManager::Object::~Object() = default;

scoped_refptr<ObjectManager> ObjectManager::Create(
    Bus* bus,
    const std::string& service_name,
    const ObjectPath& object_path) {
  auto object_manager =
      base::WrapRefCounted(new ObjectManager(bus, service_name, object_path));

  // Set up a match rule and a filter function to handle PropertiesChanged
  // signals from the service. This is important to avoid any race conditions
  // that might cause us to miss PropertiesChanged signals once all objects are
  // initialized via GetManagedObjects.
  base::PostTaskAndReplyWithResult(
      bus->GetDBusTaskRunner(), FROM_HERE,
      base::BindOnce(&ObjectManager::SetupMatchRuleAndFilter, object_manager),
      base::BindOnce(&ObjectManager::OnSetupMatchRuleAndFilterComplete,
                     object_manager));
  return object_manager;
}

ObjectManager::ObjectManager(Bus* bus,
                             const std::string& service_name,
                             const ObjectPath& object_path)
    : bus_(bus),
      service_name_(service_name),
      object_path_(object_path),
      setup_success_(false),
      cleanup_called_(false) {
  LOG_IF(FATAL, !object_path_.IsValid()) << object_path_.value();
  DVLOG(1) << "Creating ObjectManager for " << service_name_
           << " " << object_path_.value();
  DCHECK(bus_);
  bus_->AssertOnOriginThread();
  object_proxy_ = bus_->GetObjectProxy(service_name_, object_path_);
  object_proxy_->SetNameOwnerChangedCallback(base::BindRepeating(
      &ObjectManager::NameOwnerChanged, weak_ptr_factory_.GetWeakPtr()));
}

ObjectManager::~ObjectManager() {
  // Clean up Object structures
  for (ObjectMap::iterator iter = object_map_.begin();
       iter != object_map_.end(); ++iter) {
    Object* object = iter->second;

    for (Object::PropertiesMap::iterator piter = object->properties_map.begin();
         piter != object->properties_map.end(); ++piter) {
      PropertySet* properties = piter->second;
      delete properties;
    }

    delete object;
  }
}

void ObjectManager::RegisterInterface(const std::string& interface_name,
                                      Interface* interface) {
  interface_map_[interface_name] = interface;
}

void ObjectManager::UnregisterInterface(const std::string& interface_name) {
  InterfaceMap::iterator iter = interface_map_.find(interface_name);
  if (iter != interface_map_.end())
    interface_map_.erase(iter);
}

std::vector<ObjectPath> ObjectManager::GetObjects() {
  std::vector<ObjectPath> object_paths;

  for (ObjectMap::iterator iter = object_map_.begin();
       iter != object_map_.end(); ++iter)
    object_paths.push_back(iter->first);

  return object_paths;
}

std::vector<ObjectPath> ObjectManager::GetObjectsWithInterface(
      const std::string& interface_name) {
  std::vector<ObjectPath> object_paths;

  for (ObjectMap::iterator oiter = object_map_.begin();
       oiter != object_map_.end(); ++oiter) {
    Object* object = oiter->second;

    Object::PropertiesMap::iterator piter =
        object->properties_map.find(interface_name);
    if (piter != object->properties_map.end())
      object_paths.push_back(oiter->first);
  }

  return object_paths;
}

ObjectProxy* ObjectManager::GetObjectProxy(const ObjectPath& object_path) {
  ObjectMap::iterator iter = object_map_.find(object_path);
  if (iter == object_map_.end())
    return nullptr;

  Object* object = iter->second;
  return object->object_proxy;
}

PropertySet* ObjectManager::GetProperties(const ObjectPath& object_path,
                                          const std::string& interface_name) {
  ObjectMap::iterator iter = object_map_.find(object_path);
  if (iter == object_map_.end())
    return nullptr;

  Object* object = iter->second;
  Object::PropertiesMap::iterator piter =
      object->properties_map.find(interface_name);
  if (piter == object->properties_map.end())
    return nullptr;

  return piter->second;
}

void ObjectManager::GetManagedObjects() {
  MethodCall method_call(kObjectManagerInterface,
                         kObjectManagerGetManagedObjects);

  object_proxy_->CallMethod(&method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
                            base::BindOnce(&ObjectManager::OnGetManagedObjects,
                                           weak_ptr_factory_.GetWeakPtr()));
}

void ObjectManager::CleanUp() {
  DCHECK(bus_);
  bus_->AssertOnDBusThread();
  DCHECK(!cleanup_called_);

  cleanup_called_ = true;

  if (!setup_success_)
    return;

  bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this);

  ScopedDBusError error;
  bus_->RemoveMatch(match_rule_, error.get());
  if (error.is_set())
    LOG(ERROR) << "Failed to remove match rule: " << match_rule_;

  match_rule_.clear();
}

bool ObjectManager::SetupMatchRuleAndFilter() {
  DCHECK(bus_);
  DCHECK(!setup_success_);
  bus_->AssertOnDBusThread();

  if (cleanup_called_)
    return false;

  if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
    return false;

  // Try to get |service_name_owner_| from dbus if we haven't received any
  // NameOwnerChanged signals.
  if (service_name_owner_.empty()) {
    service_name_owner_ =
        bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
  }

  const std::string match_rule =
      base::StringPrintf(
          "type='signal', sender='%s', interface='%s', member='%s'",
          service_name_.c_str(),
          kPropertiesInterface,
          kPropertiesChanged);

  bus_->AddFilterFunction(&ObjectManager::HandleMessageThunk, this);

  ScopedDBusError error;
  bus_->AddMatch(match_rule, error.get());
  if (error.is_set()) {
    LOG(ERROR) << "ObjectManager failed to add match rule \"" << match_rule
               << "\". Got " << error.name() << ": " << error.message();
    bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this);
    return false;
  }

  match_rule_ = match_rule;
  setup_success_ = true;

  return true;
}

void ObjectManager::OnSetupMatchRuleAndFilterComplete(bool success) {
  if (!success) {
    LOG(WARNING) << service_name_ << " " << object_path_.value()
                 << ": Failed to set up match rule.";
    return;
  }

  DCHECK(bus_);
  DCHECK(object_proxy_);
  DCHECK(setup_success_);
  bus_->AssertOnOriginThread();

  // |object_proxy_| is no longer valid if the Bus was shut down before this
  // call. Don't initiate any other action from the origin thread.
  if (cleanup_called_)
    return;

  object_proxy_->ConnectToSignal(
      kObjectManagerInterface, kObjectManagerInterfacesAdded,
      base::BindRepeating(&ObjectManager::InterfacesAddedReceived,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindOnce(&ObjectManager::InterfacesAddedConnected,
                     weak_ptr_factory_.GetWeakPtr()));

  object_proxy_->ConnectToSignal(
      kObjectManagerInterface, kObjectManagerInterfacesRemoved,
      base::BindRepeating(&ObjectManager::InterfacesRemovedReceived,
                          weak_ptr_factory_.GetWeakPtr()),
      base::BindOnce(&ObjectManager::InterfacesRemovedConnected,
                     weak_ptr_factory_.GetWeakPtr()));

  if (!service_name_owner_.empty())
    GetManagedObjects();
}

// static
DBusHandlerResult ObjectManager::HandleMessageThunk(DBusConnection* connection,
                                                    DBusMessage* raw_message,
                                                    void* user_data) {
  ObjectManager* self = reinterpret_cast<ObjectManager*>(user_data);
  return self->HandleMessage(connection, raw_message);
}

DBusHandlerResult ObjectManager::HandleMessage(DBusConnection* connection,
                                               DBusMessage* raw_message) {
  DCHECK(bus_);
  bus_->AssertOnDBusThread();

  // Handle the message only if it is a signal.
  // Note that the match rule in SetupMatchRuleAndFilter() is configured to
  // only accept signals, but we check here just in case.
  if (dbus_message_get_type(raw_message) != DBUS_MESSAGE_TYPE_SIGNAL)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  // raw_message will be unrefed on exit of the function. Increment the
  // reference so we can use it in Signal.
  dbus_message_ref(raw_message);
  std::unique_ptr<Signal> signal(Signal::FromRawMessage(raw_message));

  const std::string interface = signal->GetInterface();
  const std::string member = signal->GetMember();

  statistics::AddReceivedSignal(service_name_, interface, member);

  // Handle the signal only if it is PropertiesChanged.
  // Note that the match rule in SetupMatchRuleAndFilter() is configured to
  // only accept PropertiesChanged signals, but we check here just in case.
  const std::string absolute_signal_name =
      GetAbsoluteMemberName(interface, member);
  const std::string properties_changed_signal_name =
      GetAbsoluteMemberName(kPropertiesInterface, kPropertiesChanged);
  if (absolute_signal_name != properties_changed_signal_name)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  VLOG(1) << "Signal received: " << signal->ToString();

  // Handle the signal only if it is from the service that the ObjectManager
  // instance is interested in.
  // Note that the match rule in SetupMatchRuleAndFilter() is configured to
  // only accept messages from the service name of our interest. However, the
  // service='...' filter does not work as intended. See crbug.com/507206#14
  // and #15 for details, hence it's necessary to check the sender here.
  std::string sender = signal->GetSender();
  if (service_name_owner_ != sender)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  const ObjectPath path = signal->GetPath();

  if (bus_->HasDBusThread()) {
    // Post a task to run the method in the origin thread. Transfer ownership of
    // |signal| to NotifyPropertiesChanged, which will handle the clean up.
    Signal* released_signal = signal.release();
    bus_->GetOriginTaskRunner()->PostTask(
        FROM_HERE, base::BindOnce(&ObjectManager::NotifyPropertiesChanged, this,
                                  path, released_signal));
  } else {
    // If the D-Bus thread is not used, just call the callback on the
    // current thread. Transfer the ownership of |signal| to
    // NotifyPropertiesChanged.
    NotifyPropertiesChanged(path, signal.release());
  }

  // We don't return DBUS_HANDLER_RESULT_HANDLED for signals because other
  // objects may be interested in them. (e.g. Signals from org.freedesktop.DBus)
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

void ObjectManager::NotifyPropertiesChanged(
    const dbus::ObjectPath object_path,
    Signal* signal) {
  DCHECK(bus_);
  bus_->AssertOnOriginThread();

  NotifyPropertiesChangedHelper(object_path, signal);

  // Delete the message on the D-Bus thread. See comments in HandleMessage.
  bus_->GetDBusTaskRunner()->PostTask(
      FROM_HERE, base::BindOnce(&base::DeletePointer<Signal>, signal));
}

void ObjectManager::NotifyPropertiesChangedHelper(
    const dbus::ObjectPath object_path,
    Signal* signal) {
  DCHECK(bus_);
  bus_->AssertOnOriginThread();

  MessageReader reader(signal);
  std::string interface;
  if (!reader.PopString(&interface)) {
    LOG(WARNING) << "Property changed signal has wrong parameters: "
                 << "expected interface name: " << signal->ToString();
    return;
  }

  PropertySet* properties = GetProperties(object_path, interface);
  if (properties)
    properties->ChangedReceived(signal);
}

void ObjectManager::OnGetManagedObjects(Response* response) {
  if (response != nullptr) {
    MessageReader reader(response);
    MessageReader array_reader(nullptr);
    if (!reader.PopArray(&array_reader))
      return;

    while (array_reader.HasMoreData()) {
      MessageReader dict_entry_reader(nullptr);
      ObjectPath object_path;
      if (!array_reader.PopDictEntry(&dict_entry_reader) ||
          !dict_entry_reader.PopObjectPath(&object_path))
        continue;

      UpdateObject(object_path, &dict_entry_reader);
    }

  } else {
    LOG(WARNING) << service_name_ << " " << object_path_.value()
                 << ": Failed to get managed objects";
  }
}

void ObjectManager::InterfacesAddedReceived(Signal* signal) {
  DCHECK(signal);
  MessageReader reader(signal);
  ObjectPath object_path;
  if (!reader.PopObjectPath(&object_path)) {
    LOG(WARNING) << service_name_ << " " << object_path_.value()
                 << ": InterfacesAdded signal has incorrect parameters: "
                 << signal->ToString();
    return;
  }

  UpdateObject(object_path, &reader);
}

void ObjectManager::InterfacesAddedConnected(const std::string& interface_name,
                                             const std::string& signal_name,
                                             bool success) {
  LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
                            << ": Failed to connect to InterfacesAdded signal.";
}

void ObjectManager::InterfacesRemovedReceived(Signal* signal) {
  DCHECK(signal);
  MessageReader reader(signal);
  ObjectPath object_path;
  std::vector<std::string> interface_names;
  if (!reader.PopObjectPath(&object_path) ||
      !reader.PopArrayOfStrings(&interface_names)) {
    LOG(WARNING) << service_name_ << " " << object_path_.value()
                 << ": InterfacesRemoved signal has incorrect parameters: "
                 << signal->ToString();
    return;
  }

  for (size_t i = 0; i < interface_names.size(); ++i)
    RemoveInterface(object_path, interface_names[i]);
}

void ObjectManager::InterfacesRemovedConnected(
    const std::string& interface_name,
    const std::string& signal_name,
    bool success) {
  LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
                            << ": Failed to connect to "
                            << "InterfacesRemoved signal.";
}

void ObjectManager::UpdateObject(const ObjectPath& object_path,
                                 MessageReader* reader) {
  DCHECK(reader);
  MessageReader array_reader(nullptr);
  if (!reader->PopArray(&array_reader))
    return;

  while (array_reader.HasMoreData()) {
    MessageReader dict_entry_reader(nullptr);
    std::string interface_name;
    if (!array_reader.PopDictEntry(&dict_entry_reader) ||
        !dict_entry_reader.PopString(&interface_name))
      continue;

    AddInterface(object_path, interface_name, &dict_entry_reader);
  }
}


void ObjectManager::AddInterface(const ObjectPath& object_path,
                                 const std::string& interface_name,
                                 MessageReader* reader) {
  InterfaceMap::iterator iiter = interface_map_.find(interface_name);
  if (iiter == interface_map_.end())
    return;
  Interface* interface = iiter->second;

  ObjectMap::iterator oiter = object_map_.find(object_path);
  Object* object;
  if (oiter == object_map_.end()) {
    object = object_map_[object_path] = new Object;
    object->object_proxy = bus_->GetObjectProxy(service_name_, object_path);
  } else
    object = oiter->second;

  Object::PropertiesMap::iterator piter =
      object->properties_map.find(interface_name);
  PropertySet* property_set;
  const bool interface_added = (piter == object->properties_map.end());
  if (interface_added) {
    property_set = object->properties_map[interface_name] =
        interface->CreateProperties(object->object_proxy,
                                    object_path, interface_name);
  } else
    property_set = piter->second;

  property_set->UpdatePropertiesFromReader(reader);

  if (interface_added)
    interface->ObjectAdded(object_path, interface_name);
}

void ObjectManager::RemoveInterface(const ObjectPath& object_path,
                                    const std::string& interface_name) {
  ObjectMap::iterator oiter = object_map_.find(object_path);
  if (oiter == object_map_.end())
    return;
  Object* object = oiter->second;

  Object::PropertiesMap::iterator piter =
      object->properties_map.find(interface_name);
  if (piter == object->properties_map.end())
    return;

  // Inform the interface before removing the properties structure or object
  // in case it needs details from them to make its own decisions.
  InterfaceMap::iterator iiter = interface_map_.find(interface_name);
  if (iiter != interface_map_.end()) {
    Interface* interface = iiter->second;
    interface->ObjectRemoved(object_path, interface_name);
  }

  delete piter->second;
  object->properties_map.erase(piter);

  if (object->properties_map.empty()) {
    object_map_.erase(oiter);
    delete object;
  }
}

void ObjectManager::UpdateServiceNameOwner(const std::string& new_owner) {
  bus_->AssertOnDBusThread();
  service_name_owner_ = new_owner;
}

void ObjectManager::NameOwnerChanged(const std::string& old_owner,
                                     const std::string& new_owner) {
  bus_->AssertOnOriginThread();

  bus_->GetDBusTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ObjectManager::UpdateServiceNameOwner, this, new_owner));

  if (!old_owner.empty()) {
    ObjectMap::iterator iter = object_map_.begin();
    while (iter != object_map_.end()) {
      ObjectMap::iterator tmp = iter;
      ++iter;

      // PropertiesMap is mutated by RemoveInterface, and also Object is
      // destroyed; easier to collect the object path and interface names
      // and remove them safely.
      const dbus::ObjectPath object_path = tmp->first;
      Object* object = tmp->second;
      std::vector<std::string> interfaces;

      for (Object::PropertiesMap::iterator piter =
              object->properties_map.begin();
           piter != object->properties_map.end(); ++piter)
        interfaces.push_back(piter->first);

      for (std::vector<std::string>::iterator iiter = interfaces.begin();
           iiter != interfaces.end(); ++iiter)
        RemoveInterface(object_path, *iiter);
    }

  }

  if (!new_owner.empty())
    GetManagedObjects();
}

}  // namespace dbus
