| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "content/browser/loader/intercepting_resource_handler.h" | 5 #include "content/browser/loader/intercepting_resource_handler.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 HoldController(std::move(controller)); | 91 HoldController(std::move(controller)); |
| 92 state_ = State::SWAPPING_HANDLERS; | 92 state_ = State::SWAPPING_HANDLERS; |
| 93 | 93 |
| 94 DoLoop(); | 94 DoLoop(); |
| 95 } | 95 } |
| 96 | 96 |
| 97 void InterceptingResourceHandler::OnWillRead( | 97 void InterceptingResourceHandler::OnWillRead( |
| 98 scoped_refptr<net::IOBuffer>* buf, | 98 scoped_refptr<net::IOBuffer>* buf, |
| 99 int* buf_size, | 99 int* buf_size, |
| 100 std::unique_ptr<ResourceController> controller) { | 100 std::unique_ptr<ResourceController> controller) { |
| 101 if (state_ == State::PASS_THROUGH) { | 101 DCHECK_EQ(state_, State::PASS_THROUGH); |
| 102 next_handler_->OnWillRead(buf, buf_size, std::move(controller)); | 102 return next_handler_->OnWillRead(buf, buf_size, std::move(controller)); |
| 103 return; | |
| 104 } | |
| 105 | |
| 106 DCHECK_EQ(State::STARTING, state_); | |
| 107 DCHECK(!first_read_buffer_); | |
| 108 DCHECK_EQ(0, first_read_buffer_size_); | |
| 109 DCHECK(!parent_read_buffer_); | |
| 110 DCHECK(!parent_read_buffer_size_); | |
| 111 | |
| 112 parent_read_buffer_ = buf; | |
| 113 parent_read_buffer_size_ = buf_size; | |
| 114 | |
| 115 state_ = State::SENDING_ON_WILL_READ_TO_OLD_HANDLER; | |
| 116 HoldController(std::move(controller)); | |
| 117 DoLoop(); | |
| 118 } | 103 } |
| 119 | 104 |
| 120 void InterceptingResourceHandler::OnReadCompleted( | 105 void InterceptingResourceHandler::OnReadCompleted( |
| 121 int bytes_read, | 106 int bytes_read, |
| 122 std::unique_ptr<ResourceController> controller) { | 107 std::unique_ptr<ResourceController> controller) { |
| 123 DCHECK(!has_controller()); | 108 DCHECK(!has_controller()); |
| 109 DCHECK_EQ(state_, State::PASS_THROUGH); |
| 110 DCHECK_GE(bytes_read, 0); |
| 124 | 111 |
| 125 DCHECK_GE(bytes_read, 0); | 112 next_handler_->OnReadCompleted(bytes_read, std::move(controller)); |
| 126 if (state_ == State::PASS_THROUGH) { | |
| 127 if (first_read_buffer_double_) { | |
| 128 // |first_read_buffer_double_| was allocated and the user wrote data to | |
| 129 // the buffer, but switching has not been done after all. | |
| 130 memcpy(first_read_buffer_->data(), first_read_buffer_double_->data(), | |
| 131 bytes_read); | |
| 132 first_read_buffer_ = nullptr; | |
| 133 first_read_buffer_double_ = nullptr; | |
| 134 } | |
| 135 next_handler_->OnReadCompleted(bytes_read, std::move(controller)); | |
| 136 return; | |
| 137 } | |
| 138 | |
| 139 DCHECK_EQ(State::WAITING_FOR_ON_READ_COMPLETED, state_); | |
| 140 first_read_buffer_bytes_read_ = bytes_read; | |
| 141 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER; | |
| 142 HoldController(std::move(controller)); | |
| 143 DoLoop(); | |
| 144 } | 113 } |
| 145 | 114 |
| 146 void InterceptingResourceHandler::OnResponseCompleted( | 115 void InterceptingResourceHandler::OnResponseCompleted( |
| 147 const net::URLRequestStatus& status, | 116 const net::URLRequestStatus& status, |
| 148 std::unique_ptr<ResourceController> controller) { | 117 std::unique_ptr<ResourceController> controller) { |
| 118 if (!new_handler_) |
| 119 state_ = State::PASS_THROUGH; |
| 120 |
| 149 if (state_ == State::PASS_THROUGH) { | 121 if (state_ == State::PASS_THROUGH) { |
| 150 LayeredResourceHandler::OnResponseCompleted(status, std::move(controller)); | |
| 151 return; | |
| 152 } | |
| 153 if (!new_handler_) { | |
| 154 // Therer is only one ResourceHandler in this InterceptingResourceHandler. | |
| 155 state_ = State::PASS_THROUGH; | |
| 156 first_read_buffer_double_ = nullptr; | |
| 157 next_handler_->OnResponseCompleted(status, std::move(controller)); | 122 next_handler_->OnResponseCompleted(status, std::move(controller)); |
| 158 return; | 123 return; |
| 159 } | 124 } |
| 160 | 125 |
| 161 // There are two ResourceHandlers in this InterceptingResourceHandler. | 126 // There are two ResourceHandlers in this InterceptingResourceHandler. |
| 162 // |next_handler_| is the old handler and |new_handler_| is the new handler. | 127 // |next_handler_| is the old handler and |new_handler_| is the new handler. |
| 163 // As written in the class comment, this class assumes that the old handler | 128 // As written in the class comment, this class assumes that the old handler |
| 164 // will immediately call Resume() in OnResponseCompleted. | 129 // will immediately call Resume() in OnResponseCompleted. |
| 165 bool was_resumed = false; | 130 bool was_resumed = false; |
| 166 // TODO(mmenke): Get rid of NullResourceController and do something more | 131 // TODO(mmenke): Get rid of NullResourceController and do something more |
| 167 // reasonable. | 132 // reasonable. |
| 168 next_handler_->OnResponseCompleted( | 133 next_handler_->OnResponseCompleted( |
| 169 status, base::MakeUnique<NullResourceController>(&was_resumed)); | 134 status, base::MakeUnique<NullResourceController>(&was_resumed)); |
| 170 DCHECK(was_resumed); | 135 DCHECK(was_resumed); |
| 171 | 136 |
| 172 state_ = State::PASS_THROUGH; | 137 state_ = State::PASS_THROUGH; |
| 173 first_read_buffer_double_ = nullptr; | |
| 174 next_handler_ = std::move(new_handler_); | 138 next_handler_ = std::move(new_handler_); |
| 175 next_handler_->OnResponseCompleted(status, std::move(controller)); | 139 next_handler_->OnResponseCompleted(status, std::move(controller)); |
| 176 } | 140 } |
| 177 | 141 |
| 178 void InterceptingResourceHandler::UseNewHandler( | 142 void InterceptingResourceHandler::UseNewHandler( |
| 179 std::unique_ptr<ResourceHandler> new_handler, | 143 std::unique_ptr<ResourceHandler> new_handler, |
| 180 const std::string& payload_for_old_handler) { | 144 const std::string& payload_for_old_handler) { |
| 181 new_handler_ = std::move(new_handler); | 145 new_handler_ = std::move(new_handler); |
| 182 new_handler_->SetDelegate(delegate()); | 146 new_handler_->SetDelegate(delegate()); |
| 183 payload_for_old_handler_ = payload_for_old_handler; | 147 payload_for_old_handler_ = payload_for_old_handler; |
| 184 } | 148 } |
| 185 | 149 |
| 186 void InterceptingResourceHandler::DoLoop() { | 150 void InterceptingResourceHandler::DoLoop() { |
| 187 DCHECK(!in_do_loop_); | 151 DCHECK(!in_do_loop_); |
| 188 DCHECK(!advance_to_next_state_); | 152 DCHECK(!advance_to_next_state_); |
| 189 | 153 |
| 190 base::AutoReset<bool> auto_in_do_loop(&in_do_loop_, true); | 154 base::AutoReset<bool> auto_in_do_loop(&in_do_loop_, true); |
| 191 advance_to_next_state_ = true; | 155 advance_to_next_state_ = true; |
| 192 | 156 |
| 193 while (advance_to_next_state_) { | 157 while (advance_to_next_state_) { |
| 194 advance_to_next_state_ = false; | 158 advance_to_next_state_ = false; |
| 195 | 159 |
| 196 switch (state_) { | 160 switch (state_) { |
| 197 case State::STARTING: | 161 case State::STARTING: |
| 198 case State::WAITING_FOR_ON_READ_COMPLETED: | |
| 199 case State::PASS_THROUGH: | 162 case State::PASS_THROUGH: |
| 200 NOTREACHED(); | 163 NOTREACHED(); |
| 201 break; | 164 break; |
| 202 case State::SENDING_ON_WILL_READ_TO_OLD_HANDLER: | |
| 203 SendOnWillReadToOldHandler(); | |
| 204 break; | |
| 205 case State::WAITING_FOR_OLD_HANDLERS_BUFFER: | |
| 206 OnBufferReceived(); | |
| 207 break; | |
| 208 case State::SENDING_ON_WILL_START_TO_NEW_HANDLER: | 165 case State::SENDING_ON_WILL_START_TO_NEW_HANDLER: |
| 209 SendOnResponseStartedToNewHandler(); | 166 SendOnResponseStartedToNewHandler(); |
| 210 break; | 167 break; |
| 211 case State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER: | |
| 212 if (first_read_buffer_double_) { | |
| 213 // OnWillRead has been called, so copying the data from | |
| 214 // |first_read_buffer_double_| to |first_read_buffer_| will be needed | |
| 215 // when OnReadCompleted is called. | |
| 216 state_ = State::WAITING_FOR_ON_READ_COMPLETED; | |
| 217 } else { | |
| 218 // OnWillRead has not been called, so no special handling will be | |
| 219 // needed from now on. | |
| 220 state_ = State::PASS_THROUGH; | |
| 221 } | |
| 222 ResumeInternal(); | |
| 223 break; | |
| 224 case State::SWAPPING_HANDLERS: | 168 case State::SWAPPING_HANDLERS: |
| 225 SendOnResponseStartedToOldHandler(); | 169 SendOnResponseStartedToOldHandler(); |
| 226 break; | 170 break; |
| 227 case State::SENDING_PAYLOAD_TO_OLD_HANDLER: | 171 case State::SENDING_PAYLOAD_TO_OLD_HANDLER: |
| 228 SendPayloadToOldHandler(); | 172 SendPayloadToOldHandler(); |
| 229 break; | 173 break; |
| 230 case State::RECEIVING_BUFFER_FROM_OLD_HANDLER: | 174 case State::RECEIVING_BUFFER_FROM_OLD_HANDLER: |
| 231 ReceivedBufferFromOldHandler(); | 175 ReceivedBufferFromOldHandler(); |
| 232 break; | 176 break; |
| 233 case State::SENDING_BUFFER_TO_NEW_HANDLER: | |
| 234 SendFirstReadBufferToNewHandler(); | |
| 235 break; | |
| 236 case State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER: | |
| 237 ReceivedBufferFromNewHandler(); | |
| 238 break; | |
| 239 } | 177 } |
| 240 } | 178 } |
| 241 } | 179 } |
| 242 | 180 |
| 243 void InterceptingResourceHandler::ResumeInternal() { | 181 void InterceptingResourceHandler::ResumeInternal() { |
| 244 DCHECK(has_controller()); | 182 DCHECK(has_controller()); |
| 245 if (state_ == State::STARTING || | 183 if (state_ == State::STARTING || |
| 246 state_ == State::WAITING_FOR_ON_READ_COMPLETED || | |
| 247 state_ == State::PASS_THROUGH) { | 184 state_ == State::PASS_THROUGH) { |
| 248 // Uninteresting Resume: just delegate to the original resource controller. | 185 // Uninteresting Resume: just delegate to the original resource controller. |
| 249 Resume(); | 186 Resume(); |
| 250 return; | 187 return; |
| 251 } | 188 } |
| 252 | 189 |
| 253 // If called recusively from a DoLoop, advance state when returning to the | 190 // If called recusively from a DoLoop, advance state when returning to the |
| 254 // loop. | 191 // loop. |
| 255 if (in_do_loop_) { | 192 if (in_do_loop_) { |
| 256 DCHECK(!advance_to_next_state_); | 193 DCHECK(!advance_to_next_state_); |
| 257 advance_to_next_state_ = true; | 194 advance_to_next_state_ = true; |
| 258 return; | 195 return; |
| 259 } | 196 } |
| 260 | 197 |
| 261 // Can't call DoLoop synchronously, as it may call into |next_handler_| | 198 // Can't call DoLoop synchronously, as it may call into |next_handler_| |
| 262 // synchronously, which is what called Resume(). | 199 // synchronously, which is what called Resume(). |
| 263 base::ThreadTaskRunnerHandle::Get()->PostTask( | 200 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 264 FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop, | 201 FROM_HERE, base::Bind(&InterceptingResourceHandler::DoLoop, |
| 265 weak_ptr_factory_.GetWeakPtr())); | 202 weak_ptr_factory_.GetWeakPtr())); |
| 266 } | 203 } |
| 267 | 204 |
| 268 void InterceptingResourceHandler::SendOnWillReadToOldHandler() { | |
| 269 DCHECK_EQ(State::SENDING_ON_WILL_READ_TO_OLD_HANDLER, state_); | |
| 270 | |
| 271 state_ = State::WAITING_FOR_OLD_HANDLERS_BUFFER; | |
| 272 next_handler_->OnWillRead(&first_read_buffer_, &first_read_buffer_size_, | |
| 273 base::MakeUnique<Controller>(this)); | |
| 274 } | |
| 275 | |
| 276 void InterceptingResourceHandler::OnBufferReceived() { | |
| 277 DCHECK_EQ(State::WAITING_FOR_OLD_HANDLERS_BUFFER, state_); | |
| 278 | |
| 279 // TODO(mmenke): If this method is just going to allocate a double buffer | |
| 280 // anyways, can the call to the old handler's OnWillRead be removed? That | |
| 281 // would mean handling replaying data in the case that |next_handler_|'s | |
| 282 // buffer is smaller than the double buffer, but SendPayloadToOldHandler | |
| 283 // already handles that case, anyways, so could share that code with the | |
| 284 // no-swap path as well. Or better, just have MimeSniffingResourceHandler | |
| 285 // create and manage the buffer itself. | |
| 286 first_read_buffer_double_ = | |
| 287 new net::IOBuffer(static_cast<size_t>(first_read_buffer_size_)); | |
| 288 *parent_read_buffer_ = first_read_buffer_double_; | |
| 289 *parent_read_buffer_size_ = first_read_buffer_size_; | |
| 290 | |
| 291 parent_read_buffer_ = nullptr; | |
| 292 parent_read_buffer_size_ = nullptr; | |
| 293 | |
| 294 state_ = State::STARTING; | |
| 295 Resume(); | |
| 296 } | |
| 297 | |
| 298 void InterceptingResourceHandler::SendOnResponseStartedToOldHandler() { | 205 void InterceptingResourceHandler::SendOnResponseStartedToOldHandler() { |
| 299 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; | 206 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; |
| 300 next_handler_->OnResponseStarted(response_.get(), | 207 next_handler_->OnResponseStarted(response_.get(), |
| 301 base::MakeUnique<Controller>(this)); | 208 base::MakeUnique<Controller>(this)); |
| 302 } | 209 } |
| 303 | 210 |
| 304 void InterceptingResourceHandler::SendPayloadToOldHandler() { | 211 void InterceptingResourceHandler::SendPayloadToOldHandler() { |
| 305 DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_); | 212 DCHECK_EQ(State::SENDING_PAYLOAD_TO_OLD_HANDLER, state_); |
| 306 DCHECK(has_controller()); | 213 DCHECK(has_controller()); |
| 307 | 214 |
| 308 if (static_cast<size_t>(payload_bytes_written_) == | 215 if (static_cast<size_t>(payload_bytes_written_) == |
| 309 payload_for_old_handler_.size()) { | 216 payload_for_old_handler_.size()) { |
| 310 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); | 217 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); |
| 311 if (payload_for_old_handler_.empty()) { | 218 if (payload_for_old_handler_.empty()) { |
| 312 // If there is no payload, just finalize the request on the old handler. | 219 // If there is no payload, just finalize the request on the old handler. |
| 313 status = net::URLRequestStatus::FromError(net::ERR_ABORTED); | 220 status = net::URLRequestStatus::FromError(net::ERR_ABORTED); |
| 314 } | 221 } |
| 315 bool was_resumed = false; | 222 bool was_resumed = false; |
| 316 // TODO(mmenke): Get rid of NullResourceController and do something more | 223 // TODO(mmenke): Get rid of NullResourceController and do something more |
| 317 // reasonable. | 224 // reasonable. |
| 318 next_handler_->OnResponseCompleted( | 225 next_handler_->OnResponseCompleted( |
| 319 status, base::MakeUnique<NullResourceController>(&was_resumed)); | 226 status, base::MakeUnique<NullResourceController>(&was_resumed)); |
| 320 DCHECK(was_resumed); | 227 DCHECK(was_resumed); |
| 321 | 228 |
| 322 next_handler_ = std::move(new_handler_); | 229 next_handler_ = std::move(new_handler_); |
| 323 state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER; | 230 state_ = State::SENDING_ON_WILL_START_TO_NEW_HANDLER; |
| 231 |
| 232 // Note that this call may be a lie--the new handler will often have been |
| 233 // substituted in after the request has actually started, so the new |
| 234 // handler will not have the chance to cancel the request before it starts. |
| 324 next_handler_->OnWillStart(request()->url(), | 235 next_handler_->OnWillStart(request()->url(), |
| 325 base::MakeUnique<Controller>(this)); | 236 base::MakeUnique<Controller>(this)); |
| 326 return; | 237 return; |
| 327 } | 238 } |
| 328 | 239 |
| 329 state_ = State::RECEIVING_BUFFER_FROM_OLD_HANDLER; | 240 state_ = State::RECEIVING_BUFFER_FROM_OLD_HANDLER; |
| 330 | 241 |
| 331 scoped_refptr<net::IOBuffer> buffer; | 242 DCHECK_EQ(read_buffer_size_, 0); |
| 332 // If |first_read_buffer_| is non-NULL, it was already received from | 243 next_handler_->OnWillRead(&read_buffer_, &read_buffer_size_, |
| 333 // |next_handler_| via OnWillRead. Can just use the buffer. | |
| 334 if (first_read_buffer_) { | |
| 335 DCHECK_GT(first_read_buffer_size_, 0); | |
| 336 | |
| 337 ResumeInternal(); | |
| 338 return; | |
| 339 } | |
| 340 | |
| 341 DCHECK(!first_read_buffer_size_); | |
| 342 next_handler_->OnWillRead(&first_read_buffer_, &first_read_buffer_size_, | |
| 343 base::MakeUnique<Controller>(this)); | 244 base::MakeUnique<Controller>(this)); |
| 344 } | 245 } |
| 345 | 246 |
| 346 void InterceptingResourceHandler::ReceivedBufferFromOldHandler() { | 247 void InterceptingResourceHandler::ReceivedBufferFromOldHandler() { |
| 347 DCHECK_EQ(State::RECEIVING_BUFFER_FROM_OLD_HANDLER, state_); | 248 DCHECK_EQ(State::RECEIVING_BUFFER_FROM_OLD_HANDLER, state_); |
| 348 DCHECK(first_read_buffer_); | 249 DCHECK(read_buffer_); |
| 349 DCHECK_GT(first_read_buffer_size_, 0); | 250 DCHECK_GT(read_buffer_size_, 0); |
| 350 | 251 |
| 351 int bytes_to_copy = | 252 int bytes_to_copy = std::min( |
| 352 std::min(first_read_buffer_size_, | 253 read_buffer_size_, static_cast<int>(payload_for_old_handler_.size() - |
| 353 static_cast<int>(payload_for_old_handler_.size() - | 254 payload_bytes_written_)); |
| 354 payload_bytes_written_)); | 255 memcpy(read_buffer_->data(), |
| 355 memcpy(first_read_buffer_->data(), | |
| 356 payload_for_old_handler_.data() + payload_bytes_written_, | 256 payload_for_old_handler_.data() + payload_bytes_written_, |
| 357 bytes_to_copy); | 257 bytes_to_copy); |
| 358 payload_bytes_written_ += bytes_to_copy; | 258 payload_bytes_written_ += bytes_to_copy; |
| 359 | 259 |
| 360 first_read_buffer_ = nullptr; | 260 read_buffer_ = nullptr; |
| 361 first_read_buffer_size_ = 0; | 261 read_buffer_size_ = 0; |
| 362 | 262 |
| 363 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; | 263 state_ = State::SENDING_PAYLOAD_TO_OLD_HANDLER; |
| 364 next_handler_->OnReadCompleted(bytes_to_copy, | 264 next_handler_->OnReadCompleted(bytes_to_copy, |
| 365 base::MakeUnique<Controller>(this)); | 265 base::MakeUnique<Controller>(this)); |
| 366 } | 266 } |
| 367 | 267 |
| 368 void InterceptingResourceHandler::SendOnResponseStartedToNewHandler() { | 268 void InterceptingResourceHandler::SendOnResponseStartedToNewHandler() { |
| 369 state_ = State::SENDING_ON_RESPONSE_STARTED_TO_NEW_HANDLER; | 269 state_ = State::PASS_THROUGH; |
| 370 next_handler_->OnResponseStarted(response_.get(), | 270 next_handler_->OnResponseStarted(response_.get(), |
| 371 base::MakeUnique<Controller>(this)); | 271 base::MakeUnique<Controller>(this)); |
| 372 } | 272 } |
| 373 | 273 |
| 374 void InterceptingResourceHandler::SendFirstReadBufferToNewHandler() { | |
| 375 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER); | |
| 376 DCHECK(!new_handler_read_buffer_); | |
| 377 DCHECK(!new_handler_read_buffer_size_); | |
| 378 | |
| 379 if (first_read_buffer_bytes_written_ == first_read_buffer_bytes_read_) { | |
| 380 state_ = State::PASS_THROUGH; | |
| 381 first_read_buffer_double_ = nullptr; | |
| 382 ResumeInternal(); | |
| 383 return; | |
| 384 } | |
| 385 | |
| 386 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER; | |
| 387 next_handler_->OnWillRead(&new_handler_read_buffer_, | |
| 388 &new_handler_read_buffer_size_, | |
| 389 base::MakeUnique<Controller>(this)); | |
| 390 } | |
| 391 | |
| 392 void InterceptingResourceHandler::ReceivedBufferFromNewHandler() { | |
| 393 DCHECK_EQ(state_, State::SENDING_BUFFER_TO_NEW_HANDLER_WAITING_FOR_BUFFER); | |
| 394 DCHECK(new_handler_read_buffer_); | |
| 395 DCHECK(new_handler_read_buffer_size_); | |
| 396 | |
| 397 int bytes_to_copy = | |
| 398 std::min(new_handler_read_buffer_size_, | |
| 399 static_cast<int>(first_read_buffer_bytes_read_ - | |
| 400 first_read_buffer_bytes_written_)); | |
| 401 memcpy(new_handler_read_buffer_->data(), | |
| 402 first_read_buffer_double_->data() + first_read_buffer_bytes_written_, | |
| 403 bytes_to_copy); | |
| 404 first_read_buffer_bytes_written_ += bytes_to_copy; | |
| 405 | |
| 406 new_handler_read_buffer_ = nullptr; | |
| 407 new_handler_read_buffer_size_ = 0; | |
| 408 | |
| 409 state_ = State::SENDING_BUFFER_TO_NEW_HANDLER; | |
| 410 next_handler_->OnReadCompleted(bytes_to_copy, | |
| 411 base::MakeUnique<Controller>(this)); | |
| 412 } | |
| 413 | |
| 414 } // namespace content | 274 } // namespace content |
| OLD | NEW |