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