Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: chrome/browser/chromeos/dbus/debug_daemon_client.cc

Issue 9838085: Move files inside chrome/browser/chromeos/dbus to chromeos/dbus (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 <fcntl.h>
6 #include <unistd.h>
7
8 #include "chrome/browser/chromeos/dbus/debug_daemon_client.h"
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/chromeos/chromeos_version.h"
13 #include "base/eintr_wrapper.h"
14 #include "base/memory/ref_counted_memory.h"
15 #include "base/platform_file.h"
16 #include "base/string_util.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "dbus/bus.h"
19 #include "dbus/message.h"
20 #include "dbus/object_path.h"
21 #include "dbus/object_proxy.h"
22 #include "net/base/file_stream.h"
23 #include "net/base/io_buffer.h"
24 #include "net/base/net_errors.h"
25 #include "third_party/cros_system_api/dbus/service_constants.h"
26
27 using content::BrowserThread;
28
29 namespace {
30
31 // Used in DebugDaemonClient::EmptySystemStopTracingCallback().
32 void EmptyStopSystemTracingCallbackBody(
33 const scoped_refptr<base::RefCountedString>& unused_result) {
34 }
35
36 // Simple class to encapsulate collecting data from a pipe into a
37 // string. To use, instantiate the class, start i/o, and then delete
38 // the instance on callback. The data should be retrieved before
39 // delete and extracted or copied.
40 //
41 // TODO(sleffler) move data collection to a sub-class so this
42 // can be reused to process data as it is received
43 class PipeReader {
44 public:
45 typedef base::Callback<void(void)>IOCompleteCallback;
46
47 explicit PipeReader(IOCompleteCallback callback)
48 : data_stream_(NULL),
49 io_buffer_(new net::IOBufferWithSize(4096)),
50 weak_ptr_factory_(this),
51 callback_(callback) {
52 pipe_fd_[0] = pipe_fd_[1] = -1;
53 }
54
55 virtual ~PipeReader() {
56 if (pipe_fd_[0] != -1)
57 if (HANDLE_EINTR(close(pipe_fd_[0])) < 0)
58 PLOG(ERROR) << "close[0]";
59 if (pipe_fd_[1] != -1)
60 if (HANDLE_EINTR(close(pipe_fd_[1])) < 0)
61 PLOG(ERROR) << "close[1]";
62 }
63
64 // Returns descriptor for the writeable side of the pipe.
65 int GetWriteFD() { return pipe_fd_[1]; }
66
67 // Closes writeable descriptor; normally used in parent process after fork.
68 void CloseWriteFD() {
69 if (pipe_fd_[1] != -1) {
70 if (HANDLE_EINTR(close(pipe_fd_[1])) < 0)
71 PLOG(ERROR) << "close";
72 pipe_fd_[1] = -1;
73 }
74 }
75
76 // Returns collected data.
77 std::string* data() { return &data_; }
78
79 // Starts data collection. Returns true if stream was setup correctly.
80 // On success data will automatically be accumulated into a string that
81 // can be retrieved with PipeReader::data(). To shutdown collection delete
82 // the instance and/or use PipeReader::OnDataReady(-1).
83 bool StartIO() {
84 // Use a pipe to collect data
85 const int status = HANDLE_EINTR(pipe(pipe_fd_));
86 if (status < 0) {
87 PLOG(ERROR) << "pipe";
88 return false;
89 }
90 base::PlatformFile data_file_ = pipe_fd_[0]; // read side
91 data_stream_.reset(new net::FileStream(data_file_,
92 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_ASYNC,
93 NULL));
94
95 // Post an initial async read to setup data collection
96 int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
97 base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
98 if (rv != net::ERR_IO_PENDING) {
99 LOG(ERROR) << "Unable to post initial read";
100 return false;
101 }
102 return true;
103 }
104
105 // Called when pipe data are available. Can also be used to shutdown
106 // data collection by passing -1 for |byte_count|.
107 void OnDataReady(int byte_count) {
108 DVLOG(1) << "OnDataReady byte_count " << byte_count;
109 if (byte_count <= 0) {
110 callback_.Run(); // signal creator to take data and delete us
111 return;
112 }
113 data_.append(io_buffer_->data(), byte_count);
114
115 // Post another read
116 int rv = data_stream_->Read(io_buffer_.get(), io_buffer_->size(),
117 base::Bind(&PipeReader::OnDataReady, weak_ptr_factory_.GetWeakPtr()));
118 if (rv != net::ERR_IO_PENDING) {
119 LOG(ERROR) << "Unable to post another read";
120 // TODO(sleffler) do something more intelligent?
121 }
122 }
123
124 private:
125 friend class base::RefCounted<PipeReader>;
126
127 int pipe_fd_[2];
128 scoped_ptr<net::FileStream> data_stream_;
129 scoped_refptr<net::IOBufferWithSize> io_buffer_;
130 base::WeakPtrFactory<PipeReader> weak_ptr_factory_;
131 std::string data_;
132 IOCompleteCallback callback_;
133
134 DISALLOW_COPY_AND_ASSIGN(PipeReader);
135 };
136
137 } // namespace
138
139 namespace chromeos {
140
141 // The DebugDaemonClient implementation used in production.
142 class DebugDaemonClientImpl : public DebugDaemonClient {
143 public:
144 explicit DebugDaemonClientImpl(dbus::Bus* bus)
145 : debugdaemon_proxy_(NULL),
146 weak_ptr_factory_(this),
147 pipe_reader_(NULL) {
148 debugdaemon_proxy_ = bus->GetObjectProxy(
149 debugd::kDebugdServiceName,
150 dbus::ObjectPath(debugd::kDebugdServicePath));
151 }
152
153 virtual ~DebugDaemonClientImpl() {}
154
155 // DebugDaemonClient override.
156 virtual void StartSystemTracing() OVERRIDE {
157 dbus::MethodCall method_call(
158 debugd::kDebugdInterface,
159 debugd::kSystraceStart);
160 dbus::MessageWriter writer(&method_call);
161 writer.AppendString("all"); // TODO(sleffler) parameterize category list
162
163 DVLOG(1) << "Requesting a systrace start";
164 debugdaemon_proxy_->CallMethod(
165 &method_call,
166 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
167 base::Bind(&DebugDaemonClientImpl::OnStartSystemTracing,
168 weak_ptr_factory_.GetWeakPtr()));
169 }
170
171 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
172 callback) OVERRIDE {
173 if (pipe_reader_ != NULL) {
174 LOG(ERROR) << "Busy doing StopSystemTracing";
175 return false;
176 }
177
178 pipe_reader_.reset(new PipeReader(
179 base::Bind(&DebugDaemonClientImpl::OnIOComplete,
180 weak_ptr_factory_.GetWeakPtr())));
181 int write_fd = -1;
182 if (!pipe_reader_->StartIO()) {
183 LOG(ERROR) << "Cannot create pipe reader";
184 // NB: continue anyway to shutdown tracing; toss trace data
185 write_fd = HANDLE_EINTR(open("/dev/null", O_WRONLY));
186 // TODO(sleffler) if this fails AppendFileDescriptor will abort
187 } else {
188 write_fd = pipe_reader_->GetWriteFD();
189 }
190
191 DCHECK(callback.is_null());
192 callback_ = callback;
193
194 // Issue the dbus request to stop system tracing
195 dbus::MethodCall method_call(
196 debugd::kDebugdInterface,
197 debugd::kSystraceStop);
198 dbus::MessageWriter writer(&method_call);
199 dbus::FileDescriptor temp(write_fd); // NB: explicit temp for C++98
200 writer.AppendFileDescriptor(temp);
201
202 DVLOG(1) << "Requesting a systrace stop";
203 debugdaemon_proxy_->CallMethod(
204 &method_call,
205 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
206 base::Bind(&DebugDaemonClientImpl::OnRequestStopSystemTracing,
207 weak_ptr_factory_.GetWeakPtr()));
208
209 pipe_reader_->CloseWriteFD(); // close our copy of fd after send
210
211 return true;
212 }
213
214 private:
215 // Called when a response for StartSystemTracing() is received.
216 void OnStartSystemTracing(dbus::Response* response) {
217 if (!response) {
218 LOG(ERROR) << "Failed to request systrace start";
219 return;
220 }
221 }
222
223 // Called when a response for RequestStopSystemTracing() is received.
224 void OnRequestStopSystemTracing(dbus::Response* response) {
225 if (!response) {
226 LOG(ERROR) << "Failed to request systrace stop";
227 pipe_reader_->OnDataReady(-1); // terminate data stream
228 }
229 // NB: requester is signaled when i/o completes
230 }
231
232 // Called when pipe i/o completes; pass data on and delete the instance.
233 void OnIOComplete() {
234 callback_.Run(base::RefCountedString::TakeString(pipe_reader_->data()));
235 pipe_reader_.reset();
236 }
237
238 dbus::ObjectProxy* debugdaemon_proxy_;
239 base::WeakPtrFactory<DebugDaemonClientImpl> weak_ptr_factory_;
240 scoped_ptr<PipeReader> pipe_reader_;
241 StopSystemTracingCallback callback_;
242
243 DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientImpl);
244 };
245
246 // The DebugDaemonClient implementation used on Linux desktop,
247 // which does nothing.
248 class DebugDaemonClientStubImpl : public DebugDaemonClient {
249 // DebugDaemonClient overrides.
250 virtual void StartSystemTracing() OVERRIDE {}
251 virtual bool RequestStopSystemTracing(const StopSystemTracingCallback&
252 callback) OVERRIDE {
253 std::string no_data;
254 callback.Run(base::RefCountedString::TakeString(&no_data));
255 return true;
256 }
257 };
258
259 DebugDaemonClient::DebugDaemonClient() {
260 }
261
262 DebugDaemonClient::~DebugDaemonClient() {
263 }
264
265 // static
266 DebugDaemonClient::StopSystemTracingCallback
267 DebugDaemonClient::EmptyStopSystemTracingCallback() {
268 return base::Bind(&EmptyStopSystemTracingCallbackBody);
269 }
270
271 // static
272 DebugDaemonClient* DebugDaemonClient::Create(DBusClientImplementationType type,
273 dbus::Bus* bus) {
274 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
275 return new DebugDaemonClientImpl(bus);
276 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
277 return new DebugDaemonClientStubImpl();
278 }
279
280 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/dbus/debug_daemon_client.h ('k') | chrome/browser/chromeos/dbus/flimflam_client_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698