 Chromium Code Reviews
 Chromium Code Reviews Issue 5756004:
  Separate BufferedDataSource and BufferedResourceLoader into two files.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 5756004:
  Separate BufferedDataSource and BufferedResourceLoader into two files.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/callback.h" | 5 #include "webkit/glue/media/buffered_data_source.h" | 
| 6 #include "base/compiler_specific.h" | 6 | 
| 7 #include "base/format_macros.h" | |
| 8 #include "base/message_loop.h" | |
| 9 #include "base/process_util.h" | |
| 10 #include "base/stl_util-inl.h" | |
| 11 #include "base/string_number_conversions.h" | |
| 12 #include "base/string_util.h" | |
| 13 #include "media/base/filter_host.h" | 7 #include "media/base/filter_host.h" | 
| 14 #include "media/base/media_format.h" | |
| 15 #include "net/base/load_flags.h" | |
| 16 #include "net/base/net_errors.h" | 8 #include "net/base/net_errors.h" | 
| 17 #include "third_party/WebKit/WebKit/chromium/public/WebKit.h" | 9 #include "net/http/http_util.h" | 
| 18 #include "third_party/WebKit/WebKit/chromium/public/WebKitClient.h" | |
| 19 #include "third_party/WebKit/WebKit/chromium/public/WebString.h" | |
| 20 #include "third_party/WebKit/WebKit/chromium/public/WebURLError.h" | |
| 21 #include "webkit/glue/media/buffered_data_source.h" | |
| 22 #include "webkit/glue/multipart_response_delegate.h" | |
| 23 #include "webkit/glue/webkit_glue.h" | 10 #include "webkit/glue/webkit_glue.h" | 
| 24 #include "webkit/glue/webmediaplayer_impl.h" | |
| 25 | 11 | 
| 26 using WebKit::WebFrame; | 12 using WebKit::WebFrame; | 
| 27 using WebKit::WebString; | 13 using net::HttpUtil; | 
| 
scherkus (not reviewing)
2010/12/14 18:48:19
nit: alphabetize forward declares
 
annacc
2010/12/14 21:10:17
Done.
 | |
| 28 using WebKit::WebURLError; | |
| 29 using WebKit::WebURLLoader; | |
| 30 using WebKit::WebURLRequest; | |
| 31 using WebKit::WebURLResponse; | |
| 32 using webkit_glue::MultipartResponseDelegate; | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 const char kHttpScheme[] = "http"; | |
| 37 const char kHttpsScheme[] = "https"; | |
| 38 const char kDataScheme[] = "data"; | |
| 39 const int64 kPositionNotSpecified = -1; | |
| 40 const int kHttpOK = 200; | |
| 41 const int kHttpPartialContent = 206; | |
| 42 | |
| 43 // Define the number of bytes in a megabyte. | |
| 44 const size_t kMegabyte = 1024 * 1024; | |
| 45 | |
| 46 // Backward capacity of the buffer, by default 2MB. | |
| 47 const size_t kBackwardCapcity = 2 * kMegabyte; | |
| 48 | |
| 49 // Forward capacity of the buffer, by default 10MB. | |
| 50 const size_t kForwardCapacity = 10 * kMegabyte; | |
| 51 | |
| 52 // The threshold of bytes that we should wait until the data arrives in the | |
| 53 // future instead of restarting a new connection. This number is defined in the | |
| 54 // number of bytes, we should determine this value from typical connection speed | |
| 55 // and amount of time for a suitable wait. Now I just make a guess for this | |
| 56 // number to be 2MB. | |
| 57 // TODO(hclam): determine a better value for this. | |
| 58 const int kForwardWaitThreshold = 2 * kMegabyte; | |
| 59 | |
| 60 // Defines how long we should wait for more data before we declare a connection | |
| 61 // timeout and start a new request. | |
| 62 // TODO(hclam): Set it to 5s, calibrate this value later. | |
| 63 const int kTimeoutMilliseconds = 5000; | |
| 64 | |
| 65 // Defines how many times we should try to read from a buffered resource loader | |
| 66 // before we declare a read error. After each failure of read from a buffered | |
| 67 // resource loader, a new one is created to be read. | |
| 68 const int kReadTrials = 3; | |
| 69 | |
| 70 // BufferedDataSource has an intermediate buffer, this value governs the initial | |
| 71 // size of that buffer. It is set to 32KB because this is a typical read size | |
| 72 // of FFmpeg. | |
| 73 const int kInitialReadBufferSize = 32768; | |
| 74 | |
| 75 // Returns true if |url| operates on HTTP protocol. | |
| 76 bool IsHttpProtocol(const GURL& url) { | |
| 77 return url.SchemeIs(kHttpScheme) || url.SchemeIs(kHttpsScheme); | |
| 78 } | |
| 79 | |
| 80 bool IsDataProtocol(const GURL& url) { | |
| 81 return url.SchemeIs(kDataScheme); | |
| 82 } | |
| 83 | |
| 84 } // namespace | |
| 85 | 14 | 
| 86 namespace webkit_glue { | 15 namespace webkit_glue { | 
| 87 | 16 | 
| 88 ///////////////////////////////////////////////////////////////////////////// | |
| 89 // BufferedResourceLoader | |
| 90 BufferedResourceLoader::BufferedResourceLoader( | |
| 91 const GURL& url, | |
| 92 int64 first_byte_position, | |
| 93 int64 last_byte_position) | |
| 94 : buffer_(new media::SeekableBuffer(kBackwardCapcity, kForwardCapacity)), | |
| 95 deferred_(false), | |
| 96 defer_allowed_(true), | |
| 97 completed_(false), | |
| 98 range_requested_(false), | |
| 99 partial_response_(false), | |
| 100 url_(url), | |
| 101 first_byte_position_(first_byte_position), | |
| 102 last_byte_position_(last_byte_position), | |
| 103 start_callback_(NULL), | |
| 104 offset_(0), | |
| 105 content_length_(kPositionNotSpecified), | |
| 106 instance_size_(kPositionNotSpecified), | |
| 107 read_callback_(NULL), | |
| 108 read_position_(0), | |
| 109 read_size_(0), | |
| 110 read_buffer_(NULL), | |
| 111 first_offset_(0), | |
| 112 last_offset_(0), | |
| 113 keep_test_loader_(false) { | |
| 114 } | |
| 115 | |
| 116 BufferedResourceLoader::~BufferedResourceLoader() { | |
| 117 if (!completed_ && url_loader_.get()) | |
| 118 url_loader_->cancel(); | |
| 119 } | |
| 120 | |
| 121 void BufferedResourceLoader::Start(net::CompletionCallback* start_callback, | |
| 122 NetworkEventCallback* event_callback, | |
| 123 WebFrame* frame) { | |
| 124 // Make sure we have not started. | |
| 125 DCHECK(!start_callback_.get()); | |
| 126 DCHECK(!event_callback_.get()); | |
| 127 DCHECK(start_callback); | |
| 128 DCHECK(event_callback); | |
| 129 CHECK(frame); | |
| 130 | |
| 131 start_callback_.reset(start_callback); | |
| 132 event_callback_.reset(event_callback); | |
| 133 | |
| 134 if (first_byte_position_ != kPositionNotSpecified) { | |
| 135 range_requested_ = true; | |
| 136 // TODO(hclam): server may not support range request so |offset_| may not | |
| 137 // equal to |first_byte_position_|. | |
| 138 offset_ = first_byte_position_; | |
| 139 } | |
| 140 | |
| 141 // Increment the reference count right before we start the request. This | |
| 142 // reference will be release when this request has ended. | |
| 143 AddRef(); | |
| 144 | |
| 145 // Prepare the request. | |
| 146 WebURLRequest request(url_); | |
| 147 request.setHTTPHeaderField(WebString::fromUTF8("Range"), | |
| 148 WebString::fromUTF8(GenerateHeaders( | |
| 149 first_byte_position_, | |
| 150 last_byte_position_))); | |
| 151 frame->setReferrerForRequest(request, WebKit::WebURL()); | |
| 152 // TODO(annacc): we should be using createAssociatedURLLoader() instead? | |
| 153 frame->dispatchWillSendRequest(request); | |
| 154 | |
| 155 // This flag is for unittests as we don't want to reset |url_loader| | |
| 156 if (!keep_test_loader_) | |
| 157 url_loader_.reset(WebKit::webKitClient()->createURLLoader()); | |
| 158 | |
| 159 // Start the resource loading. | |
| 160 url_loader_->loadAsynchronously(request, this); | |
| 161 } | |
| 162 | |
| 163 void BufferedResourceLoader::Stop() { | |
| 164 // Reset callbacks. | |
| 165 start_callback_.reset(); | |
| 166 event_callback_.reset(); | |
| 167 read_callback_.reset(); | |
| 168 | |
| 169 // Use the internal buffer to signal that we have been stopped. | |
| 170 // TODO(hclam): Not so pretty to do this. | |
| 171 if (!buffer_.get()) | |
| 172 return; | |
| 173 | |
| 174 // Destroy internal buffer. | |
| 175 buffer_.reset(); | |
| 176 | |
| 177 if (url_loader_.get()) { | |
| 178 if (deferred_) | |
| 179 url_loader_->setDefersLoading(false); | |
| 180 deferred_ = false; | |
| 181 | |
| 182 if (!completed_) { | |
| 183 url_loader_->cancel(); | |
| 184 completed_ = true; | |
| 185 } | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 void BufferedResourceLoader::Read(int64 position, | |
| 190 int read_size, | |
| 191 uint8* buffer, | |
| 192 net::CompletionCallback* read_callback) { | |
| 193 DCHECK(!read_callback_.get()); | |
| 194 DCHECK(buffer_.get()); | |
| 195 DCHECK(read_callback); | |
| 196 DCHECK(buffer); | |
| 197 | |
| 198 // Save the parameter of reading. | |
| 199 read_callback_.reset(read_callback); | |
| 200 read_position_ = position; | |
| 201 read_size_ = read_size; | |
| 202 read_buffer_ = buffer; | |
| 203 | |
| 204 // If read position is beyond the instance size, we cannot read there. | |
| 205 if (instance_size_ != kPositionNotSpecified && | |
| 206 instance_size_ <= read_position_) { | |
| 207 DoneRead(0); | |
| 208 return; | |
| 209 } | |
| 210 | |
| 211 // Make sure |offset_| and |read_position_| does not differ by a large | |
| 212 // amount. | |
| 213 if (read_position_ > offset_ + kint32max || | |
| 214 read_position_ < offset_ + kint32min) { | |
| 215 DoneRead(net::ERR_CACHE_MISS); | |
| 216 return; | |
| 217 } | |
| 218 | |
| 219 // Prepare the parameters. | |
| 220 first_offset_ = static_cast<int>(read_position_ - offset_); | |
| 221 last_offset_ = first_offset_ + read_size_; | |
| 222 | |
| 223 // If we can serve the request now, do the actual read. | |
| 224 if (CanFulfillRead()) { | |
| 225 ReadInternal(); | |
| 226 DisableDeferIfNeeded(); | |
| 227 return; | |
| 228 } | |
| 229 | |
| 230 // If we expected the read request to be fulfilled later, returns | |
| 231 // immediately and let more data to flow in. | |
| 232 if (WillFulfillRead()) | |
| 233 return; | |
| 234 | |
| 235 // Make a callback to report failure. | |
| 236 DoneRead(net::ERR_CACHE_MISS); | |
| 237 } | |
| 238 | |
| 239 int64 BufferedResourceLoader::GetBufferedFirstBytePosition() { | |
| 240 if (buffer_.get()) | |
| 241 return offset_ - static_cast<int>(buffer_->backward_bytes()); | |
| 242 return kPositionNotSpecified; | |
| 243 } | |
| 244 | |
| 245 int64 BufferedResourceLoader::GetBufferedLastBytePosition() { | |
| 246 if (buffer_.get()) | |
| 247 return offset_ + static_cast<int>(buffer_->forward_bytes()) - 1; | |
| 248 return kPositionNotSpecified; | |
| 249 } | |
| 250 | |
| 251 void BufferedResourceLoader::SetAllowDefer(bool is_allowed) { | |
| 252 defer_allowed_ = is_allowed; | |
| 253 DisableDeferIfNeeded(); | |
| 254 } | |
| 255 | |
| 256 void BufferedResourceLoader::SetURLLoaderForTest(WebURLLoader* mock_loader) { | |
| 257 url_loader_.reset(mock_loader); | |
| 258 keep_test_loader_ = true; | |
| 259 } | |
| 260 | |
| 261 ///////////////////////////////////////////////////////////////////////////// | |
| 262 // BufferedResourceLoader, WebKit::WebURLLoaderClient implementations. | |
| 263 void BufferedResourceLoader::willSendRequest( | |
| 264 WebURLLoader* loader, | |
| 265 WebURLRequest& newRequest, | |
| 266 const WebURLResponse& redirectResponse) { | |
| 267 | |
| 268 // The load may have been stopped and |start_callback| is destroyed. | |
| 269 // In this case we shouldn't do anything. | |
| 270 if (!start_callback_.get()) { | |
| 271 // Set the url in the request to an invalid value (empty url). | |
| 272 newRequest.setURL(WebKit::WebURL()); | |
| 273 return; | |
| 274 } | |
| 275 | |
| 276 if (!IsProtocolSupportedForMedia(newRequest.url())) { | |
| 277 // Set the url in the request to an invalid value (empty url). | |
| 278 newRequest.setURL(WebKit::WebURL()); | |
| 279 DoneStart(net::ERR_ADDRESS_INVALID); | |
| 280 Stop(); | |
| 281 return; | |
| 282 } | |
| 283 | |
| 284 url_ = newRequest.url(); | |
| 285 } | |
| 286 | |
| 287 void BufferedResourceLoader::didSendData( | |
| 288 WebURLLoader* loader, | |
| 289 unsigned long long bytes_sent, | |
| 290 unsigned long long total_bytes_to_be_sent) { | |
| 291 NOTIMPLEMENTED(); | |
| 292 } | |
| 293 | |
| 294 void BufferedResourceLoader::didReceiveResponse( | |
| 295 WebURLLoader* loader, | |
| 296 const WebURLResponse& response) { | |
| 297 | |
| 298 // The loader may have been stopped and |start_callback| is destroyed. | |
| 299 // In this case we shouldn't do anything. | |
| 300 if (!start_callback_.get()) | |
| 301 return; | |
| 302 | |
| 303 // We make a strong assumption that when we reach here we have either | |
| 304 // received a response from HTTP/HTTPS protocol or the request was | |
| 305 // successful (in particular range request). So we only verify the partial | |
| 306 // response for HTTP and HTTPS protocol. | |
| 307 if (IsHttpProtocol(url_)) { | |
| 308 int error = net::OK; | |
| 309 | |
| 310 if (response.httpStatusCode() == kHttpPartialContent) | |
| 311 partial_response_ = true; | |
| 312 | |
| 313 if (range_requested_ && partial_response_) { | |
| 314 // If we have verified the partial response and it is correct, we will | |
| 315 // return net::OK. | |
| 316 if (!VerifyPartialResponse(response)) | |
| 317 error = net::ERR_INVALID_RESPONSE; | |
| 318 } else if (response.httpStatusCode() != kHttpOK) { | |
| 319 // We didn't request a range but server didn't reply with "200 OK". | |
| 320 error = net::ERR_FAILED; | |
| 321 } | |
| 322 | |
| 323 if (error != net::OK) { | |
| 324 DoneStart(error); | |
| 325 Stop(); | |
| 326 return; | |
| 327 } | |
| 328 } else { | |
| 329 // For any protocol other than HTTP and HTTPS, assume range request is | |
| 330 // always fulfilled. | |
| 331 partial_response_ = range_requested_; | |
| 332 } | |
| 333 | |
| 334 // Expected content length can be -1, in that case |content_length_| is | |
| 335 // not specified and this is a streaming response. | |
| 336 content_length_ = response.expectedContentLength(); | |
| 337 | |
| 338 // If we have not requested a range, then the size of the instance is equal | |
| 339 // to the content length. | |
| 340 if (!partial_response_) | |
| 341 instance_size_ = content_length_; | |
| 342 | |
| 343 // Calls with a successful response. | |
| 344 DoneStart(net::OK); | |
| 345 } | |
| 346 | |
| 347 void BufferedResourceLoader::didReceiveData( | |
| 348 WebURLLoader* loader, | |
| 349 const char* data, | |
| 350 int data_length) { | |
| 351 DCHECK(!completed_); | |
| 352 DCHECK_GT(data_length, 0); | |
| 353 | |
| 354 // If this loader has been stopped, |buffer_| would be destroyed. | |
| 355 // In this case we shouldn't do anything. | |
| 356 if (!buffer_.get()) | |
| 357 return; | |
| 358 | |
| 359 // Writes more data to |buffer_|. | |
| 360 buffer_->Append(reinterpret_cast<const uint8*>(data), data_length); | |
| 361 | |
| 362 // If there is an active read request, try to fulfill the request. | |
| 363 if (HasPendingRead() && CanFulfillRead()) { | |
| 364 ReadInternal(); | |
| 365 } else if (!defer_allowed_) { | |
| 366 // If we're not allowed to defer, slide the buffer window forward instead | |
| 367 // of deferring. | |
| 368 if (buffer_->forward_bytes() > buffer_->forward_capacity()) { | |
| 369 size_t excess = buffer_->forward_bytes() - buffer_->forward_capacity(); | |
| 370 bool success = buffer_->Seek(excess); | |
| 371 DCHECK(success); | |
| 372 offset_ += first_offset_ + excess; | |
| 373 } | |
| 374 } | |
| 375 | |
| 376 // At last see if the buffer is full and we need to defer the downloading. | |
| 377 EnableDeferIfNeeded(); | |
| 378 | |
| 379 // Notify that we have received some data. | |
| 380 NotifyNetworkEvent(); | |
| 381 } | |
| 382 | |
| 383 void BufferedResourceLoader::didDownloadData( | |
| 384 WebKit::WebURLLoader* loader, | |
| 385 int dataLength) { | |
| 386 NOTIMPLEMENTED(); | |
| 387 } | |
| 388 | |
| 389 void BufferedResourceLoader::didReceiveCachedMetadata( | |
| 390 WebURLLoader* loader, | |
| 391 const char* data, | |
| 392 int data_length) { | |
| 393 NOTIMPLEMENTED(); | |
| 394 } | |
| 395 | |
| 396 void BufferedResourceLoader::didFinishLoading( | |
| 397 WebURLLoader* loader, | |
| 398 double finishTime) { | |
| 399 DCHECK(!completed_); | |
| 400 completed_ = true; | |
| 401 | |
| 402 // If there is a start callback, calls it. | |
| 403 if (start_callback_.get()) { | |
| 404 DoneStart(net::OK); | |
| 405 } | |
| 406 | |
| 407 // If there is a pending read but the request has ended, returns with what | |
| 408 // we have. | |
| 409 if (HasPendingRead()) { | |
| 410 // Make sure we have a valid buffer before we satisfy a read request. | |
| 411 DCHECK(buffer_.get()); | |
| 412 | |
| 413 // Try to fulfill with what is in the buffer. | |
| 414 if (CanFulfillRead()) | |
| 415 ReadInternal(); | |
| 416 else | |
| 417 DoneRead(net::ERR_CACHE_MISS); | |
| 418 } | |
| 419 | |
| 420 // There must not be any outstanding read request. | |
| 421 DCHECK(!HasPendingRead()); | |
| 422 | |
| 423 // Notify that network response is completed. | |
| 424 NotifyNetworkEvent(); | |
| 425 | |
| 426 url_loader_.reset(); | |
| 427 Release(); | |
| 428 } | |
| 429 | |
| 430 void BufferedResourceLoader::didFail( | |
| 431 WebURLLoader* loader, | |
| 432 const WebURLError& error) { | |
| 433 DCHECK(!completed_); | |
| 434 completed_ = true; | |
| 435 | |
| 436 // If there is a start callback, calls it. | |
| 437 if (start_callback_.get()) { | |
| 438 DoneStart(error.reason); | |
| 439 } | |
| 440 | |
| 441 // If there is a pending read but the request failed, return with the | |
| 442 // reason for the error. | |
| 443 if (HasPendingRead()) { | |
| 444 DoneRead(error.reason); | |
| 445 } | |
| 446 | |
| 447 // Notify that network response is completed. | |
| 448 NotifyNetworkEvent(); | |
| 449 | |
| 450 url_loader_.reset(); | |
| 451 Release(); | |
| 452 } | |
| 453 | |
| 454 ///////////////////////////////////////////////////////////////////////////// | |
| 455 // BufferedResourceLoader, private | |
| 456 void BufferedResourceLoader::EnableDeferIfNeeded() { | |
| 457 if (!defer_allowed_) | |
| 458 return; | |
| 459 | |
| 460 if (!deferred_ && | |
| 461 buffer_->forward_bytes() >= buffer_->forward_capacity()) { | |
| 462 deferred_ = true; | |
| 463 | |
| 464 if (url_loader_.get()) | |
| 465 url_loader_->setDefersLoading(true); | |
| 466 | |
| 467 NotifyNetworkEvent(); | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 void BufferedResourceLoader::DisableDeferIfNeeded() { | |
| 472 if (deferred_ && | |
| 473 (!defer_allowed_ || | |
| 474 buffer_->forward_bytes() < buffer_->forward_capacity() / 2)) { | |
| 475 deferred_ = false; | |
| 476 | |
| 477 if (url_loader_.get()) | |
| 478 url_loader_->setDefersLoading(false); | |
| 479 | |
| 480 NotifyNetworkEvent(); | |
| 481 } | |
| 482 } | |
| 483 | |
| 484 bool BufferedResourceLoader::CanFulfillRead() { | |
| 485 // If we are reading too far in the backward direction. | |
| 486 if (first_offset_ < 0 && | |
| 487 first_offset_ + static_cast<int>(buffer_->backward_bytes()) < 0) | |
| 488 return false; | |
| 489 | |
| 490 // If the start offset is too far ahead. | |
| 491 if (first_offset_ >= static_cast<int>(buffer_->forward_bytes())) | |
| 492 return false; | |
| 493 | |
| 494 // At the point, we verified that first byte requested is within the buffer. | |
| 495 // If the request has completed, then just returns with what we have now. | |
| 496 if (completed_) | |
| 497 return true; | |
| 498 | |
| 499 // If the resource request is still active, make sure the whole requested | |
| 500 // range is covered. | |
| 501 if (last_offset_ > static_cast<int>(buffer_->forward_bytes())) | |
| 502 return false; | |
| 503 | |
| 504 return true; | |
| 505 } | |
| 506 | |
| 507 bool BufferedResourceLoader::WillFulfillRead() { | |
| 508 // Reading too far in the backward direction. | |
| 509 if (first_offset_ < 0 && | |
| 510 first_offset_ + static_cast<int>(buffer_->backward_bytes()) < 0) | |
| 511 return false; | |
| 512 | |
| 513 // Try to read too far ahead. | |
| 514 if (last_offset_ > kForwardWaitThreshold) | |
| 515 return false; | |
| 516 | |
| 517 // The resource request has completed, there's no way we can fulfill the | |
| 518 // read request. | |
| 519 if (completed_) | |
| 520 return false; | |
| 521 | |
| 522 return true; | |
| 523 } | |
| 524 | |
| 525 void BufferedResourceLoader::ReadInternal() { | |
| 526 // Seek to the first byte requested. | |
| 527 bool ret = buffer_->Seek(first_offset_); | |
| 528 DCHECK(ret); | |
| 529 | |
| 530 // Then do the read. | |
| 531 int read = static_cast<int>(buffer_->Read(read_buffer_, read_size_)); | |
| 532 offset_ += first_offset_ + read; | |
| 533 | |
| 534 // And report with what we have read. | |
| 535 DoneRead(read); | |
| 536 } | |
| 537 | |
| 538 bool BufferedResourceLoader::VerifyPartialResponse( | |
| 539 const WebURLResponse& response) { | |
| 540 int first_byte_position, last_byte_position, instance_size; | |
| 541 | |
| 542 if (!MultipartResponseDelegate::ReadContentRanges(response, | |
| 543 &first_byte_position, | |
| 544 &last_byte_position, | |
| 545 &instance_size)) { | |
| 546 return false; | |
| 547 } | |
| 548 | |
| 549 if (instance_size != kPositionNotSpecified) { | |
| 550 instance_size_ = instance_size; | |
| 551 } | |
| 552 | |
| 553 if (first_byte_position_ != kPositionNotSpecified && | |
| 554 first_byte_position_ != first_byte_position) { | |
| 555 return false; | |
| 556 } | |
| 557 | |
| 558 // TODO(hclam): I should also check |last_byte_position|, but since | |
| 559 // we will never make such a request that it is ok to leave it unimplemented. | |
| 560 return true; | |
| 561 } | |
| 562 | |
| 563 std::string BufferedResourceLoader::GenerateHeaders( | |
| 564 int64 first_byte_position, | |
| 565 int64 last_byte_position) { | |
| 566 // Construct the value for the range header. | |
| 567 std::string header; | |
| 568 if (first_byte_position > kPositionNotSpecified && | |
| 569 last_byte_position > kPositionNotSpecified) { | |
| 570 if (first_byte_position <= last_byte_position) { | |
| 571 header = base::StringPrintf("bytes=%" PRId64 "-%" PRId64, | |
| 572 first_byte_position, | |
| 573 last_byte_position); | |
| 574 } | |
| 575 } else if (first_byte_position > kPositionNotSpecified) { | |
| 576 header = base::StringPrintf("bytes=%" PRId64 "-", | |
| 577 first_byte_position); | |
| 578 } else if (last_byte_position > kPositionNotSpecified) { | |
| 579 NOTIMPLEMENTED() << "Suffix range not implemented"; | |
| 580 } | |
| 581 return header; | |
| 582 } | |
| 583 | |
| 584 void BufferedResourceLoader::DoneRead(int error) { | |
| 585 read_callback_->RunWithParams(Tuple1<int>(error)); | |
| 586 read_callback_.reset(); | |
| 587 read_position_ = 0; | |
| 588 read_size_ = 0; | |
| 589 read_buffer_ = NULL; | |
| 590 first_offset_ = 0; | |
| 591 last_offset_ = 0; | |
| 592 } | |
| 593 | |
| 594 void BufferedResourceLoader::DoneStart(int error) { | |
| 595 start_callback_->RunWithParams(Tuple1<int>(error)); | |
| 596 start_callback_.reset(); | |
| 597 } | |
| 598 | |
| 599 void BufferedResourceLoader::NotifyNetworkEvent() { | |
| 600 if (event_callback_.get()) | |
| 601 event_callback_->Run(); | |
| 602 } | |
| 603 | |
| 604 ///////////////////////////////////////////////////////////////////////////// | |
| 605 // BufferedDataSource | |
| 606 BufferedDataSource::BufferedDataSource( | 17 BufferedDataSource::BufferedDataSource( | 
| 607 MessageLoop* render_loop, | 18 MessageLoop* render_loop, | 
| 608 WebFrame* frame) | 19 WebFrame* frame) | 
| 609 : total_bytes_(kPositionNotSpecified), | 20 : total_bytes_(net::kPositionNotSpecified), | 
| 610 loaded_(false), | 21 loaded_(false), | 
| 611 streaming_(false), | 22 streaming_(false), | 
| 612 frame_(frame), | 23 frame_(frame), | 
| 613 single_origin_(true), | 24 single_origin_(true), | 
| 614 loader_(NULL), | 25 loader_(NULL), | 
| 615 network_activity_(false), | 26 network_activity_(false), | 
| 616 initialize_callback_(NULL), | 27 initialize_callback_(NULL), | 
| 617 read_callback_(NULL), | 28 read_callback_(NULL), | 
| 618 read_position_(0), | 29 read_position_(0), | 
| 619 read_size_(0), | 30 read_size_(0), | 
| 620 read_buffer_(NULL), | 31 read_buffer_(NULL), | 
| 621 read_attempts_(0), | 32 read_attempts_(0), | 
| 622 intermediate_read_buffer_(new uint8[kInitialReadBufferSize]), | 33 intermediate_read_buffer_(new uint8[net::kInitialReadBufferSize]), | 
| 623 intermediate_read_buffer_size_(kInitialReadBufferSize), | 34 intermediate_read_buffer_size_(net::kInitialReadBufferSize), | 
| 624 render_loop_(render_loop), | 35 render_loop_(render_loop), | 
| 625 stop_signal_received_(false), | 36 stop_signal_received_(false), | 
| 626 stopped_on_render_loop_(false), | 37 stopped_on_render_loop_(false), | 
| 627 media_is_paused_(true), | 38 media_is_paused_(true), | 
| 628 using_range_request_(true) { | 39 using_range_request_(true) { | 
| 629 } | 40 } | 
| 630 | 41 | 
| 631 BufferedDataSource::~BufferedDataSource() { | 42 BufferedDataSource::~BufferedDataSource() { | 
| 632 } | 43 } | 
| 633 | 44 | 
| 634 // A factory method to create BufferedResourceLoader using the read parameters. | 45 // A factory method to create BufferedResourceLoader using the read parameters. | 
| 635 // This method can be overrided to inject mock BufferedResourceLoader object | 46 // This method can be overrided to inject mock BufferedResourceLoader object | 
| 636 // for testing purpose. | 47 // for testing purpose. | 
| 637 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( | 48 BufferedResourceLoader* BufferedDataSource::CreateResourceLoader( | 
| 638 int64 first_byte_position, int64 last_byte_position) { | 49 int64 first_byte_position, int64 last_byte_position) { | 
| 639 DCHECK(MessageLoop::current() == render_loop_); | 50 DCHECK(MessageLoop::current() == render_loop_); | 
| 640 | 51 | 
| 641 return new BufferedResourceLoader(url_, | 52 return new BufferedResourceLoader(url_, | 
| 642 first_byte_position, | 53 first_byte_position, | 
| 643 last_byte_position); | 54 last_byte_position); | 
| 644 } | 55 } | 
| 645 | 56 | 
| 646 // This method simply returns kTimeoutMilliseconds. The purpose of this | 57 // This method simply returns kTimeoutMilliseconds. The purpose of this | 
| 647 // method is to be overidded so as to provide a different timeout value | 58 // method is to be overidded so as to provide a different timeout value | 
| 648 // for testing purpose. | 59 // for testing purpose. | 
| 649 base::TimeDelta BufferedDataSource::GetTimeoutMilliseconds() { | 60 base::TimeDelta BufferedDataSource::GetTimeoutMilliseconds() { | 
| 650 return base::TimeDelta::FromMilliseconds(kTimeoutMilliseconds); | 61 return base::TimeDelta::FromMilliseconds(net::kTimeoutMilliseconds); | 
| 651 } | 62 } | 
| 652 | 63 | 
| 653 ///////////////////////////////////////////////////////////////////////////// | 64 ///////////////////////////////////////////////////////////////////////////// | 
| 654 // BufferedDataSource, media::Filter implementation | 65 // BufferedDataSource, media::Filter implementation | 
| 655 void BufferedDataSource::Initialize(const std::string& url, | 66 void BufferedDataSource::Initialize(const std::string& url, | 
| 656 media::FilterCallback* callback) { | 67 media::FilterCallback* callback) { | 
| 657 // Saves the url. | 68 // Saves the url. | 
| 658 url_ = GURL(url); | 69 url_ = GURL(url); | 
| 659 | 70 | 
| 660 if (!IsProtocolSupportedForMedia(url_)) { | 71 if (!IsProtocolSupportedForMedia(url_)) { | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 675 | 86 | 
| 676 // Post a task to complete the initialization task. | 87 // Post a task to complete the initialization task. | 
| 677 render_loop_->PostTask(FROM_HERE, | 88 render_loop_->PostTask(FROM_HERE, | 
| 678 NewRunnableMethod(this, &BufferedDataSource::InitializeTask)); | 89 NewRunnableMethod(this, &BufferedDataSource::InitializeTask)); | 
| 679 } | 90 } | 
| 680 | 91 | 
| 681 bool BufferedDataSource::IsUrlSupported(const std::string& url) { | 92 bool BufferedDataSource::IsUrlSupported(const std::string& url) { | 
| 682 GURL gurl(url); | 93 GURL gurl(url); | 
| 683 | 94 | 
| 684 // This data source doesn't support data:// protocol so reject it. | 95 // This data source doesn't support data:// protocol so reject it. | 
| 685 return IsProtocolSupportedForMedia(gurl) && !IsDataProtocol(gurl); | 96 return IsProtocolSupportedForMedia(gurl) && !net::HttpUtil::IsDataProtocol(gur l); | 
| 
scherkus (not reviewing)
2010/12/14 18:48:19
>80 chars
 
annacc
2010/12/14 21:10:17
Done.
 | |
| 686 } | 97 } | 
| 687 | 98 | 
| 688 void BufferedDataSource::Stop(media::FilterCallback* callback) { | 99 void BufferedDataSource::Stop(media::FilterCallback* callback) { | 
| 689 { | 100 { | 
| 690 AutoLock auto_lock(lock_); | 101 AutoLock auto_lock(lock_); | 
| 691 stop_signal_received_ = true; | 102 stop_signal_received_ = true; | 
| 692 } | 103 } | 
| 693 if (callback) { | 104 if (callback) { | 
| 694 callback->Run(); | 105 callback->Run(); | 
| 695 delete callback; | 106 delete callback; | 
| (...skipping 12 matching lines...) Expand all Loading... | |
| 708 ///////////////////////////////////////////////////////////////////////////// | 119 ///////////////////////////////////////////////////////////////////////////// | 
| 709 // BufferedDataSource, media::DataSource implementation | 120 // BufferedDataSource, media::DataSource implementation | 
| 710 void BufferedDataSource::Read(int64 position, size_t size, uint8* data, | 121 void BufferedDataSource::Read(int64 position, size_t size, uint8* data, | 
| 711 media::DataSource::ReadCallback* read_callback) { | 122 media::DataSource::ReadCallback* read_callback) { | 
| 712 render_loop_->PostTask(FROM_HERE, | 123 render_loop_->PostTask(FROM_HERE, | 
| 713 NewRunnableMethod(this, &BufferedDataSource::ReadTask, | 124 NewRunnableMethod(this, &BufferedDataSource::ReadTask, | 
| 714 position, static_cast<int>(size), data, read_callback)); | 125 position, static_cast<int>(size), data, read_callback)); | 
| 715 } | 126 } | 
| 716 | 127 | 
| 717 bool BufferedDataSource::GetSize(int64* size_out) { | 128 bool BufferedDataSource::GetSize(int64* size_out) { | 
| 718 if (total_bytes_ != kPositionNotSpecified) { | 129 if (total_bytes_ != net::kPositionNotSpecified) { | 
| 719 *size_out = total_bytes_; | 130 *size_out = total_bytes_; | 
| 720 return true; | 131 return true; | 
| 721 } | 132 } | 
| 722 *size_out = 0; | 133 *size_out = 0; | 
| 723 return false; | 134 return false; | 
| 724 } | 135 } | 
| 725 | 136 | 
| 726 bool BufferedDataSource::IsStreaming() { | 137 bool BufferedDataSource::IsStreaming() { | 
| 727 return streaming_; | 138 return streaming_; | 
| 728 } | 139 } | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 755 return; | 166 return; | 
| 756 | 167 | 
| 757 // Kick starts the watch dog task that will handle connection timeout. | 168 // Kick starts the watch dog task that will handle connection timeout. | 
| 758 // We run the watch dog 2 times faster the actual timeout so as to catch | 169 // We run the watch dog 2 times faster the actual timeout so as to catch | 
| 759 // the timeout more accurately. | 170 // the timeout more accurately. | 
| 760 watch_dog_timer_.Start( | 171 watch_dog_timer_.Start( | 
| 761 GetTimeoutMilliseconds() / 2, | 172 GetTimeoutMilliseconds() / 2, | 
| 762 this, | 173 this, | 
| 763 &BufferedDataSource::WatchDogTask); | 174 &BufferedDataSource::WatchDogTask); | 
| 764 | 175 | 
| 765 if (IsHttpProtocol(url_)) { | 176 if (net::HttpUtil::IsHttpProtocol(url_)) { | 
| 766 // Fetch only first 1024 bytes as this usually covers the header portion | 177 // Fetch only first 1024 bytes as this usually covers the header portion | 
| 767 // of a media file that gives enough information about the codecs, etc. | 178 // of a media file that gives enough information about the codecs, etc. | 
| 768 // This also serve as a probe to determine server capability to serve | 179 // This also serve as a probe to determine server capability to serve | 
| 769 // range request. | 180 // range request. | 
| 770 // TODO(hclam): Do some experiments for the best approach. | 181 // TODO(hclam): Do some experiments for the best approach. | 
| 771 loader_ = CreateResourceLoader(0, 1024); | 182 loader_ = CreateResourceLoader(0, 1024); | 
| 772 loader_->Start( | 183 loader_->Start( | 
| 773 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback), | 184 NewCallback(this, &BufferedDataSource::HttpInitialStartCallback), | 
| 774 NewCallback(this, &BufferedDataSource::NetworkEventCallback), | 185 NewCallback(this, &BufferedDataSource::NetworkEventCallback), | 
| 775 frame_); | 186 frame_); | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 857 if (!read_callback_.get()) | 268 if (!read_callback_.get()) | 
| 858 return; | 269 return; | 
| 859 | 270 | 
| 860 DCHECK(loader_.get()); | 271 DCHECK(loader_.get()); | 
| 861 base::TimeDelta delta = base::Time::Now() - read_submitted_time_; | 272 base::TimeDelta delta = base::Time::Now() - read_submitted_time_; | 
| 862 if (delta < GetTimeoutMilliseconds()) | 273 if (delta < GetTimeoutMilliseconds()) | 
| 863 return; | 274 return; | 
| 864 | 275 | 
| 865 // TODO(hclam): Maybe raise an error here. But if an error is reported | 276 // TODO(hclam): Maybe raise an error here. But if an error is reported | 
| 866 // the whole pipeline may get destroyed... | 277 // the whole pipeline may get destroyed... | 
| 867 if (read_attempts_ >= kReadTrials) | 278 if (read_attempts_ >= net::kReadTrials) | 
| 868 return; | 279 return; | 
| 869 | 280 | 
| 870 ++read_attempts_; | 281 ++read_attempts_; | 
| 871 read_submitted_time_ = base::Time::Now(); | 282 read_submitted_time_ = base::Time::Now(); | 
| 872 | 283 | 
| 873 // Stops the current loader and creates a new resource loader and | 284 // Stops the current loader and creates a new resource loader and | 
| 874 // retry the request. | 285 // retry the request. | 
| 875 loader_->Stop(); | 286 loader_->Stop(); | 
| 876 loader_ = CreateResourceLoader(read_position_, -1); | 287 loader_ = CreateResourceLoader(read_position_, -1); | 
| 877 loader_->SetAllowDefer(!media_is_paused_); | 288 loader_->SetAllowDefer(!media_is_paused_); | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 956 | 367 | 
| 957 int64 instance_size = loader_->instance_size(); | 368 int64 instance_size = loader_->instance_size(); | 
| 958 bool partial_response = loader_->partial_response(); | 369 bool partial_response = loader_->partial_response(); | 
| 959 bool success = error == net::OK; | 370 bool success = error == net::OK; | 
| 960 | 371 | 
| 961 if (success) { | 372 if (success) { | 
| 962 // TODO(hclam): Needs more thinking about supporting servers without range | 373 // TODO(hclam): Needs more thinking about supporting servers without range | 
| 963 // request or their partial response is not complete. | 374 // request or their partial response is not complete. | 
| 964 total_bytes_ = instance_size; | 375 total_bytes_ = instance_size; | 
| 965 loaded_ = false; | 376 loaded_ = false; | 
| 966 streaming_ = (instance_size == kPositionNotSpecified) || !partial_response; | 377 streaming_ = (instance_size == net::kPositionNotSpecified) || !partial_respo nse; | 
| 
scherkus (not reviewing)
2010/12/14 18:48:19
>80 chars
 
annacc
2010/12/14 21:10:17
Done.
 | |
| 967 } else { | 378 } else { | 
| 968 // TODO(hclam): In case of failure, we can retry several times. | 379 // TODO(hclam): In case of failure, we can retry several times. | 
| 969 loader_->Stop(); | 380 loader_->Stop(); | 
| 970 } | 381 } | 
| 971 | 382 | 
| 972 if (error == net::ERR_INVALID_RESPONSE && using_range_request_) { | 383 if (error == net::ERR_INVALID_RESPONSE && using_range_request_) { | 
| 973 // Assuming that the Range header was causing the problem. Retry without | 384 // Assuming that the Range header was causing the problem. Retry without | 
| 974 // the Range header. | 385 // the Range header. | 
| 975 using_range_request_ = false; | 386 using_range_request_ = false; | 
| 976 loader_ = CreateResourceLoader(-1, -1); | 387 loader_ = CreateResourceLoader(-1, -1); | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 } | 427 } | 
| 1017 | 428 | 
| 1018 void BufferedDataSource::NonHttpInitialStartCallback(int error) { | 429 void BufferedDataSource::NonHttpInitialStartCallback(int error) { | 
| 1019 DCHECK(MessageLoop::current() == render_loop_); | 430 DCHECK(MessageLoop::current() == render_loop_); | 
| 1020 DCHECK(loader_.get()); | 431 DCHECK(loader_.get()); | 
| 1021 | 432 | 
| 1022 // Check if the request ended up at a different origin via redirect. | 433 // Check if the request ended up at a different origin via redirect. | 
| 1023 single_origin_ = url_.GetOrigin() == loader_->url().GetOrigin(); | 434 single_origin_ = url_.GetOrigin() == loader_->url().GetOrigin(); | 
| 1024 | 435 | 
| 1025 int64 instance_size = loader_->instance_size(); | 436 int64 instance_size = loader_->instance_size(); | 
| 1026 bool success = error == net::OK && instance_size != kPositionNotSpecified; | 437 bool success = error == net::OK && instance_size != net::kPositionNotSpecified ; | 
| 1027 | 438 | 
| 1028 if (success) { | 439 if (success) { | 
| 1029 total_bytes_ = instance_size; | 440 total_bytes_ = instance_size; | 
| 1030 loaded_ = true; | 441 loaded_ = true; | 
| 1031 } else { | 442 } else { | 
| 1032 loader_->Stop(); | 443 loader_->Stop(); | 
| 1033 } | 444 } | 
| 1034 | 445 | 
| 1035 // We need to prevent calling to filter host and running the callback if | 446 // We need to prevent calling to filter host and running the callback if | 
| 1036 // we have received the stop signal. We need to lock down the whole callback | 447 // we have received the stop signal. We need to lock down the whole callback | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1127 | 538 | 
| 1128 // In case of non-HTTP request we don't need to report network events, | 539 // In case of non-HTTP request we don't need to report network events, | 
| 1129 // so return immediately. | 540 // so return immediately. | 
| 1130 if (loaded_) | 541 if (loaded_) | 
| 1131 return; | 542 return; | 
| 1132 | 543 | 
| 1133 bool network_activity = loader_->network_activity(); | 544 bool network_activity = loader_->network_activity(); | 
| 1134 int64 buffered_last_byte_position = loader_->GetBufferedLastBytePosition(); | 545 int64 buffered_last_byte_position = loader_->GetBufferedLastBytePosition(); | 
| 1135 | 546 | 
| 1136 // If we get an unspecified value, return immediately. | 547 // If we get an unspecified value, return immediately. | 
| 1137 if (buffered_last_byte_position == kPositionNotSpecified) | 548 if (buffered_last_byte_position == net::kPositionNotSpecified) | 
| 1138 return; | 549 return; | 
| 1139 | 550 | 
| 1140 // We need to prevent calling to filter host and running the callback if | 551 // We need to prevent calling to filter host and running the callback if | 
| 1141 // we have received the stop signal. We need to lock down the whole callback | 552 // we have received the stop signal. We need to lock down the whole callback | 
| 1142 // method to prevent bad things from happening. The reason behind this is | 553 // method to prevent bad things from happening. The reason behind this is | 
| 1143 // that we cannot guarantee tasks on render thread have completely stopped | 554 // that we cannot guarantee tasks on render thread have completely stopped | 
| 1144 // when we receive the Stop() method call. So only way to solve this is to | 555 // when we receive the Stop() method call. So only way to solve this is to | 
| 1145 // let tasks on render thread to run but make sure they don't call outside | 556 // let tasks on render thread to run but make sure they don't call outside | 
| 1146 // this object when Stop() method is ever called. Locking this method is safe | 557 // this object when Stop() method is ever called. Locking this method is safe | 
| 1147 // because |lock_| is only acquired in tasks on render thread. | 558 // because |lock_| is only acquired in tasks on render thread. | 
| 1148 AutoLock auto_lock(lock_); | 559 AutoLock auto_lock(lock_); | 
| 1149 if (stop_signal_received_) | 560 if (stop_signal_received_) | 
| 1150 return; | 561 return; | 
| 1151 | 562 | 
| 1152 if (network_activity != network_activity_) { | 563 if (network_activity != network_activity_) { | 
| 1153 network_activity_ = network_activity; | 564 network_activity_ = network_activity; | 
| 1154 host()->SetNetworkActivity(network_activity); | 565 host()->SetNetworkActivity(network_activity); | 
| 1155 } | 566 } | 
| 1156 host()->SetBufferedBytes(buffered_last_byte_position + 1); | 567 host()->SetBufferedBytes(buffered_last_byte_position + 1); | 
| 1157 } | 568 } | 
| 1158 | 569 | 
| 1159 } // namespace webkit_glue | 570 } // namespace webkit_glue | 
| OLD | NEW |