// 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 "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(NULL) {
}

ObjectManager::Object::~Object() {
}

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) {
  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()));

  // 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::Bind(&ObjectManager::SetupMatchRuleAndFilter, this),
      base::Bind(&ObjectManager::OnSetupMatchRuleAndFilterComplete, this));
}

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 NULL;

  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 NULL;

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

  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();
}

void ObjectManager::InitializeObjects() {
  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()));

  GetManagedObjects();
}

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) {
  LOG_IF(WARNING, !success) << service_name_ << " " << object_path_.value()
                            << ": Failed to set up match rule.";
  if (success)
    InitializeObjects();
}

// 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);
  scoped_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 != NULL) {
    MessageReader reader(response);
    MessageReader array_reader(NULL);
    if (!reader.PopArray(&array_reader))
      return;

    while (array_reader.HasMoreData()) {
      MessageReader dict_entry_reader(NULL);
      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(NULL);
  if (!reader->PopArray(&array_reader))
    return;

  while (array_reader.HasMoreData()) {
    MessageReader dict_entry_reader(NULL);
    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
