| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/glue/webmediaplayer_impl.h" | 5 #include "webkit/glue/webmediaplayer_impl.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "media/filters/null_audio_renderer.h" | 24 #include "media/filters/null_audio_renderer.h" |
| 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" | 25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h" |
| 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" |
| 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" |
| 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h" | 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h" |
| 29 #include "webkit/glue/media/buffered_data_source.h" | 29 #include "webkit/glue/media/buffered_data_source.h" |
| 30 #include "webkit/glue/media/simple_data_source.h" | 30 #include "webkit/glue/media/simple_data_source.h" |
| 31 #include "webkit/glue/media/media_stream_client.h" | 31 #include "webkit/glue/media/media_stream_client.h" |
| 32 #include "webkit/glue/media/video_renderer_impl.h" | 32 #include "webkit/glue/media/video_renderer_impl.h" |
| 33 #include "webkit/glue/media/web_video_renderer.h" | 33 #include "webkit/glue/media/web_video_renderer.h" |
| 34 #include "webkit/glue/webmediaplayer_proxy.h" |
| 34 #include "webkit/glue/webvideoframe_impl.h" | 35 #include "webkit/glue/webvideoframe_impl.h" |
| 35 | 36 |
| 36 using WebKit::WebCanvas; | 37 using WebKit::WebCanvas; |
| 37 using WebKit::WebRect; | 38 using WebKit::WebRect; |
| 38 using WebKit::WebSize; | 39 using WebKit::WebSize; |
| 39 using media::PipelineStatus; | 40 using media::PipelineStatus; |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 | 43 |
| 43 // Limits the maximum outstanding repaints posted on render thread. | |
| 44 // This number of 50 is a guess, it does not take too much memory on the task | |
| 45 // queue but gives up a pretty good latency on repaint. | |
| 46 const int kMaxOutstandingRepaints = 50; | |
| 47 | |
| 48 // Limits the range of playback rate. | 44 // Limits the range of playback rate. |
| 49 // | 45 // |
| 50 // TODO(kylep): Revisit these. | 46 // TODO(kylep): Revisit these. |
| 51 // | 47 // |
| 52 // Vista has substantially lower performance than XP or Windows7. If you speed | 48 // Vista has substantially lower performance than XP or Windows7. If you speed |
| 53 // up a video too much, it can't keep up, and rendering stops updating except on | 49 // up a video too much, it can't keep up, and rendering stops updating except on |
| 54 // the time bar. For really high speeds, audio becomes a bottleneck and we just | 50 // the time bar. For really high speeds, audio becomes a bottleneck and we just |
| 55 // use up the data we have, which may not achieve the speed requested, but will | 51 // use up the data we have, which may not achieve the speed requested, but will |
| 56 // not crash the tab. | 52 // not crash the tab. |
| 57 // | 53 // |
| (...skipping 22 matching lines...) Expand all Loading... |
| 80 } | 76 } |
| 81 | 77 |
| 82 // Now we can safely cast to int64 microseconds. | 78 // Now we can safely cast to int64 microseconds. |
| 83 return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer)); | 79 return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer)); |
| 84 } | 80 } |
| 85 | 81 |
| 86 } // namespace | 82 } // namespace |
| 87 | 83 |
| 88 namespace webkit_glue { | 84 namespace webkit_glue { |
| 89 | 85 |
| 90 ///////////////////////////////////////////////////////////////////////////// | |
| 91 // WebMediaPlayerImpl::Proxy implementation | |
| 92 | |
| 93 WebMediaPlayerImpl::Proxy::Proxy(MessageLoop* render_loop, | |
| 94 WebMediaPlayerImpl* webmediaplayer) | |
| 95 : render_loop_(render_loop), | |
| 96 webmediaplayer_(webmediaplayer), | |
| 97 outstanding_repaints_(0) { | |
| 98 DCHECK(render_loop_); | |
| 99 DCHECK(webmediaplayer_); | |
| 100 } | |
| 101 | |
| 102 WebMediaPlayerImpl::Proxy::~Proxy() { | |
| 103 Detach(); | |
| 104 } | |
| 105 | |
| 106 void WebMediaPlayerImpl::Proxy::Repaint() { | |
| 107 base::AutoLock auto_lock(lock_); | |
| 108 if (outstanding_repaints_ < kMaxOutstandingRepaints) { | |
| 109 ++outstanding_repaints_; | |
| 110 | |
| 111 render_loop_->PostTask(FROM_HERE, | |
| 112 NewRunnableMethod(this, &WebMediaPlayerImpl::Proxy::RepaintTask)); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 void WebMediaPlayerImpl::Proxy::SetVideoRenderer( | |
| 117 scoped_refptr<WebVideoRenderer> video_renderer) { | |
| 118 video_renderer_ = video_renderer; | |
| 119 } | |
| 120 | |
| 121 WebDataSourceBuildObserverHack* WebMediaPlayerImpl::Proxy::GetBuildObserver() { | |
| 122 if (!build_observer_.get()) | |
| 123 build_observer_.reset(NewCallback(this, &Proxy::AddDataSource)); | |
| 124 return build_observer_.get(); | |
| 125 } | |
| 126 | |
| 127 void WebMediaPlayerImpl::Proxy::Paint(SkCanvas* canvas, | |
| 128 const gfx::Rect& dest_rect) { | |
| 129 DCHECK(MessageLoop::current() == render_loop_); | |
| 130 if (video_renderer_) { | |
| 131 video_renderer_->Paint(canvas, dest_rect); | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 void WebMediaPlayerImpl::Proxy::SetSize(const gfx::Rect& rect) { | |
| 136 DCHECK(MessageLoop::current() == render_loop_); | |
| 137 if (video_renderer_) { | |
| 138 video_renderer_->SetRect(rect); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 bool WebMediaPlayerImpl::Proxy::HasSingleOrigin() { | |
| 143 DCHECK(MessageLoop::current() == render_loop_); | |
| 144 | |
| 145 base::AutoLock auto_lock(data_sources_lock_); | |
| 146 | |
| 147 for (DataSourceList::iterator itr = data_sources_.begin(); | |
| 148 itr != data_sources_.end(); | |
| 149 itr++) { | |
| 150 if (!(*itr)->HasSingleOrigin()) | |
| 151 return false; | |
| 152 } | |
| 153 return true; | |
| 154 } | |
| 155 | |
| 156 void WebMediaPlayerImpl::Proxy::AbortDataSources() { | |
| 157 DCHECK(MessageLoop::current() == render_loop_); | |
| 158 base::AutoLock auto_lock(data_sources_lock_); | |
| 159 | |
| 160 for (DataSourceList::iterator itr = data_sources_.begin(); | |
| 161 itr != data_sources_.end(); | |
| 162 itr++) { | |
| 163 (*itr)->Abort(); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 void WebMediaPlayerImpl::Proxy::Detach() { | |
| 168 DCHECK(MessageLoop::current() == render_loop_); | |
| 169 webmediaplayer_ = NULL; | |
| 170 video_renderer_ = NULL; | |
| 171 | |
| 172 { | |
| 173 base::AutoLock auto_lock(data_sources_lock_); | |
| 174 data_sources_.clear(); | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 void WebMediaPlayerImpl::Proxy::PipelineInitializationCallback( | |
| 179 PipelineStatus status) { | |
| 180 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 181 this, &WebMediaPlayerImpl::Proxy::PipelineInitializationTask, status)); | |
| 182 } | |
| 183 | |
| 184 void WebMediaPlayerImpl::Proxy::PipelineSeekCallback(PipelineStatus status) { | |
| 185 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 186 this, &WebMediaPlayerImpl::Proxy::PipelineSeekTask, status)); | |
| 187 } | |
| 188 | |
| 189 void WebMediaPlayerImpl::Proxy::PipelineEndedCallback(PipelineStatus status) { | |
| 190 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 191 this, &WebMediaPlayerImpl::Proxy::PipelineEndedTask, status)); | |
| 192 } | |
| 193 | |
| 194 void WebMediaPlayerImpl::Proxy::PipelineErrorCallback(PipelineStatus error) { | |
| 195 DCHECK_NE(error, media::PIPELINE_OK); | |
| 196 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 197 this, &WebMediaPlayerImpl::Proxy::PipelineErrorTask, error)); | |
| 198 } | |
| 199 | |
| 200 void WebMediaPlayerImpl::Proxy::NetworkEventCallback(PipelineStatus status) { | |
| 201 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 202 this, &WebMediaPlayerImpl::Proxy::NetworkEventTask, status)); | |
| 203 } | |
| 204 | |
| 205 void WebMediaPlayerImpl::Proxy::AddDataSource(WebDataSource* data_source) { | |
| 206 base::AutoLock auto_lock(data_sources_lock_); | |
| 207 data_sources_.push_back(make_scoped_refptr(data_source)); | |
| 208 } | |
| 209 | |
| 210 void WebMediaPlayerImpl::Proxy::RepaintTask() { | |
| 211 DCHECK(MessageLoop::current() == render_loop_); | |
| 212 { | |
| 213 base::AutoLock auto_lock(lock_); | |
| 214 --outstanding_repaints_; | |
| 215 DCHECK_GE(outstanding_repaints_, 0); | |
| 216 } | |
| 217 if (webmediaplayer_) { | |
| 218 webmediaplayer_->Repaint(); | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 void WebMediaPlayerImpl::Proxy::PipelineInitializationTask( | |
| 223 PipelineStatus status) { | |
| 224 DCHECK(MessageLoop::current() == render_loop_); | |
| 225 if (webmediaplayer_) { | |
| 226 webmediaplayer_->OnPipelineInitialize(status); | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 void WebMediaPlayerImpl::Proxy::PipelineSeekTask(PipelineStatus status) { | |
| 231 DCHECK(MessageLoop::current() == render_loop_); | |
| 232 if (webmediaplayer_) { | |
| 233 webmediaplayer_->OnPipelineSeek(status); | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 void WebMediaPlayerImpl::Proxy::PipelineEndedTask(PipelineStatus status) { | |
| 238 DCHECK(MessageLoop::current() == render_loop_); | |
| 239 if (webmediaplayer_) { | |
| 240 webmediaplayer_->OnPipelineEnded(status); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void WebMediaPlayerImpl::Proxy::PipelineErrorTask(PipelineStatus error) { | |
| 245 DCHECK(MessageLoop::current() == render_loop_); | |
| 246 if (webmediaplayer_) { | |
| 247 webmediaplayer_->OnPipelineError(error); | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 void WebMediaPlayerImpl::Proxy::NetworkEventTask(PipelineStatus status) { | |
| 252 DCHECK(MessageLoop::current() == render_loop_); | |
| 253 if (webmediaplayer_) { | |
| 254 webmediaplayer_->OnNetworkEvent(status); | |
| 255 } | |
| 256 } | |
| 257 | |
| 258 void WebMediaPlayerImpl::Proxy::GetCurrentFrame( | |
| 259 scoped_refptr<media::VideoFrame>* frame_out) { | |
| 260 if (video_renderer_) | |
| 261 video_renderer_->GetCurrentFrame(frame_out); | |
| 262 } | |
| 263 | |
| 264 void WebMediaPlayerImpl::Proxy::PutCurrentFrame( | |
| 265 scoped_refptr<media::VideoFrame> frame) { | |
| 266 if (video_renderer_) | |
| 267 video_renderer_->PutCurrentFrame(frame); | |
| 268 } | |
| 269 | |
| 270 void WebMediaPlayerImpl::Proxy::DemuxerOpened(media::ChunkDemuxer* demuxer) { | |
| 271 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 272 this, &WebMediaPlayerImpl::Proxy::DemuxerOpenedTask, | |
| 273 scoped_refptr<media::ChunkDemuxer>(demuxer))); | |
| 274 } | |
| 275 | |
| 276 void WebMediaPlayerImpl::Proxy::DemuxerClosed() { | |
| 277 render_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 278 this, &WebMediaPlayerImpl::Proxy::DemuxerClosedTask)); | |
| 279 } | |
| 280 | |
| 281 void WebMediaPlayerImpl::Proxy::DemuxerFlush() { | |
| 282 if (chunk_demuxer_.get()) | |
| 283 chunk_demuxer_->FlushData(); | |
| 284 } | |
| 285 | |
| 286 bool WebMediaPlayerImpl::Proxy::DemuxerAppend(const uint8* data, | |
| 287 size_t length) { | |
| 288 if (chunk_demuxer_.get()) | |
| 289 return chunk_demuxer_->AppendData(data, length); | |
| 290 return false; | |
| 291 } | |
| 292 | |
| 293 void WebMediaPlayerImpl::Proxy::DemuxerEndOfStream( | |
| 294 media::PipelineStatus status) { | |
| 295 if (chunk_demuxer_.get()) | |
| 296 chunk_demuxer_->EndOfStream(status); | |
| 297 } | |
| 298 | |
| 299 void WebMediaPlayerImpl::Proxy::DemuxerShutdown() { | |
| 300 if (chunk_demuxer_.get()) | |
| 301 chunk_demuxer_->Shutdown(); | |
| 302 } | |
| 303 | |
| 304 void WebMediaPlayerImpl::Proxy::DemuxerOpenedTask( | |
| 305 const scoped_refptr<media::ChunkDemuxer>& demuxer) { | |
| 306 DCHECK(MessageLoop::current() == render_loop_); | |
| 307 chunk_demuxer_ = demuxer; | |
| 308 if (webmediaplayer_) | |
| 309 webmediaplayer_->OnDemuxerOpened(); | |
| 310 } | |
| 311 | |
| 312 void WebMediaPlayerImpl::Proxy::DemuxerClosedTask() { | |
| 313 chunk_demuxer_ = NULL; | |
| 314 } | |
| 315 | |
| 316 ///////////////////////////////////////////////////////////////////////////// | |
| 317 // WebMediaPlayerImpl implementation | |
| 318 | |
| 319 WebMediaPlayerImpl::WebMediaPlayerImpl( | 86 WebMediaPlayerImpl::WebMediaPlayerImpl( |
| 320 WebKit::WebMediaPlayerClient* client, | 87 WebKit::WebMediaPlayerClient* client, |
| 321 media::FilterCollection* collection, | 88 media::FilterCollection* collection, |
| 322 media::MessageLoopFactory* message_loop_factory, | 89 media::MessageLoopFactory* message_loop_factory, |
| 323 MediaStreamClient* media_stream_client, | 90 MediaStreamClient* media_stream_client, |
| 324 media::MediaLog* media_log) | 91 media::MediaLog* media_log) |
| 325 : network_state_(WebKit::WebMediaPlayer::Empty), | 92 : network_state_(WebKit::WebMediaPlayer::Empty), |
| 326 ready_state_(WebKit::WebMediaPlayer::HaveNothing), | 93 ready_state_(WebKit::WebMediaPlayer::HaveNothing), |
| 327 main_loop_(NULL), | 94 main_loop_(NULL), |
| 328 filter_collection_(collection), | 95 filter_collection_(collection), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 351 NOTREACHED() << "Could not start PipelineThread"; | 118 NOTREACHED() << "Could not start PipelineThread"; |
| 352 return false; | 119 return false; |
| 353 } | 120 } |
| 354 | 121 |
| 355 pipeline_ = new media::PipelineImpl(pipeline_message_loop); | 122 pipeline_ = new media::PipelineImpl(pipeline_message_loop); |
| 356 | 123 |
| 357 // Also we want to be notified of |main_loop_| destruction. | 124 // Also we want to be notified of |main_loop_| destruction. |
| 358 main_loop_->AddDestructionObserver(this); | 125 main_loop_->AddDestructionObserver(this); |
| 359 | 126 |
| 360 // Creates the proxy. | 127 // Creates the proxy. |
| 361 proxy_ = new Proxy(main_loop_, this); | 128 proxy_ = new WebMediaPlayerProxy(main_loop_, this); |
| 362 web_video_renderer->SetWebMediaPlayerImplProxy(proxy_); | 129 web_video_renderer->SetWebMediaPlayerProxy(proxy_); |
| 363 proxy_->SetVideoRenderer(web_video_renderer); | 130 proxy_->SetVideoRenderer(web_video_renderer); |
| 364 | 131 |
| 365 // Set our pipeline callbacks. | 132 // Set our pipeline callbacks. |
| 366 pipeline_->Init( | 133 pipeline_->Init( |
| 367 NewCallback(proxy_.get(), | 134 NewCallback(proxy_.get(), |
| 368 &WebMediaPlayerImpl::Proxy::PipelineEndedCallback), | 135 &WebMediaPlayerProxy::PipelineEndedCallback), |
| 369 NewCallback(proxy_.get(), | 136 NewCallback(proxy_.get(), |
| 370 &WebMediaPlayerImpl::Proxy::PipelineErrorCallback), | 137 &WebMediaPlayerProxy::PipelineErrorCallback), |
| 371 NewCallback(proxy_.get(), | 138 NewCallback(proxy_.get(), |
| 372 &WebMediaPlayerImpl::Proxy::NetworkEventCallback)); | 139 &WebMediaPlayerProxy::NetworkEventCallback)); |
| 373 | 140 |
| 374 // A simple data source that keeps all data in memory. | 141 // A simple data source that keeps all data in memory. |
| 375 scoped_ptr<media::DataSourceFactory> simple_data_source_factory( | 142 scoped_ptr<media::DataSourceFactory> simple_data_source_factory( |
| 376 SimpleDataSource::CreateFactory(MessageLoop::current(), frame, | 143 SimpleDataSource::CreateFactory(MessageLoop::current(), frame, |
| 377 proxy_->GetBuildObserver())); | 144 proxy_->GetBuildObserver())); |
| 378 | 145 |
| 379 // A sophisticated data source that does memory caching. | 146 // A sophisticated data source that does memory caching. |
| 380 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory( | 147 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory( |
| 381 BufferedDataSource::CreateFactory(MessageLoop::current(), frame, | 148 BufferedDataSource::CreateFactory(MessageLoop::current(), frame, |
| 382 proxy_->GetBuildObserver())); | 149 proxy_->GetBuildObserver())); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 // Get the preload value. | 222 // Get the preload value. |
| 456 setPreload(GetClient()->preload()); | 223 setPreload(GetClient()->preload()); |
| 457 | 224 |
| 458 // Initialize the pipeline. | 225 // Initialize the pipeline. |
| 459 SetNetworkState(WebKit::WebMediaPlayer::Loading); | 226 SetNetworkState(WebKit::WebMediaPlayer::Loading); |
| 460 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); | 227 SetReadyState(WebKit::WebMediaPlayer::HaveNothing); |
| 461 pipeline_->Start( | 228 pipeline_->Start( |
| 462 filter_collection_.release(), | 229 filter_collection_.release(), |
| 463 url.spec(), | 230 url.spec(), |
| 464 NewCallback(proxy_.get(), | 231 NewCallback(proxy_.get(), |
| 465 &WebMediaPlayerImpl::Proxy::PipelineInitializationCallback)); | 232 &WebMediaPlayerProxy::PipelineInitializationCallback)); |
| 466 | |
| 467 media_log_->Load(url.spec()); | 233 media_log_->Load(url.spec()); |
| 468 } | 234 } |
| 469 | 235 |
| 470 void WebMediaPlayerImpl::cancelLoad() { | 236 void WebMediaPlayerImpl::cancelLoad() { |
| 471 DCHECK(MessageLoop::current() == main_loop_); | 237 DCHECK(MessageLoop::current() == main_loop_); |
| 472 } | 238 } |
| 473 | 239 |
| 474 void WebMediaPlayerImpl::play() { | 240 void WebMediaPlayerImpl::play() { |
| 475 DCHECK(MessageLoop::current() == main_loop_); | 241 DCHECK(MessageLoop::current() == main_loop_); |
| 476 | 242 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 } | 289 } |
| 524 | 290 |
| 525 seeking_ = true; | 291 seeking_ = true; |
| 526 | 292 |
| 527 proxy_->DemuxerFlush(); | 293 proxy_->DemuxerFlush(); |
| 528 | 294 |
| 529 // Kick off the asynchronous seek! | 295 // Kick off the asynchronous seek! |
| 530 pipeline_->Seek( | 296 pipeline_->Seek( |
| 531 seek_time, | 297 seek_time, |
| 532 NewCallback(proxy_.get(), | 298 NewCallback(proxy_.get(), |
| 533 &WebMediaPlayerImpl::Proxy::PipelineSeekCallback)); | 299 &WebMediaPlayerProxy::PipelineSeekCallback)); |
| 534 } | 300 } |
| 535 | 301 |
| 536 void WebMediaPlayerImpl::setEndTime(float seconds) { | 302 void WebMediaPlayerImpl::setEndTime(float seconds) { |
| 537 DCHECK(MessageLoop::current() == main_loop_); | 303 DCHECK(MessageLoop::current() == main_loop_); |
| 538 | 304 |
| 539 // TODO(hclam): add method call when it has been implemented. | 305 // TODO(hclam): add method call when it has been implemented. |
| 540 return; | 306 return; |
| 541 } | 307 } |
| 542 | 308 |
| 543 void WebMediaPlayerImpl::setRate(float rate) { | 309 void WebMediaPlayerImpl::setRate(float rate) { |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1043 } | 809 } |
| 1044 } | 810 } |
| 1045 | 811 |
| 1046 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { | 812 WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() { |
| 1047 DCHECK(MessageLoop::current() == main_loop_); | 813 DCHECK(MessageLoop::current() == main_loop_); |
| 1048 DCHECK(client_); | 814 DCHECK(client_); |
| 1049 return client_; | 815 return client_; |
| 1050 } | 816 } |
| 1051 | 817 |
| 1052 } // namespace webkit_glue | 818 } // namespace webkit_glue |
| OLD | NEW |