• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SystemClockClientImpl()21   SystemClockClientImpl()
22       : can_set_time_(false),
23         can_set_time_initialized_(false),
24         system_clock_proxy_(NULL),
25         weak_ptr_factory_(this) {}
26 
~SystemClockClientImpl()27   virtual ~SystemClockClientImpl() {
28   }
29 
AddObserver(Observer * observer)30   virtual void AddObserver(Observer* observer) OVERRIDE {
31     observers_.AddObserver(observer);
32   }
33 
RemoveObserver(Observer * observer)34   virtual void RemoveObserver(Observer* observer) OVERRIDE {
35     observers_.RemoveObserver(observer);
36   }
37 
HasObserver(Observer * observer)38   virtual bool HasObserver(Observer* observer) OVERRIDE {
39     return observers_.HasObserver(observer);
40   }
41 
SetTime(int64 time_in_seconds)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 
CanSetTime()53   virtual bool CanSetTime() OVERRIDE { return can_set_time_; }
54 
55  protected:
Init(dbus::Bus * bus)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.
TimeUpdatedReceived(dbus::Signal * signal)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.
TimeUpdatedConnected(const std::string & interface_name,const std::string & signal_name,bool success)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.
OnGetCanSet(dbus::Response * response)94   void OnGetCanSet(dbus::Response* response) {
95     if (!response) {
96       LOG(WARNING) << "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.
GetCanSet()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 
SystemClockUpdated()142 void SystemClockClient::Observer::SystemClockUpdated() {
143 }
144 
SystemClockCanSetTimeChanged(bool can_set_time)145 void SystemClockClient::Observer::SystemClockCanSetTimeChanged(
146     bool can_set_time) {
147 }
148 
SystemClockClient()149 SystemClockClient::SystemClockClient() {
150 }
151 
~SystemClockClient()152 SystemClockClient::~SystemClockClient() {
153 }
154 
155 // static
Create()156 SystemClockClient* SystemClockClient::Create() {
157   return new SystemClockClientImpl();
158 }
159 
160 }  // namespace chromeos
161