OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "webkit/media/buffered_data_source.h" | 5 #include "webkit/media/buffered_data_source.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" |
8 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
9 #include "media/base/media_log.h" | 10 #include "media/base/media_log.h" |
10 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
11 | 12 |
12 using WebKit::WebFrame; | 13 using WebKit::WebFrame; |
13 | 14 |
14 namespace { | 15 namespace { |
15 | 16 |
16 // BufferedDataSource has an intermediate buffer, this value governs the initial | 17 // BufferedDataSource has an intermediate buffer, this value governs the initial |
17 // size of that buffer. It is set to 32KB because this is a typical read size | 18 // size of that buffer. It is set to 32KB because this is a typical read size |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 | 83 |
83 if (loader_.get()) { | 84 if (loader_.get()) { |
84 base::AutoLock auto_lock(lock_); | 85 base::AutoLock auto_lock(lock_); |
85 UpdateHostState_Locked(); | 86 UpdateHostState_Locked(); |
86 } | 87 } |
87 } | 88 } |
88 | 89 |
89 void BufferedDataSource::Initialize( | 90 void BufferedDataSource::Initialize( |
90 const GURL& url, | 91 const GURL& url, |
91 BufferedResourceLoader::CORSMode cors_mode, | 92 BufferedResourceLoader::CORSMode cors_mode, |
92 const media::PipelineStatusCB& initialize_cb) { | 93 const InitializeCB& init_cb) { |
93 DCHECK(MessageLoop::current() == render_loop_); | 94 DCHECK(MessageLoop::current() == render_loop_); |
94 DCHECK(!initialize_cb.is_null()); | 95 DCHECK(!init_cb.is_null()); |
95 DCHECK(!loader_.get()); | 96 DCHECK(!loader_.get()); |
96 url_ = url; | 97 url_ = url; |
97 cors_mode_ = cors_mode; | 98 cors_mode_ = cors_mode; |
98 | 99 |
99 initialize_cb_ = initialize_cb; | 100 init_cb_ = init_cb; |
100 | 101 |
101 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { | 102 if (url_.SchemeIs(kHttpScheme) || url_.SchemeIs(kHttpsScheme)) { |
102 // Do an unbounded range request starting at the beginning. If the server | 103 // Do an unbounded range request starting at the beginning. If the server |
103 // responds with 200 instead of 206 we'll fall back into a streaming mode. | 104 // responds with 200 instead of 206 we'll fall back into a streaming mode. |
104 loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); | 105 loader_.reset(CreateResourceLoader(0, kPositionNotSpecified)); |
105 } else { | 106 } else { |
106 // For all other protocols, assume they support range request. We fetch | 107 // For all other protocols, assume they support range request. We fetch |
107 // the full range of the resource to obtain the instance size because | 108 // the full range of the resource to obtain the instance size because |
108 // we won't be served HTTP headers. | 109 // we won't be served HTTP headers. |
109 loader_.reset(CreateResourceLoader(kPositionNotSpecified, | 110 loader_.reset(CreateResourceLoader(kPositionNotSpecified, |
110 kPositionNotSpecified)); | 111 kPositionNotSpecified)); |
111 assume_fully_buffered_ = true; | 112 assume_fully_buffered_ = true; |
112 } | 113 } |
113 | 114 |
114 loader_->Start( | 115 loader_->Start( |
115 base::Bind(&BufferedDataSource::StartCallback, this), | 116 base::Bind(&BufferedDataSource::StartCallback, this), |
116 base::Bind(&BufferedDataSource::LoadingStateChangedCallback, this), | 117 base::Bind(&BufferedDataSource::LoadingStateChangedCallback, this), |
117 base::Bind(&BufferedDataSource::ProgressCallback, this), | 118 base::Bind(&BufferedDataSource::ProgressCallback, this), |
118 frame_); | 119 frame_); |
119 } | 120 } |
120 | 121 |
121 void BufferedDataSource::SetPreload(Preload preload) { | 122 void BufferedDataSource::SetPreload(Preload preload) { |
122 DCHECK(MessageLoop::current() == render_loop_); | 123 DCHECK(MessageLoop::current() == render_loop_); |
123 preload_ = preload; | 124 preload_ = preload; |
124 } | 125 } |
125 | 126 |
126 bool BufferedDataSource::HasSingleOrigin() { | 127 bool BufferedDataSource::HasSingleOrigin() { |
127 DCHECK(MessageLoop::current() == render_loop_); | 128 DCHECK(MessageLoop::current() == render_loop_); |
128 DCHECK(initialize_cb_.is_null() && loader_.get()) | 129 DCHECK(init_cb_.is_null() && loader_.get()) |
129 << "Initialize() must complete before calling HasSingleOrigin()"; | 130 << "Initialize() must complete before calling HasSingleOrigin()"; |
130 return loader_->HasSingleOrigin(); | 131 return loader_->HasSingleOrigin(); |
131 } | 132 } |
132 | 133 |
133 bool BufferedDataSource::DidPassCORSAccessCheck() const { | 134 bool BufferedDataSource::DidPassCORSAccessCheck() const { |
134 return loader_.get() && loader_->DidPassCORSAccessCheck(); | 135 return loader_.get() && loader_->DidPassCORSAccessCheck(); |
135 } | 136 } |
136 | 137 |
137 void BufferedDataSource::Abort() { | 138 void BufferedDataSource::Abort() { |
138 DCHECK(MessageLoop::current() == render_loop_); | 139 DCHECK(MessageLoop::current() == render_loop_); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 | 226 |
226 // Call to read internal to perform the actual read. | 227 // Call to read internal to perform the actual read. |
227 ReadInternal(); | 228 ReadInternal(); |
228 } | 229 } |
229 | 230 |
230 void BufferedDataSource::CleanupTask() { | 231 void BufferedDataSource::CleanupTask() { |
231 DCHECK(MessageLoop::current() == render_loop_); | 232 DCHECK(MessageLoop::current() == render_loop_); |
232 | 233 |
233 { | 234 { |
234 base::AutoLock auto_lock(lock_); | 235 base::AutoLock auto_lock(lock_); |
235 initialize_cb_.Reset(); | 236 init_cb_.Reset(); |
236 if (stopped_on_render_loop_) | 237 if (stopped_on_render_loop_) |
237 return; | 238 return; |
238 | 239 |
239 // Signal that stop task has finished execution. | 240 // Signal that stop task has finished execution. |
240 // NOTE: it's vital that this be set under lock, as that's how Read() tests | 241 // NOTE: it's vital that this be set under lock, as that's how Read() tests |
241 // before registering a new |read_cb_| (which is cleared below). | 242 // before registering a new |read_cb_| (which is cleared below). |
242 stopped_on_render_loop_ = true; | 243 stopped_on_render_loop_ = true; |
243 | 244 |
244 if (!read_cb_.is_null()) | 245 if (!read_cb_.is_null()) |
245 DoneRead_Locked(kReadError); | 246 DoneRead_Locked(kReadError); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 DCHECK(!read_cb_.is_null()); | 316 DCHECK(!read_cb_.is_null()); |
316 DCHECK(bytes_read >= 0 || bytes_read == kReadError); | 317 DCHECK(bytes_read >= 0 || bytes_read == kReadError); |
317 lock_.AssertAcquired(); | 318 lock_.AssertAcquired(); |
318 | 319 |
319 read_cb_.Run(bytes_read); | 320 read_cb_.Run(bytes_read); |
320 read_cb_.Reset(); | 321 read_cb_.Reset(); |
321 read_size_ = 0; | 322 read_size_ = 0; |
322 read_buffer_ = 0; | 323 read_buffer_ = 0; |
323 } | 324 } |
324 | 325 |
325 void BufferedDataSource::DoneInitialization_Locked( | |
326 media::PipelineStatus status) { | |
327 DCHECK(MessageLoop::current() == render_loop_); | |
328 DCHECK(!initialize_cb_.is_null()); | |
329 lock_.AssertAcquired(); | |
330 | |
331 initialize_cb_.Run(status); | |
332 initialize_cb_.Reset(); | |
333 } | |
334 | |
335 ///////////////////////////////////////////////////////////////////////////// | 326 ///////////////////////////////////////////////////////////////////////////// |
336 // BufferedResourceLoader callback methods. | 327 // BufferedResourceLoader callback methods. |
337 void BufferedDataSource::StartCallback( | 328 void BufferedDataSource::StartCallback( |
338 BufferedResourceLoader::Status status) { | 329 BufferedResourceLoader::Status status) { |
339 DCHECK(MessageLoop::current() == render_loop_); | 330 DCHECK(MessageLoop::current() == render_loop_); |
340 DCHECK(loader_.get()); | 331 DCHECK(loader_.get()); |
341 | 332 |
342 bool initialize_cb_is_null = false; | 333 bool init_cb_is_null = false; |
343 { | 334 { |
344 base::AutoLock auto_lock(lock_); | 335 base::AutoLock auto_lock(lock_); |
345 initialize_cb_is_null = initialize_cb_.is_null(); | 336 init_cb_is_null = init_cb_.is_null(); |
346 } | 337 } |
347 if (initialize_cb_is_null) { | 338 if (init_cb_is_null) { |
348 loader_->Stop(); | 339 loader_->Stop(); |
349 return; | 340 return; |
350 } | 341 } |
351 | 342 |
352 // All responses must be successful. Resources that are assumed to be fully | 343 // All responses must be successful. Resources that are assumed to be fully |
353 // buffered must have a known content length. | 344 // buffered must have a known content length. |
354 bool success = status == BufferedResourceLoader::kOk && | 345 bool success = status == BufferedResourceLoader::kOk && |
355 (!assume_fully_buffered_ || | 346 (!assume_fully_buffered_ || |
356 loader_->instance_size() != kPositionNotSpecified); | 347 loader_->instance_size() != kPositionNotSpecified); |
357 | 348 |
358 if (success) { | 349 if (success) { |
359 total_bytes_ = loader_->instance_size(); | 350 total_bytes_ = loader_->instance_size(); |
360 streaming_ = !assume_fully_buffered_ && | 351 streaming_ = !assume_fully_buffered_ && |
361 (total_bytes_ == kPositionNotSpecified || !loader_->range_supported()); | 352 (total_bytes_ == kPositionNotSpecified || !loader_->range_supported()); |
362 } else { | 353 } else { |
363 loader_->Stop(); | 354 loader_->Stop(); |
364 } | 355 } |
365 | 356 |
366 // TODO(scherkus): we shouldn't have to lock to signal host(), see | 357 // TODO(scherkus): we shouldn't have to lock to signal host(), see |
367 // http://crbug.com/113712 for details. | 358 // http://crbug.com/113712 for details. |
368 scoped_refptr<BufferedDataSource> destruction_guard(this); | 359 scoped_refptr<BufferedDataSource> destruction_guard(this); |
369 { | 360 { |
370 base::AutoLock auto_lock(lock_); | 361 base::AutoLock auto_lock(lock_); |
371 if (stop_signal_received_) | 362 if (stop_signal_received_) |
372 return; | 363 return; |
373 | 364 |
374 if (!success) { | 365 if (success) |
375 DoneInitialization_Locked(media::PIPELINE_ERROR_NETWORK); | 366 UpdateHostState_Locked(); |
376 return; | |
377 } | |
378 | 367 |
379 UpdateHostState_Locked(); | 368 base::ResetAndReturn(&init_cb_).Run(success); |
380 DoneInitialization_Locked(media::PIPELINE_OK); | |
381 } | 369 } |
382 } | 370 } |
383 | 371 |
384 void BufferedDataSource::PartialReadStartCallback( | 372 void BufferedDataSource::PartialReadStartCallback( |
385 BufferedResourceLoader::Status status) { | 373 BufferedResourceLoader::Status status) { |
386 DCHECK(MessageLoop::current() == render_loop_); | 374 DCHECK(MessageLoop::current() == render_loop_); |
387 DCHECK(loader_.get()); | 375 DCHECK(loader_.get()); |
388 | 376 |
389 if (status == BufferedResourceLoader::kOk) { | 377 if (status == BufferedResourceLoader::kOk) { |
390 // Once the request has started successfully, we can proceed with | 378 // Once the request has started successfully, we can proceed with |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 if (total_bytes_ == kPositionNotSpecified) | 499 if (total_bytes_ == kPositionNotSpecified) |
512 return; | 500 return; |
513 | 501 |
514 host()->SetTotalBytes(total_bytes_); | 502 host()->SetTotalBytes(total_bytes_); |
515 | 503 |
516 if (assume_fully_buffered_) | 504 if (assume_fully_buffered_) |
517 host()->AddBufferedByteRange(0, total_bytes_); | 505 host()->AddBufferedByteRange(0, total_bytes_); |
518 } | 506 } |
519 | 507 |
520 } // namespace webkit_media | 508 } // namespace webkit_media |
OLD | NEW |