1// Copyright (c) 2012 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/image_burner_client.h"
6
7#include "base/bind.h"
8#include "base/compiler_specific.h"
9#include "dbus/bus.h"
10#include "dbus/message.h"
11#include "dbus/object_path.h"
12#include "dbus/object_proxy.h"
13#include "third_party/cros_system_api/dbus/service_constants.h"
14
15namespace chromeos {
16
17namespace {
18
19// The ImageBurnerClient implementation.
20class ImageBurnerClientImpl : public ImageBurnerClient {
21 public:
22  ImageBurnerClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
23
24  virtual ~ImageBurnerClientImpl() {}
25
26  // ImageBurnerClient override.
27  virtual void BurnImage(const std::string& from_path,
28                         const std::string& to_path,
29                         const ErrorCallback& error_callback) OVERRIDE {
30    dbus::MethodCall method_call(imageburn::kImageBurnServiceInterface,
31                                 imageburn::kBurnImage);
32    dbus::MessageWriter writer(&method_call);
33    writer.AppendString(from_path);
34    writer.AppendString(to_path);
35    proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
36                       base::Bind(&ImageBurnerClientImpl::OnBurnImage,
37                                  weak_ptr_factory_.GetWeakPtr(),
38                                  error_callback));
39  }
40
41  // ImageBurnerClient override.
42  virtual void SetEventHandlers(
43      const BurnFinishedHandler& burn_finished_handler,
44      const BurnProgressUpdateHandler& burn_progress_update_handler) OVERRIDE {
45    burn_finished_handler_ = burn_finished_handler;
46    burn_progress_update_handler_ = burn_progress_update_handler;
47  }
48
49  // ImageBurnerClient override.
50  virtual void ResetEventHandlers() OVERRIDE {
51    burn_finished_handler_.Reset();
52    burn_progress_update_handler_.Reset();
53  }
54
55 protected:
56  virtual void Init(dbus::Bus* bus) OVERRIDE {
57    proxy_ =
58        bus->GetObjectProxy(imageburn::kImageBurnServiceName,
59                            dbus::ObjectPath(imageburn::kImageBurnServicePath));
60    proxy_->ConnectToSignal(
61        imageburn::kImageBurnServiceInterface,
62        imageburn::kSignalBurnFinishedName,
63        base::Bind(&ImageBurnerClientImpl::OnBurnFinished,
64                   weak_ptr_factory_.GetWeakPtr()),
65        base::Bind(&ImageBurnerClientImpl::OnSignalConnected,
66                   weak_ptr_factory_.GetWeakPtr()));
67    proxy_->ConnectToSignal(
68        imageburn::kImageBurnServiceInterface,
69        imageburn::kSignalBurnUpdateName,
70        base::Bind(&ImageBurnerClientImpl::OnBurnProgressUpdate,
71                   weak_ptr_factory_.GetWeakPtr()),
72        base::Bind(&ImageBurnerClientImpl::OnSignalConnected,
73                   weak_ptr_factory_.GetWeakPtr()));
74  }
75
76 private:
77  // Called when a response for BurnImage is received
78  void OnBurnImage(ErrorCallback error_callback, dbus::Response* response) {
79    if (!response) {
80      error_callback.Run();
81      return;
82    }
83  }
84
85  // Handles burn_finished signal and calls |handler|.
86  void OnBurnFinished(dbus::Signal* signal) {
87    dbus::MessageReader reader(signal);
88    std::string target_path;
89    bool success;
90    std::string error;
91    if (!reader.PopString(&target_path) ||
92        !reader.PopBool(&success) ||
93        !reader.PopString(&error)) {
94      LOG(ERROR) << "Invalid signal: " << signal->ToString();
95      return;
96    }
97    if (!burn_finished_handler_.is_null())
98      burn_finished_handler_.Run(target_path, success, error);
99  }
100
101  // Handles burn_progress_udpate signal and calls |handler|.
102  void OnBurnProgressUpdate(dbus::Signal* signal) {
103    dbus::MessageReader reader(signal);
104    std::string target_path;
105    int64 num_bytes_burnt;
106    int64 total_size;
107    if (!reader.PopString(&target_path) ||
108        !reader.PopInt64(&num_bytes_burnt) ||
109        !reader.PopInt64(&total_size)) {
110      LOG(ERROR) << "Invalid signal: " << signal->ToString();
111      return;
112    }
113    if (!burn_progress_update_handler_.is_null())
114      burn_progress_update_handler_.Run(target_path, num_bytes_burnt,
115                                        total_size);
116  }
117
118  // Handles the result of signal connection setup.
119  void OnSignalConnected(const std::string& interface,
120                         const std::string& signal,
121                         bool succeeded) {
122    LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
123        signal << " failed.";
124  }
125
126  dbus::ObjectProxy* proxy_;
127  BurnFinishedHandler burn_finished_handler_;
128  BurnProgressUpdateHandler burn_progress_update_handler_;
129
130  // Note: This should remain the last member so it'll be destroyed and
131  // invalidate its weak pointers before any other members are destroyed.
132  base::WeakPtrFactory<ImageBurnerClientImpl> weak_ptr_factory_;
133
134  DISALLOW_COPY_AND_ASSIGN(ImageBurnerClientImpl);
135};
136
137}  // namespace
138
139ImageBurnerClient::ImageBurnerClient() {
140}
141
142ImageBurnerClient::~ImageBurnerClient() {
143}
144
145// static
146ImageBurnerClient* ImageBurnerClient::Create() {
147  return new ImageBurnerClientImpl();
148}
149
150}  // namespace chromeos
151