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

Side by Side Diff: chrome/browser/devtools/devtools_adb_bridge.cc

Issue 12559008: DevTools: add backend for discovering connected ADB devices. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Same with Fetch for fetching discovery pages. Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
(Empty)
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 "chrome/browser/devtools/devtools_adb_bridge.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/logging.h"
13 #include "base/message_loop_proxy.h"
14 #include "base/stringprintf.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/threading/thread.h"
17 #include "chrome/browser/devtools/adb_client_socket.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "net/base/io_buffer.h"
20 #include "net/url_request/url_request_context_getter.h"
21
22 using content::BrowserThread;
23
24 namespace {
25
26 static const char* kDevToolsAdbBridgeThreadName = "Chrome_DevToolsADBThread";
27 const int kAdbPort = 5037;
28 const int kBufferSize = 16 * 1024;
29
30 } // namespace
31
32 struct DevToolsAdbBridge::RequestInfo {
33 Callback callback;
34 scoped_refptr<net::IOBuffer> buffer;
35 std::string data;
36 };
37
38 // static
39 DevToolsAdbBridge* DevToolsAdbBridge::Start(Profile* profile) {
40 return new DevToolsAdbBridge(profile);
41 }
42
43 void DevToolsAdbBridge::Stop() {
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
45 if (!thread_.get())
46 return;
47 BrowserThread::PostTaskAndReply(
48 BrowserThread::FILE, FROM_HERE,
49 base::Bind(&DevToolsAdbBridge::StopHandlerOnFileThread, this),
50 base::Bind(&DevToolsAdbBridge::ResetHandlerAndReleaseOnUIThread, this));
51 }
52
53 void DevToolsAdbBridge::Query(
54 const std::string query,
55 const Callback& callback) {
56 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
57
58 // There is a race condition in case Query immediately follows start. We
59 // consider it Ok since query is polling anyways.
60 if (!thread_.get()) {
61 callback.Run("ADB is not yet connected", std::string());
62 return;
63 }
64 thread_->message_loop()->PostTask(
65 FROM_HERE,
66 base::Bind(&DevToolsAdbBridge::QueryOnHandlerThread,
67 this, query, callback));
68 }
69
70 void DevToolsAdbBridge::Fetch(
71 const std::string url,
72 const Callback& callback) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74
75 thread_->message_loop()->PostTask(
76 FROM_HERE,
77 base::Bind(&DevToolsAdbBridge::FetchOnHandlerThread,
78 this, url, callback));
79 }
80
81 DevToolsAdbBridge::DevToolsAdbBridge(Profile* profile)
82 : profile_(profile) {
83 // Balanced in ResetThreadAndRelease().
84 AddRef();
85
86 thread_.reset(new base::Thread(kDevToolsAdbBridgeThreadName));
87 BrowserThread::PostTask(
88 BrowserThread::FILE, FROM_HERE,
89 base::Bind(&DevToolsAdbBridge::StartHandlerOnFileThread, this));
90 }
91
92 DevToolsAdbBridge::~DevToolsAdbBridge() {
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94 // Stop() must be called prior to destruction.
95 DCHECK(thread_.get() == NULL);
96 }
97
98 void DevToolsAdbBridge::StartHandlerOnFileThread() {
99 base::Thread::Options options;
100 options.message_loop_type = MessageLoop::TYPE_IO;
101 if (!thread_->StartWithOptions(options)) {
102 BrowserThread::PostTask(
103 BrowserThread::UI, FROM_HERE,
104 base::Bind(&DevToolsAdbBridge::ResetHandlerOnUIThread, this));
105 return;
106 }
107
108 thread_->message_loop()->PostTask(
109 FROM_HERE,
110 base::Bind(&DevToolsAdbBridge::InitOnHandlerThread, this));
111 }
112
113 // Runs on FILE thread to make sure that it is serialized against
114 // {Start|Stop}HandlerThread and to allow calling pthread_join.
115 void DevToolsAdbBridge::StopHandlerOnFileThread() {
116 if (!thread_->message_loop())
117 return;
118 thread_->message_loop()->PostTask(
119 FROM_HERE,
120 base::Bind(&DevToolsAdbBridge::TeardownOnHandlerThread, this));
121 // Thread::Stop joins the thread.
122 thread_->Stop();
123 }
124
125 void DevToolsAdbBridge::ResetHandlerAndReleaseOnUIThread() {
126 ResetHandlerOnUIThread();
127 Release();
128 }
129
130 void DevToolsAdbBridge::ResetHandlerOnUIThread() {
131 thread_.reset();
132 }
133
134 void DevToolsAdbBridge::InitOnHandlerThread() {
135 }
136
137 void DevToolsAdbBridge::QueryOnHandlerThread(
138 const std::string query,
139 const Callback& callback) {
140 ADBClientSocket::Query(
141 kAdbPort, query,
142 base::Bind(&DevToolsAdbBridge::QueryResponseOnHandlerThread,
143 base::Unretained(this), callback));
144 }
145
146 void DevToolsAdbBridge::FetchOnHandlerThread(
147 const std::string url,
148 const Callback& callback) {
149 net::URLRequestContext* context =
150 profile_->GetRequestContext()->GetURLRequestContext();
151 net::URLRequest* request = new net::URLRequest(GURL(url), this, context);
152 RequestInfo info;
153 info.callback = callback;
154 info.buffer = new net::IOBuffer(kBufferSize);
155 info.data = "";
156 request_info_[request] = info;
157 request->Start();
158 }
159
160 void DevToolsAdbBridge::QueryResponseOnHandlerThread(
161 const Callback& callback,
162 const std::string& error,
163 const std::string& response) {
164 BrowserThread::PostTask(
165 BrowserThread::UI, FROM_HERE,
166 base::Bind(&DevToolsAdbBridge::RespondOnUIThread, this,
167 callback, error, response));
168 }
169
170 void DevToolsAdbBridge::TeardownOnHandlerThread() {
171 }
172
173 void DevToolsAdbBridge::RespondOnUIThread(
174 const Callback& callback,
175 const std::string& error,
176 const std::string& response) {
177 callback.Run(error, response);
178 }
179
180 // Called on the handler thread.
181 void DevToolsAdbBridge::OnResponseStarted(net::URLRequest* request) {
182 int bytes_read = 0;
183 // Some servers may treat HEAD requests as GET requests. To free up the
184 // network connection as soon as possible, signal that the request has
185 // completed immediately, without trying to read any data back (all we care
186 // about is the response code and headers, which we already have).
187 net::IOBuffer* buffer = request_info_[request].buffer.get();
188 if (request->status().is_success())
189 request->Read(buffer, kBufferSize, &bytes_read);
190 OnReadCompleted(request, bytes_read);
191 }
192
193 // Called on the handler thread.
194 void DevToolsAdbBridge::OnReadCompleted(net::URLRequest* request,
195 int bytes_read) {
196 net::IOBuffer* buffer = request_info_[request].buffer.get();
197 do {
198 if (!request->status().is_success() || bytes_read <= 0)
199 break;
200 request_info_[request].data =
201 request_info_[request].data + std::string(buffer->data(), bytes_read);
202 } while (request->Read(buffer, kBufferSize, &bytes_read));
203
204 // See comments re: HEAD requests in OnResponseStarted().
205 if (!request->status().is_io_pending()) {
206 BrowserThread::PostTask(
207 BrowserThread::UI, FROM_HERE,
208 base::Bind(&DevToolsAdbBridge::RespondOnUIThread, this,
209 request_info_[request].callback, "", request_info_[request].data));
210 request_info_.erase(request);
211 delete request;
212 }
213 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698