Home | History | Annotate | Download | only in dbus
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chromeos/dbus/system_clock_client.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback.h"
      9 #include "base/observer_list.h"
     10 #include "dbus/bus.h"
     11 #include "dbus/message.h"
     12 #include "dbus/object_path.h"
     13 #include "dbus/object_proxy.h"
     14 #include "third_party/cros_system_api/dbus/service_constants.h"
     15 
     16 namespace chromeos {
     17 
     18 // The SystemClockClient implementation used in production.
     19 class SystemClockClientImpl : public SystemClockClient {
     20  public:
     21   SystemClockClientImpl()
     22       : can_set_time_(false),
     23         can_set_time_initialized_(false),
     24         system_clock_proxy_(NULL),
     25         weak_ptr_factory_(this) {}
     26 
     27   virtual ~SystemClockClientImpl() {
     28   }
     29 
     30   virtual void AddObserver(Observer* observer) OVERRIDE {
     31     observers_.AddObserver(observer);
     32   }
     33 
     34   virtual void RemoveObserver(Observer* observer) OVERRIDE {
     35     observers_.RemoveObserver(observer);
     36   }
     37 
     38   virtual bool HasObserver(Observer* observer) OVERRIDE {
     39     return observers_.HasObserver(observer);
     40   }
     41 
     42   virtual void SetTime(int64 time_in_seconds) OVERRIDE {
     43     // Always try to set the time, because |can_set_time_| may be stale.
     44     dbus::MethodCall method_call(system_clock::kSystemClockInterface,
     45                                  system_clock::kSystemClockSet);
     46     dbus::MessageWriter writer(&method_call);
     47     writer.AppendInt64(time_in_seconds);
     48     system_clock_proxy_->CallMethod(&method_call,
     49                                     dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
     50                                     dbus::ObjectProxy::EmptyResponseCallback());
     51   }
     52 
     53   virtual bool CanSetTime() OVERRIDE { return can_set_time_; }
     54 
     55  protected:
     56   virtual void Init(dbus::Bus* bus) OVERRIDE {
     57     system_clock_proxy_ = bus->GetObjectProxy(
     58         system_clock::kSystemClockServiceName,
     59         dbus::ObjectPath(system_clock::kSystemClockServicePath));
     60 
     61     // Check whether the system clock can be set.
     62     GetCanSet();
     63 
     64     // Monitor the D-Bus signal for TimeUpdated changes.
     65     system_clock_proxy_->ConnectToSignal(
     66         system_clock::kSystemClockInterface,
     67         system_clock::kSystemClockUpdated,
     68         base::Bind(&SystemClockClientImpl::TimeUpdatedReceived,
     69                    weak_ptr_factory_.GetWeakPtr()),
     70         base::Bind(&SystemClockClientImpl::TimeUpdatedConnected,
     71                    weak_ptr_factory_.GetWeakPtr()));
     72   }
     73 
     74  private:
     75   // Called when a TimeUpdated signal is received.
     76   void TimeUpdatedReceived(dbus::Signal* signal) {
     77     VLOG(1) << "TimeUpdated signal received: " << signal->ToString();
     78     dbus::MessageReader reader(signal);
     79     FOR_EACH_OBSERVER(Observer, observers_, SystemClockUpdated());
     80 
     81     // Check if the system clock can be changed now.
     82     GetCanSet();
     83   }
     84 
     85   // Called when the TimeUpdated signal is initially connected.
     86   void TimeUpdatedConnected(const std::string& interface_name,
     87                             const std::string& signal_name,
     88                             bool success) {
     89     LOG_IF(ERROR, !success)
     90         << "Failed to connect to TimeUpdated signal.";
     91   }
     92 
     93   // Callback for CanSetTime method.
     94   void OnGetCanSet(dbus::Response* response) {
     95     if (!response) {
     96       VLOG(1) << "CanSetTime request failed.";
     97       return;
     98     }
     99 
    100     dbus::MessageReader reader(response);
    101     bool can_set_time;
    102     if (!reader.PopBool(&can_set_time)) {
    103       LOG(ERROR) << "CanSetTime response invalid: " << response->ToString();
    104       return;
    105     }
    106 
    107     // Nothing to do if the CanSetTime response hasn't changed.
    108     if (can_set_time_initialized_ && can_set_time_ == can_set_time)
    109       return;
    110 
    111     can_set_time_initialized_ = true;
    112     can_set_time_ = can_set_time;
    113 
    114     FOR_EACH_OBSERVER(
    115         Observer, observers_, SystemClockCanSetTimeChanged(can_set_time));
    116   }
    117 
    118   // Check whether the time can be set.
    119   void GetCanSet() {
    120     dbus::MethodCall method_call(system_clock::kSystemClockInterface,
    121                                  system_clock::kSystemClockCanSet);
    122     dbus::MessageWriter writer(&method_call);
    123     system_clock_proxy_->CallMethod(
    124         &method_call,
    125         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
    126         base::Bind(&SystemClockClientImpl::OnGetCanSet,
    127                    weak_ptr_factory_.GetWeakPtr()));
    128   }
    129 
    130   // Whether the time can be set. Value is false until the first
    131   // CanSetTime response is received.
    132   bool can_set_time_;
    133   bool can_set_time_initialized_;
    134   dbus::ObjectProxy* system_clock_proxy_;
    135   ObserverList<Observer> observers_;
    136 
    137   base::WeakPtrFactory<SystemClockClientImpl> weak_ptr_factory_;
    138 
    139   DISALLOW_COPY_AND_ASSIGN(SystemClockClientImpl);
    140 };
    141 
    142 void SystemClockClient::Observer::SystemClockUpdated() {
    143 }
    144 
    145 void SystemClockClient::Observer::SystemClockCanSetTimeChanged(
    146     bool can_set_time) {
    147 }
    148 
    149 SystemClockClient::SystemClockClient() {
    150 }
    151 
    152 SystemClockClient::~SystemClockClient() {
    153 }
    154 
    155 // static
    156 SystemClockClient* SystemClockClient::Create() {
    157   return new SystemClockClientImpl();
    158 }
    159 
    160 }  // namespace chromeos
    161