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

Side by Side Diff: chrome/browser/devtools/device/android_device_manager.cc

Issue 1078733002: Android device manager should not drop WebSocket frame data even if it arrives together with handsh… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/devtools/device/android_device_manager.h" 5 #include "chrome/browser/devtools/device/android_device_manager.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 const std::string& response) { 47 const std::string& response) {
48 response_message_loop->PostTask(FROM_HERE, 48 response_message_loop->PostTask(FROM_HERE,
49 base::Bind(callback, result, response)); 49 base::Bind(callback, result, response));
50 } 50 }
51 51
52 static void PostHttpUpgradeCallback( 52 static void PostHttpUpgradeCallback(
53 scoped_refptr<base::MessageLoopProxy> response_message_loop, 53 scoped_refptr<base::MessageLoopProxy> response_message_loop,
54 const AndroidDeviceManager::HttpUpgradeCallback& callback, 54 const AndroidDeviceManager::HttpUpgradeCallback& callback,
55 int result, 55 int result,
56 const std::string& extensions, 56 const std::string& extensions,
57 const std::string& body_head,
57 scoped_ptr<net::StreamSocket> socket) { 58 scoped_ptr<net::StreamSocket> socket) {
58 response_message_loop->PostTask( 59 response_message_loop->PostTask(
59 FROM_HERE, 60 FROM_HERE,
60 base::Bind(callback, result, extensions, base::Passed(&socket))); 61 base::Bind(callback, result, extensions, body_head,
62 base::Passed(&socket)));
61 } 63 }
62 64
63 class HttpRequest { 65 class HttpRequest {
64 public: 66 public:
65 typedef AndroidDeviceManager::CommandCallback CommandCallback; 67 typedef AndroidDeviceManager::CommandCallback CommandCallback;
66 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback; 68 typedef AndroidDeviceManager::HttpUpgradeCallback HttpUpgradeCallback;
67 69
68 static void CommandRequest(const std::string& request, 70 static void CommandRequest(const std::string& request,
69 const CommandCallback& callback, 71 const CommandCallback& callback,
70 int result, 72 int result,
71 scoped_ptr<net::StreamSocket> socket) { 73 scoped_ptr<net::StreamSocket> socket) {
72 if (result != net::OK) { 74 if (result != net::OK) {
73 callback.Run(result, std::string()); 75 callback.Run(result, std::string());
74 return; 76 return;
75 } 77 }
76 new HttpRequest(socket.Pass(), request, callback); 78 new HttpRequest(socket.Pass(), request, callback);
77 } 79 }
78 80
79 static void HttpUpgradeRequest(const std::string& request, 81 static void HttpUpgradeRequest(const std::string& request,
80 const HttpUpgradeCallback& callback, 82 const HttpUpgradeCallback& callback,
81 int result, 83 int result,
82 scoped_ptr<net::StreamSocket> socket) { 84 scoped_ptr<net::StreamSocket> socket) {
83 if (result != net::OK) { 85 if (result != net::OK) {
84 callback.Run(result, "", make_scoped_ptr<net::StreamSocket>(nullptr)); 86 callback.Run(
87 result, std::string(), std::string(),
88 make_scoped_ptr<net::StreamSocket>(nullptr));
85 return; 89 return;
86 } 90 }
87 new HttpRequest(socket.Pass(), request, callback); 91 new HttpRequest(socket.Pass(), request, callback);
88 } 92 }
89 93
90 private: 94 private:
91 HttpRequest(scoped_ptr<net::StreamSocket> socket, 95 HttpRequest(scoped_ptr<net::StreamSocket> socket,
92 const std::string& request, 96 const std::string& request,
93 const CommandCallback& callback) 97 const CommandCallback& callback)
94 : socket_(socket.Pass()), 98 : socket_(socket.Pass()),
95 command_callback_(callback), 99 command_callback_(callback),
96 body_pos_(0) { 100 expected_size_(-1),
101 header_size_(0) {
97 SendRequest(request); 102 SendRequest(request);
98 } 103 }
99 104
100 HttpRequest(scoped_ptr<net::StreamSocket> socket, 105 HttpRequest(scoped_ptr<net::StreamSocket> socket,
101 const std::string& request, 106 const std::string& request,
102 const HttpUpgradeCallback& callback) 107 const HttpUpgradeCallback& callback)
103 : socket_(socket.Pass()), 108 : socket_(socket.Pass()),
104 http_upgrade_callback_(callback), 109 http_upgrade_callback_(callback),
105 body_pos_(0) { 110 expected_size_(-1),
111 header_size_(0) {
106 SendRequest(request); 112 SendRequest(request);
107 } 113 }
108 114
109 ~HttpRequest() { 115 ~HttpRequest() {
110 } 116 }
111 117
112 void DoSendRequest(int result) { 118 void DoSendRequest(int result) {
113 while (result != net::ERR_IO_PENDING) { 119 while (result != net::ERR_IO_PENDING) {
114 if (!CheckNetResultOrDie(result)) 120 if (!CheckNetResultOrDie(result))
115 return; 121 return;
(...skipping 19 matching lines...) Expand all
135 new net::IOBuffer(request.size()); 141 new net::IOBuffer(request.size());
136 memcpy(base_buffer->data(), request.data(), request.size()); 142 memcpy(base_buffer->data(), request.data(), request.size());
137 request_ = new net::DrainableIOBuffer(base_buffer.get(), request.size()); 143 request_ = new net::DrainableIOBuffer(base_buffer.get(), request.size());
138 144
139 DoSendRequest(net::OK); 145 DoSendRequest(net::OK);
140 } 146 }
141 147
142 void ReadResponse(int result) { 148 void ReadResponse(int result) {
143 if (!CheckNetResultOrDie(result)) 149 if (!CheckNetResultOrDie(result))
144 return; 150 return;
145 scoped_refptr<net::IOBuffer> response_buffer = 151
146 new net::IOBuffer(kBufferSize); 152 response_buffer_ = new net::IOBuffer(kBufferSize);
147 153
148 result = socket_->Read( 154 result = socket_->Read(
149 response_buffer.get(), 155 response_buffer_.get(),
150 kBufferSize, 156 kBufferSize,
151 base::Bind(&HttpRequest::OnResponseData, base::Unretained(this), 157 base::Bind(&HttpRequest::OnResponseData, base::Unretained(this)));
152 response_buffer,
153 -1));
154 if (result != net::ERR_IO_PENDING) 158 if (result != net::ERR_IO_PENDING)
155 OnResponseData(response_buffer, -1, result); 159 OnResponseData(result);
156 } 160 }
157 161
158 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer, 162 void OnResponseData(int result) {
159 int bytes_total,
160 int result) {
161 if (!CheckNetResultOrDie(result)) 163 if (!CheckNetResultOrDie(result))
162 return; 164 return;
163 if (result == 0) { 165 if (result == 0) {
164 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED); 166 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
165 return; 167 return;
166 } 168 }
167 169
168 response_ += std::string(response_buffer->data(), result); 170 response_.append(response_buffer_->data(), result);
169 int expected_length = 0; 171 if (expected_size_ < 0) {
170 if (bytes_total < 0) { 172 int expected_length = 0;
173
171 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header. 174 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header.
172 std::string content_length = ExtractHeader("Content-Length:"); 175 std::string content_length = ExtractHeader("Content-Length:");
173 if (!content_length.empty()) { 176 if (!content_length.empty()) {
174 if (!base::StringToInt(content_length, &expected_length)) { 177 if (!base::StringToInt(content_length, &expected_length)) {
175 CheckNetResultOrDie(net::ERR_FAILED); 178 CheckNetResultOrDie(net::ERR_FAILED);
176 return; 179 return;
177 } 180 }
178 } 181 }
179 182
180 body_pos_ = response_.find("\r\n\r\n"); 183 header_size_ = response_.find("\r\n\r\n");
181 if (body_pos_ != std::string::npos) { 184 if (header_size_ != std::string::npos) {
182 body_pos_ += 4; 185 header_size_ += 4;
183 bytes_total = body_pos_ + expected_length; 186 expected_size_ = header_size_ + expected_length;
184 } 187 }
185 } 188 }
186 189
187 if (bytes_total == static_cast<int>(response_.length())) { 190 // WebSocket handshake doesn't contain the Content-Length. For this case,
191 // |expected_size_| is set to the size of the header (handshake).
192 // Some WebSocket frames can be already received into |response_|.
193 if (static_cast<int>(response_.length()) >= expected_size_) {
194 const std::string& body = response_.substr(header_size_);
188 if (!command_callback_.is_null()) { 195 if (!command_callback_.is_null()) {
189 command_callback_.Run(net::OK, response_.substr(body_pos_)); 196 command_callback_.Run(net::OK, body);
190 } else { 197 } else {
198 // Pass the WebSocket frames (in |body|), too.
191 http_upgrade_callback_.Run(net::OK, 199 http_upgrade_callback_.Run(net::OK,
192 ExtractHeader("Sec-WebSocket-Extensions:"), socket_.Pass()); 200 ExtractHeader("Sec-WebSocket-Extensions:"), body, socket_.Pass());
193 } 201 }
194 delete this; 202 delete this;
195 return; 203 return;
196 } 204 }
197 205
198 result = socket_->Read( 206 result = socket_->Read(
199 response_buffer.get(), 207 response_buffer_.get(),
200 kBufferSize, 208 kBufferSize,
201 base::Bind(&HttpRequest::OnResponseData, 209 base::Bind(&HttpRequest::OnResponseData, base::Unretained(this)));
202 base::Unretained(this),
203 response_buffer,
204 bytes_total));
205 if (result != net::ERR_IO_PENDING) 210 if (result != net::ERR_IO_PENDING)
206 OnResponseData(response_buffer, bytes_total, result); 211 OnResponseData(result);
207 } 212 }
208 213
209 std::string ExtractHeader(const std::string& header) { 214 std::string ExtractHeader(const std::string& header) {
210 size_t start_pos = response_.find(header); 215 size_t start_pos = response_.find(header);
211 if (start_pos == std::string::npos) 216 if (start_pos == std::string::npos)
212 return std::string(); 217 return std::string();
213 218
214 size_t endline_pos = response_.find("\n", start_pos); 219 size_t endline_pos = response_.find("\n", start_pos);
215 if (endline_pos == std::string::npos) 220 if (endline_pos == std::string::npos)
216 return std::string(); 221 return std::string();
217 222
218 std::string value = response_.substr( 223 std::string value = response_.substr(
219 start_pos + header.length(), endline_pos - start_pos - header.length()); 224 start_pos + header.length(), endline_pos - start_pos - header.length());
220 base::TrimWhitespace(value, base::TRIM_ALL, &value); 225 base::TrimWhitespace(value, base::TRIM_ALL, &value);
221 return value; 226 return value;
222 } 227 }
223 228
224 bool CheckNetResultOrDie(int result) { 229 bool CheckNetResultOrDie(int result) {
225 if (result >= 0) 230 if (result >= 0)
226 return true; 231 return true;
227 if (!command_callback_.is_null()) { 232 if (!command_callback_.is_null()) {
228 command_callback_.Run(result, std::string()); 233 command_callback_.Run(result, std::string());
229 } else { 234 } else {
230 http_upgrade_callback_.Run( 235 http_upgrade_callback_.Run(
231 result, "", make_scoped_ptr<net::StreamSocket>(nullptr)); 236 result, std::string(), std::string(),
237 make_scoped_ptr<net::StreamSocket>(nullptr));
232 } 238 }
233 delete this; 239 delete this;
234 return false; 240 return false;
235 } 241 }
236 242
237 scoped_ptr<net::StreamSocket> socket_; 243 scoped_ptr<net::StreamSocket> socket_;
238 scoped_refptr<net::DrainableIOBuffer> request_; 244 scoped_refptr<net::DrainableIOBuffer> request_;
239 std::string response_; 245 std::string response_;
240 CommandCallback command_callback_; 246 CommandCallback command_callback_;
241 HttpUpgradeCallback http_upgrade_callback_; 247 HttpUpgradeCallback http_upgrade_callback_;
242 size_t body_pos_; 248
249 scoped_refptr<net::IOBuffer> response_buffer_;
250 // Initially -1. Once the end of the header is seen:
251 // - If the Content-Length header is included, this variable is set to the
252 // sum of the header size (including the last two CRLFs) and the value of
253 // the header.
254 // - Otherwise, this variable is set to the size of the header (including the
255 // last two CRLFs).
256 int expected_size_;
257 // Set to the size of the header part in |response_|.
258 size_t header_size_;
243 }; 259 };
244 260
245 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> { 261 class DevicesRequest : public base::RefCountedThreadSafe<DevicesRequest> {
246 public: 262 public:
247 typedef AndroidDeviceManager::DeviceInfo DeviceInfo; 263 typedef AndroidDeviceManager::DeviceInfo DeviceInfo;
248 typedef AndroidDeviceManager::DeviceProvider DeviceProvider; 264 typedef AndroidDeviceManager::DeviceProvider DeviceProvider;
249 typedef AndroidDeviceManager::DeviceProviders DeviceProviders; 265 typedef AndroidDeviceManager::DeviceProviders DeviceProviders;
250 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors; 266 typedef AndroidDeviceManager::DeviceDescriptors DeviceDescriptors;
251 typedef base::Callback<void(scoped_ptr<DeviceDescriptors>)> 267 typedef base::Callback<void(scoped_ptr<DeviceDescriptors>)>
252 DescriptorsCallback; 268 DescriptorsCallback;
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 it->provider, it->serial); 560 it->provider, it->serial);
545 } else { 561 } else {
546 device = found->second.get(); 562 device = found->second.get();
547 } 563 }
548 response.push_back(device); 564 response.push_back(device);
549 new_devices[it->serial] = device->weak_factory_.GetWeakPtr(); 565 new_devices[it->serial] = device->weak_factory_.GetWeakPtr();
550 } 566 }
551 devices_.swap(new_devices); 567 devices_.swap(new_devices);
552 callback.Run(response); 568 callback.Run(response);
553 } 569 }
OLDNEW
« no previous file with comments | « chrome/browser/devtools/device/android_device_manager.h ('k') | chrome/browser/devtools/device/android_web_socket.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698