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

#include <stddef.h>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/debug/leak_annotations.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "dbus/bus.h"
#include "dbus/dbus_statistics.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/scoped_dbus_error.h"
#include "dbus/util.h"

namespace dbus {

namespace {

constexpr char kErrorServiceUnknown[] =
    "org.freedesktop.DBus.Error.ServiceUnknown";
constexpr char kErrorObjectUnknown[] =
    "org.freedesktop.DBus.Error.UnknownObject";

// Used for success ratio histograms. 1 for success, 0 for failure.
constexpr int kSuccessRatioHistogramMaxValue = 2;

// The path of D-Bus Object sending NameOwnerChanged signal.
constexpr char kDBusSystemObjectPath[] = "/org/freedesktop/DBus";

// The D-Bus Object interface.
constexpr char kDBusSystemObjectInterface[] = "org.freedesktop.DBus";

// The D-Bus Object address.
constexpr char kDBusSystemObjectAddress[] = "org.freedesktop.DBus";

// The NameOwnerChanged member in |kDBusSystemObjectInterface|.
constexpr char kNameOwnerChangedMember[] = "NameOwnerChanged";

}  // namespace

ObjectProxy::ReplyCallbackHolder::ReplyCallbackHolder(
    scoped_refptr<base::TaskRunner> origin_task_runner,
    ResponseOrErrorCallback callback)
    : origin_task_runner_(origin_task_runner), callback_(std::move(callback)) {
  DCHECK(origin_task_runner_.get());
  DCHECK(!callback_.is_null());
}

ObjectProxy::ReplyCallbackHolder::ReplyCallbackHolder(
    ReplyCallbackHolder&& other) = default;

ObjectProxy::ReplyCallbackHolder::~ReplyCallbackHolder() {
  if (callback_.is_null()) {
    // This is the regular case.
    // CallMethod and its family creates this object on the origin thread,
    // PostTask()s to the D-Bus thread for actual D-Bus communication,
    // then PostTask()s back to the origin thread to invoke the |callback_|.
    // At that timing, the ownership of callback should be released via
    // ReleaseCallback().
    // Otherwise, this instance was moved to another one. Do nothing in
    // either case.
    return;
  }

  // The only case where |origin_task_runner_| becomes nullptr is that
  // this is moved. In such a case, |callback_| should be nullptr, too, so it
  // should be handled above. Thus, here |origin_task_runner_| must not be
  // nullptr.
  DCHECK(origin_task_runner_.get());

  if (origin_task_runner_->RunsTasksInCurrentSequence()) {
    // Destroyed on the origin thread. This happens when PostTask()ing to
    // the D-Bus thread fails. The |callback_| can be destroyed on the
    // current thread safely. Do nothing here, and let member destruction
    // destroy the callback.
    return;
  }

  // Here is on D-Bus thread, so try to PostTask() to destroy the callback.
  // to the origin thread.
  // The |origin_task_runner_| may already have stopped. E.g., on Chrome's
  // shutdown the message loop of the UI thread (= the origin thread) stops
  // before D-Bus threaed's. In such a case, PostTask() fails. Because we
  // cannot do much thing here, instead, simply leak the callback rather than
  // destroying it on the D-Bus thread, which could be unexpected from the
  // direct or indirect caller of CallMethod.
  auto* callback_to_be_deleted =
      new ResponseOrErrorCallback(std::move(callback_));
  ANNOTATE_LEAKING_OBJECT_PTR(callback_to_be_deleted);
  origin_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&base::DeletePointer<ResponseOrErrorCallback>,
                                callback_to_be_deleted));
}

ObjectProxy::ResponseOrErrorCallback
ObjectProxy::ReplyCallbackHolder::ReleaseCallback() {
  DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
  return std::move(callback_);
}

ObjectProxy::ObjectProxy(Bus* bus,
                         const std::string& service_name,
                         const ObjectPath& object_path,
                         int options)
    : bus_(bus),
      service_name_(service_name),
      object_path_(object_path),
      ignore_service_unknown_errors_(
          options & IGNORE_SERVICE_UNKNOWN_ERRORS) {
  LOG_IF(FATAL, !object_path_.IsValid()) << object_path_.value();
}

ObjectProxy::~ObjectProxy() {
  DCHECK(pending_calls_.empty());
}

// Originally we tried to make |method_call| a const reference, but we
// gave up as dbus_connection_send_with_reply_and_block() takes a
// non-const pointer of DBusMessage as the second parameter.
std::unique_ptr<Response> ObjectProxy::CallMethodAndBlockWithErrorDetails(
    MethodCall* method_call,
    int timeout_ms,
    ScopedDBusError* error) {
  bus_->AssertOnDBusThread();

  if (!bus_->Connect() ||
      !method_call->SetDestination(service_name_) ||
      !method_call->SetPath(object_path_))
    return std::unique_ptr<Response>();

  DBusMessage* request_message = method_call->raw_message();

  // Send the message synchronously.
  const base::TimeTicks start_time = base::TimeTicks::Now();
  DBusMessage* response_message =
      bus_->SendWithReplyAndBlock(request_message, timeout_ms, error->get());
  // Record if the method call is successful, or not. 1 if successful.
  UMA_HISTOGRAM_ENUMERATION("DBus.SyncMethodCallSuccess",
                            response_message ? 1 : 0,
                            kSuccessRatioHistogramMaxValue);
  statistics::AddBlockingSentMethodCall(service_name_,
                                        method_call->GetInterface(),
                                        method_call->GetMember());

  if (!response_message) {
    LogMethodCallFailure(method_call->GetInterface(),
                         method_call->GetMember(),
                         error->is_set() ? error->name() : "unknown error type",
                         error->is_set() ? error->message() : "");
    return std::unique_ptr<Response>();
  }
  // Record time spent for the method call. Don't include failures.
  UMA_HISTOGRAM_TIMES("DBus.SyncMethodCallTime",
                      base::TimeTicks::Now() - start_time);

  return Response::FromRawMessage(response_message);
}

std::unique_ptr<Response> ObjectProxy::CallMethodAndBlock(
    MethodCall* method_call,
    int timeout_ms) {
  ScopedDBusError error;
  return CallMethodAndBlockWithErrorDetails(method_call, timeout_ms, &error);
}

void ObjectProxy::CallMethod(MethodCall* method_call,
                             int timeout_ms,
                             ResponseCallback callback) {
  auto internal_callback = base::BindOnce(
      &ObjectProxy::OnCallMethod, this, method_call->GetInterface(),
      method_call->GetMember(), std::move(callback));

  CallMethodWithErrorResponse(method_call, timeout_ms,
                              std::move(internal_callback));
}

void ObjectProxy::CallMethodWithErrorResponse(
    MethodCall* method_call,
    int timeout_ms,
    ResponseOrErrorCallback callback) {
  bus_->AssertOnOriginThread();

  const base::TimeTicks start_time = base::TimeTicks::Now();

  ReplyCallbackHolder callback_holder(bus_->GetOriginTaskRunner(),
                                      std::move(callback));

  if (!method_call->SetDestination(service_name_) ||
      !method_call->SetPath(object_path_)) {
    // In case of a failure, run the error callback with nullptr.
    base::OnceClosure task =
        base::BindOnce(&ObjectProxy::RunResponseOrErrorCallback, this,
                       std::move(callback_holder), start_time,
                       nullptr /* response */, nullptr /* error_response */);
    bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, std::move(task));
    return;
  }

  // Increment the reference count so we can safely reference the
  // underlying request message until the method call is complete. This
  // will be unref'ed in StartAsyncMethodCall().
  DBusMessage* request_message = method_call->raw_message();
  dbus_message_ref(request_message);

  statistics::AddSentMethodCall(service_name_,
                                method_call->GetInterface(),
                                method_call->GetMember());

  // Wait for the response in the D-Bus thread.
  base::OnceClosure task =
      base::BindOnce(&ObjectProxy::StartAsyncMethodCall, this, timeout_ms,
                     request_message, std::move(callback_holder), start_time);
  bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, std::move(task));
}

void ObjectProxy::CallMethodWithErrorCallback(MethodCall* method_call,
                                              int timeout_ms,
                                              ResponseCallback callback,
                                              ErrorCallback error_callback) {
  auto internal_callback = base::BindOnce(
      [](ResponseCallback callback, ErrorCallback error_callback,
         Response* response, ErrorResponse* error_response) {
        if (response) {
          std::move(callback).Run(response);
        } else {
          std::move(error_callback).Run(error_response);
        }
      },
      std::move(callback), std::move(error_callback));

  CallMethodWithErrorResponse(method_call, timeout_ms,
                              std::move(internal_callback));
}

void ObjectProxy::ConnectToSignal(const std::string& interface_name,
                                  const std::string& signal_name,
                                  SignalCallback signal_callback,
                                  OnConnectedCallback on_connected_callback) {
  bus_->AssertOnOriginThread();

  if (bus_->HasDBusThread()) {
    base::PostTaskAndReplyWithResult(
        bus_->GetDBusTaskRunner(), FROM_HERE,
        base::BindOnce(&ObjectProxy::ConnectToSignalInternal, this,
                       interface_name, signal_name, signal_callback),
        base::BindOnce(std::move(on_connected_callback), interface_name,
                       signal_name));
  } else {
    // If the bus doesn't have a dedicated dbus thread we need to call
    // ConnectToSignalInternal directly otherwise we might miss a signal
    // that is currently queued if we do a PostTask.
    const bool success =
        ConnectToSignalInternal(interface_name, signal_name, signal_callback);
    std::move(on_connected_callback).Run(interface_name, signal_name, success);
  }
}

void ObjectProxy::SetNameOwnerChangedCallback(
    NameOwnerChangedCallback callback) {
  bus_->AssertOnOriginThread();

  name_owner_changed_callback_ = callback;
}

void ObjectProxy::WaitForServiceToBeAvailable(
    WaitForServiceToBeAvailableCallback callback) {
  bus_->AssertOnOriginThread();

  wait_for_service_to_be_available_callbacks_.push_back(std::move(callback));
  bus_->GetDBusTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(&ObjectProxy::WaitForServiceToBeAvailableInternal, this));
}

void ObjectProxy::Detach() {
  bus_->AssertOnDBusThread();

  if (bus_->is_connected())
    bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this);

  for (const auto& match_rule : match_rules_) {
    ScopedDBusError error;
    bus_->RemoveMatch(match_rule, error.get());
    if (error.is_set()) {
      // There is nothing we can do to recover, so just print the error.
      LOG(ERROR) << "Failed to remove match rule: " << match_rule;
    }
  }
  match_rules_.clear();

  for (auto* pending_call : pending_calls_) {
    dbus_pending_call_cancel(pending_call);
    dbus_pending_call_unref(pending_call);
  }
  pending_calls_.clear();
}

void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
                                       DBusMessage* request_message,
                                       ReplyCallbackHolder callback_holder,
                                       base::TimeTicks start_time) {
  bus_->AssertOnDBusThread();

  if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) {
    // In case of a failure, run the error callback with nullptr.
    base::OnceClosure task =
        base::BindOnce(&ObjectProxy::RunResponseOrErrorCallback, this,
                       std::move(callback_holder), start_time,
                       nullptr /* response */, nullptr /* error_response */);
    bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, std::move(task));

    dbus_message_unref(request_message);
    return;
  }

  DBusPendingCall* dbus_pending_call = nullptr;
  bus_->SendWithReply(request_message, &dbus_pending_call, timeout_ms);

  using PendingCallback =
      base::OnceCallback<void(DBusPendingCall * pending_call)>;
  // This returns false only when unable to allocate memory.
  const bool success = dbus_pending_call_set_notify(
      dbus_pending_call,
      [](DBusPendingCall* pending_call, void* user_data) {
        std::move(*static_cast<PendingCallback*>(user_data)).Run(pending_call);
      },
      // PendingCallback instance is owned by libdbus.
      new PendingCallback(base::BindOnce(&ObjectProxy::OnPendingCallIsComplete,
                                         this, std::move(callback_holder),
                                         start_time)),
      [](void* user_data) { delete static_cast<PendingCallback*>(user_data); });
  CHECK(success) << "Unable to allocate memory";
  pending_calls_.insert(dbus_pending_call);

  // It's now safe to unref the request message.
  dbus_message_unref(request_message);
}

void ObjectProxy::OnPendingCallIsComplete(ReplyCallbackHolder callback_holder,
                                          base::TimeTicks start_time,
                                          DBusPendingCall* pending_call) {
  bus_->AssertOnDBusThread();

  DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);

  // Either |response| or |error_response| takes ownership of the
  // |response_message|.
  std::unique_ptr<Response> response;
  std::unique_ptr<ErrorResponse> error_response;
  if (dbus_message_get_type(response_message) == DBUS_MESSAGE_TYPE_ERROR) {
    error_response = ErrorResponse::FromRawMessage(response_message);
  } else {
    response = Response::FromRawMessage(response_message);
  }

  base::OnceClosure task =
      base::BindOnce(&ObjectProxy::RunResponseOrErrorCallback, this,
                     std::move(callback_holder), start_time, response.get(),
                     error_response.get());

  // The message should be deleted on the D-Bus thread for a complicated
  // reason:
  //
  // libdbus keeps track of the number of bytes in the incoming message
  // queue to ensure that the data size in the queue is manageable. The
  // bookkeeping is partly done via dbus_message_unref(), and immediately
  // asks the client code (Chrome) to stop monitoring the underlying
  // socket, if the number of bytes exceeds a certian number, which is set
  // to 63MB, per dbus-transport.cc:
  //
  //   /* Try to default to something that won't totally hose the system,
  //    * but doesn't impose too much of a limitation.
  //    */
  //   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
  //
  // The monitoring of the socket is done on the D-Bus thread (see Watch
  // class in bus.cc), hence we should stop the monitoring on D-Bus thread.
  bus_->GetOriginTaskRunner()->PostTaskAndReply(
      FROM_HERE, std::move(task),
      base::BindOnce(
          [](Response* response, ErrorResponse* error_response) {
            // Do nothing.
          },
          base::Owned(response.release()),
          base::Owned(error_response.release())));

  // Remove the pending call from the set.
  pending_calls_.erase(pending_call);
  dbus_pending_call_unref(pending_call);
}

void ObjectProxy::RunResponseOrErrorCallback(
    ReplyCallbackHolder callback_holder,
    base::TimeTicks start_time,
    Response* response,
    ErrorResponse* error_response) {
  bus_->AssertOnOriginThread();
  callback_holder.ReleaseCallback().Run(response, error_response);

  if (response) {
    // Record time spent for the method call. Don't include failures.
    UMA_HISTOGRAM_TIMES("DBus.AsyncMethodCallTime",
                        base::TimeTicks::Now() - start_time);
  }
  // Record if the method call is successful, or not. 1 if successful.
  UMA_HISTOGRAM_ENUMERATION("DBus.AsyncMethodCallSuccess", response ? 1 : 0,
                            kSuccessRatioHistogramMaxValue);
}

bool ObjectProxy::ConnectToNameOwnerChangedSignal() {
  bus_->AssertOnDBusThread();

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

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

  // Add a match_rule listening NameOwnerChanged for the well-known name
  // |service_name_|.
  const std::string name_owner_changed_match_rule =
      base::StringPrintf(
          "type='signal',interface='org.freedesktop.DBus',"
          "member='NameOwnerChanged',path='/org/freedesktop/DBus',"
          "sender='org.freedesktop.DBus',arg0='%s'",
          service_name_.c_str());

  const bool success =
      AddMatchRuleWithoutCallback(name_owner_changed_match_rule,
                                  "org.freedesktop.DBus.NameOwnerChanged");

  // Try getting the current name owner. It's not guaranteed that we can get
  // the name owner at this moment, as the service may not yet be started. If
  // that's the case, we'll get the name owner via NameOwnerChanged signal,
  // as soon as the service is started.
  UpdateNameOwnerAndBlock();

  return success;
}

bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name,
                                          const std::string& signal_name,
                                          SignalCallback signal_callback) {
  bus_->AssertOnDBusThread();

  if (!ConnectToNameOwnerChangedSignal())
    return false;

  const std::string absolute_signal_name =
      GetAbsoluteMemberName(interface_name, signal_name);

  // Add a match rule so the signal goes through HandleMessage().
  const std::string match_rule = base::StringPrintf(
      "type='signal', sender='%s', interface='%s', path='%s'",
      service_name_.c_str(), interface_name.c_str(),
      object_path_.value().c_str());
  return AddMatchRuleWithCallback(match_rule,
                                  absolute_signal_name,
                                  signal_callback);
}

void ObjectProxy::WaitForServiceToBeAvailableInternal() {
  bus_->AssertOnDBusThread();

  if (!ConnectToNameOwnerChangedSignal()) {  // Failed to connect to the signal.
    const bool service_is_ready = false;
    bus_->GetOriginTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks,
                       this, service_is_ready));
    return;
  }

  const bool service_is_available = !service_name_owner_.empty();
  if (service_is_available) {  // Service is already available.
    bus_->GetOriginTaskRunner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks,
                       this, service_is_available));
    return;
  }
}

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

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

  // Verify the signal comes from the object we're proxying for, this is
  // our last chance to return DBUS_HANDLER_RESULT_NOT_YET_HANDLED and
  // allow other object proxies to handle instead.
  const ObjectPath path = signal->GetPath();
  if (path != object_path_) {
    if (path.value() == kDBusSystemObjectPath &&
        signal->GetMember() == kNameOwnerChangedMember) {
      // Handle NameOwnerChanged separately
      return HandleNameOwnerChanged(std::move(signal));
    }
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }

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

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

  // Check if we know about the signal.
  const std::string absolute_signal_name = GetAbsoluteMemberName(
      interface, member);
  MethodTable::const_iterator iter = method_table_.find(absolute_signal_name);
  if (iter == method_table_.end()) {
    // Don't know about the signal.
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }
  VLOG(1) << "Signal received: " << signal->ToString();

  std::string sender = signal->GetSender();
  if (service_name_owner_ != sender) {
    LOG(ERROR) << "Rejecting a message from a wrong sender.";
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  }

  const base::TimeTicks start_time = base::TimeTicks::Now();
  if (bus_->HasDBusThread()) {
    // Post a task to run the method in the origin thread.
    // Transfer the ownership of |signal| to RunMethod().
    // |released_signal| will be deleted in RunMethod().
    Signal* released_signal = signal.release();
    bus_->GetOriginTaskRunner()->PostTask(FROM_HERE,
                                          base::Bind(&ObjectProxy::RunMethod,
                                                     this,
                                                     start_time,
                                                     iter->second,
                                                     released_signal));
  } else {
    const base::TimeTicks start_time = base::TimeTicks::Now();
    // If the D-Bus thread is not used, just call the callback on the
    // current thread. Transfer the ownership of |signal| to RunMethod().
    Signal* released_signal = signal.release();
    RunMethod(start_time, iter->second, released_signal);
  }

  // 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 ObjectProxy::RunMethod(base::TimeTicks start_time,
                            std::vector<SignalCallback> signal_callbacks,
                            Signal* signal) {
  bus_->AssertOnOriginThread();

  for (std::vector<SignalCallback>::iterator iter = signal_callbacks.begin();
       iter != signal_callbacks.end(); ++iter)
    iter->Run(signal);

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

  // Record time spent for handling the signal.
  UMA_HISTOGRAM_TIMES("DBus.SignalHandleTime",
                      base::TimeTicks::Now() - start_time);
}

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

void ObjectProxy::LogMethodCallFailure(
    const base::StringPiece& interface_name,
    const base::StringPiece& method_name,
    const base::StringPiece& error_name,
    const base::StringPiece& error_message) const {
  if (ignore_service_unknown_errors_ &&
      (error_name == kErrorServiceUnknown || error_name == kErrorObjectUnknown))
    return;

  std::ostringstream msg;
  msg << "Failed to call method: " << interface_name << "." << method_name
      << ": object_path= " << object_path_.value()
      << ": " << error_name << ": " << error_message;

  // "UnknownObject" indicates that an object or service is no longer available,
  // e.g. a Shill network service has gone out of range. Treat these as warnings
  // not errors.
  if (error_name == kErrorObjectUnknown)
    LOG(WARNING) << msg.str();
  else
    LOG(ERROR) << msg.str();
}

void ObjectProxy::OnCallMethod(const std::string& interface_name,
                               const std::string& method_name,
                               ResponseCallback response_callback,
                               Response* response,
                               ErrorResponse* error_response) {
  if (response) {
    // Method call was successful.
    std::move(response_callback).Run(response);
    return;
  }
  // Method call failed.
  std::string error_name;
  std::string error_message;
  if (error_response) {
    // Error message may contain the error message as string.
    error_name = error_response->GetErrorName();
    MessageReader reader(error_response);
    reader.PopString(&error_message);
  } else {
    error_name = "unknown error type";
  }
  LogMethodCallFailure(interface_name, method_name, error_name, error_message);

  std::move(response_callback).Run(nullptr);
}

bool ObjectProxy::AddMatchRuleWithCallback(
    const std::string& match_rule,
    const std::string& absolute_signal_name,
    SignalCallback signal_callback) {
  DCHECK(!match_rule.empty());
  DCHECK(!absolute_signal_name.empty());
  bus_->AssertOnDBusThread();

  if (match_rules_.find(match_rule) == match_rules_.end()) {
    ScopedDBusError error;
    bus_->AddMatch(match_rule, error.get());
    if (error.is_set()) {
      LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
                 << error.name() << ": " << error.message();
      return false;
    } else {
      // Store the match rule, so that we can remove this in Detach().
      match_rules_.insert(match_rule);
      // Add the signal callback to the method table.
      method_table_[absolute_signal_name].push_back(signal_callback);
      return true;
    }
  } else {
    // We already have the match rule.
    method_table_[absolute_signal_name].push_back(signal_callback);
    return true;
  }
}

bool ObjectProxy::AddMatchRuleWithoutCallback(
    const std::string& match_rule,
    const std::string& absolute_signal_name) {
  DCHECK(!match_rule.empty());
  DCHECK(!absolute_signal_name.empty());
  bus_->AssertOnDBusThread();

  if (match_rules_.find(match_rule) != match_rules_.end())
    return true;

  ScopedDBusError error;
  bus_->AddMatch(match_rule, error.get());
  if (error.is_set()) {
    LOG(ERROR) << "Failed to add match rule \"" << match_rule << "\". Got "
               << error.name() << ": " << error.message();
    return false;
  }
  // Store the match rule, so that we can remove this in Detach().
  match_rules_.insert(match_rule);
  return true;
}

void ObjectProxy::UpdateNameOwnerAndBlock() {
  bus_->AssertOnDBusThread();
  // Errors should be suppressed here, as the service may not be yet running
  // when connecting to signals of the service, which is just fine.
  // The ObjectProxy will be notified when the service is launched via
  // NameOwnerChanged signal. See also comments in ConnectToSignalInternal().
  service_name_owner_ =
      bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
}

DBusHandlerResult ObjectProxy::HandleNameOwnerChanged(
    std::unique_ptr<Signal> signal) {
  DCHECK(signal);
  bus_->AssertOnDBusThread();

  // Confirm the validity of the NameOwnerChanged signal.
  if (signal->GetMember() == kNameOwnerChangedMember &&
      signal->GetInterface() == kDBusSystemObjectInterface &&
      signal->GetSender() == kDBusSystemObjectAddress) {
    MessageReader reader(signal.get());
    std::string name, old_owner, new_owner;
    if (reader.PopString(&name) &&
        reader.PopString(&old_owner) &&
        reader.PopString(&new_owner) &&
        name == service_name_) {
      service_name_owner_ = new_owner;
      bus_->GetOriginTaskRunner()->PostTask(
          FROM_HERE,
          base::Bind(&ObjectProxy::RunNameOwnerChangedCallback,
                     this, old_owner, new_owner));

      const bool service_is_available = !service_name_owner_.empty();
      if (service_is_available) {
        bus_->GetOriginTaskRunner()->PostTask(
            FROM_HERE,
            base::Bind(&ObjectProxy::RunWaitForServiceToBeAvailableCallbacks,
                       this, service_is_available));
      }
    }
  }

  // Always return unhandled to let other object proxies handle the same
  // signal.
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

void ObjectProxy::RunNameOwnerChangedCallback(const std::string& old_owner,
                                              const std::string& new_owner) {
  bus_->AssertOnOriginThread();
  if (!name_owner_changed_callback_.is_null())
    name_owner_changed_callback_.Run(old_owner, new_owner);
}

void ObjectProxy::RunWaitForServiceToBeAvailableCallbacks(
    bool service_is_available) {
  bus_->AssertOnOriginThread();

  std::vector<WaitForServiceToBeAvailableCallback> callbacks;
  callbacks.swap(wait_for_service_to_be_available_callbacks_);
  for (size_t i = 0; i < callbacks.size(); ++i)
    std::move(callbacks[i]).Run(service_is_available);
}

}  // namespace dbus
