// 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),
      weak_ptr_factory_(this) {
  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::Bind(&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::Bind(&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;

  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_);

  // |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::Bind(&ObjectManager::InterfacesAddedReceived,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&ObjectManager::InterfacesAddedConnected,
                 weak_ptr_factory_.GetWeakPtr()));

  object_proxy_->ConnectToSignal(
      kObjectManagerInterface,
      kObjectManagerInterfacesRemoved,
      base::Bind(&ObjectManager::InterfacesRemovedReceived,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&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::Bind(&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::Bind(&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::NameOwnerChanged(const std::string& old_owner,
                                     const std::string& new_owner) {
  service_name_owner_ = 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
