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