12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/system_clock_client.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/fake_system_clock_client.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/bus.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/message.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/object_path.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/object_proxy.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The SystemClockClient implementation used in production.
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SystemClockClientImpl : public SystemClockClient {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit SystemClockClientImpl(dbus::Bus* bus)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : system_clock_proxy_(NULL),
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        weak_ptr_factory_(this) {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_clock_proxy_ = bus->GetObjectProxy(
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        system_clock::kSystemClockServiceName,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        dbus::ObjectPath(system_clock::kSystemClockServicePath));
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Monitor the D-Bus signal for TimeUpdated changes.
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    system_clock_proxy_->ConnectToSignal(
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        system_clock::kSystemClockInterface,
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        system_clock::kSystemClockUpdated,
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&SystemClockClientImpl::TimeUpdatedReceived,
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&SystemClockClientImpl::TimeUpdatedConnected,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SystemClockClientImpl() {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // SystemClockClient overrides:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    observers_.AddObserver(observer);
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    observers_.RemoveObserver(observer);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool HasObserver(Observer* observer) OVERRIDE {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return observers_.HasObserver(observer);
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called when a TimeUpdated signal is received.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TimeUpdatedReceived(dbus::Signal* signal) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "TimeUpdated signal received: " << signal->ToString();
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::MessageReader reader(signal);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FOR_EACH_OBSERVER(Observer, observers_, SystemClockUpdated());
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called when the TimeUpdated signal is initially connected.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TimeUpdatedConnected(const std::string& interface_name,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const std::string& signal_name,
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            bool success) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG_IF(ERROR, !success)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        << "Failed to connect to TimeUpdated signal.";
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dbus::ObjectProxy* system_clock_proxy_;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ObserverList<Observer> observers_;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WeakPtrFactory<SystemClockClientImpl> weak_ptr_factory_;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SystemClockClientImpl);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SystemClockClient::SystemClockClient() {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SystemClockClient::~SystemClockClient() {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SystemClockClient* SystemClockClient::Create(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DBusClientImplementationType type,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dbus::Bus* bus) {
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (type == REAL_DBUS_CLIENT_IMPLEMENTATION) {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return new SystemClockClientImpl(bus);
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return new FakeSystemClockClient();
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
97