Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: content/renderer/media/android/webmediaplayer_android.cc

Issue 136343002: Remove Chrome for TV code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added the crbug. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/android/webmediaplayer_android.h" 5 #include "content/renderer/media/android/webmediaplayer_android.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 22 matching lines...) Expand all
33 #include "third_party/WebKit/public/web/WebDocument.h" 33 #include "third_party/WebKit/public/web/WebDocument.h"
34 #include "third_party/WebKit/public/web/WebFrame.h" 34 #include "third_party/WebKit/public/web/WebFrame.h"
35 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" 35 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
36 #include "third_party/WebKit/public/web/WebView.h" 36 #include "third_party/WebKit/public/web/WebView.h"
37 #include "third_party/skia/include/core/SkBitmap.h" 37 #include "third_party/skia/include/core/SkBitmap.h"
38 #include "third_party/skia/include/core/SkCanvas.h" 38 #include "third_party/skia/include/core/SkCanvas.h"
39 #include "third_party/skia/include/core/SkPaint.h" 39 #include "third_party/skia/include/core/SkPaint.h"
40 #include "ui/gfx/image/image.h" 40 #include "ui/gfx/image/image.h"
41 #include "webkit/renderer/compositor_bindings/web_layer_impl.h" 41 #include "webkit/renderer/compositor_bindings/web_layer_impl.h"
42 42
43 #if defined(GOOGLE_TV)
44 #include "content/renderer/media/media_stream_audio_renderer.h"
45 #include "content/renderer/media/media_stream_client.h"
46 #endif
47
48 static const uint32 kGLTextureExternalOES = 0x8D65; 43 static const uint32 kGLTextureExternalOES = 0x8D65;
49 44
50 using blink::WebMediaPlayer; 45 using blink::WebMediaPlayer;
51 using blink::WebSize; 46 using blink::WebSize;
52 using blink::WebString; 47 using blink::WebString;
53 using blink::WebTimeRanges; 48 using blink::WebTimeRanges;
54 using blink::WebURL; 49 using blink::WebURL;
55 using media::MediaPlayerAndroid; 50 using media::MediaPlayerAndroid;
56 using media::VideoFrame; 51 using media::VideoFrame;
57 52
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 is_playing_(false), 97 is_playing_(false),
103 playing_started_(false), 98 playing_started_(false),
104 needs_establish_peer_(true), 99 needs_establish_peer_(true),
105 stream_texture_proxy_initialized_(false), 100 stream_texture_proxy_initialized_(false),
106 has_size_info_(false), 101 has_size_info_(false),
107 has_media_metadata_(false), 102 has_media_metadata_(false),
108 has_media_info_(false), 103 has_media_info_(false),
109 stream_texture_factory_(factory), 104 stream_texture_factory_(factory),
110 needs_external_surface_(false), 105 needs_external_surface_(false),
111 video_frame_provider_client_(NULL), 106 video_frame_provider_client_(NULL),
112 #if defined(GOOGLE_TV)
113 external_surface_threshold_(-1),
114 demuxer_(NULL),
115 media_stream_client_(NULL),
116 #endif // defined(GOOGLE_TV)
117 pending_playback_(false), 107 pending_playback_(false),
118 player_type_(MEDIA_PLAYER_TYPE_URL), 108 player_type_(MEDIA_PLAYER_TYPE_URL),
119 current_time_(0), 109 current_time_(0),
120 is_remote_(false), 110 is_remote_(false),
121 media_log_(media_log), 111 media_log_(media_log),
122 weak_factory_(this) { 112 weak_factory_(this) {
123 DCHECK(manager_); 113 DCHECK(manager_);
124 114
125 DCHECK(main_thread_checker_.CalledOnValidThread()); 115 DCHECK(main_thread_checker_.CalledOnValidThread());
126 116
127 // We want to be notified of |main_loop_| destruction. 117 // We want to be notified of |main_loop_| destruction.
128 base::MessageLoop::current()->AddDestructionObserver(this); 118 base::MessageLoop::current()->AddDestructionObserver(this);
129 119
130 player_id_ = manager_->RegisterMediaPlayer(this); 120 player_id_ = manager_->RegisterMediaPlayer(this);
131 121
132 #if defined(GOOGLE_TV)
133 if (CommandLine::ForCurrentProcess()->HasSwitch(
134 switches::kUseExternalVideoSurfaceThresholdInPixels)) {
135 if (!base::StringToInt(
136 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
137 switches::kUseExternalVideoSurfaceThresholdInPixels),
138 &external_surface_threshold_)) {
139 external_surface_threshold_ = -1;
140 }
141 }
142 #endif // defined(GOOGLE_TV)
143
144 #if defined(VIDEO_HOLE) 122 #if defined(VIDEO_HOLE)
145 // Defer stream texture creation until we are sure it's necessary. 123 // Defer stream texture creation until we are sure it's necessary.
146 needs_establish_peer_ = false; 124 needs_establish_peer_ = false;
147 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); 125 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1));
148 #endif // defined(VIDEO_HOLE) 126 #endif // defined(VIDEO_HOLE)
149 TryCreateStreamTextureProxyIfNeeded(); 127 TryCreateStreamTextureProxyIfNeeded();
150 128
151 if (blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) { 129 if (blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) {
152 // TODO(xhwang): Report an error when there is encrypted stream but EME is 130 // TODO(xhwang): Report an error when there is encrypted stream but EME is
153 // not enabled. Currently the player just doesn't start and waits for ever. 131 // not enabled. Currently the player just doesn't start and waits for ever.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 stream_texture_factory_->Context3d(); 163 stream_texture_factory_->Context3d();
186 if (context->makeContextCurrent()) 164 if (context->makeContextCurrent())
187 context->deleteTexture(remote_playback_texture_id_); 165 context->deleteTexture(remote_playback_texture_id_);
188 } 166 }
189 167
190 if (base::MessageLoop::current()) 168 if (base::MessageLoop::current())
191 base::MessageLoop::current()->RemoveDestructionObserver(this); 169 base::MessageLoop::current()->RemoveDestructionObserver(this);
192 170
193 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_) 171 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_)
194 delegate_->PlayerGone(this); 172 delegate_->PlayerGone(this);
195
196 #if defined(GOOGLE_TV)
197 if (audio_renderer_) {
198 if (audio_renderer_->IsLocalRenderer()) {
199 audio_renderer_->Stop();
200 } else if (!paused()) {
201 // The |audio_renderer_| can be shared by multiple remote streams, and
202 // it will be stopped when WebRtcAudioDeviceImpl goes away. So we simply
203 // pause the |audio_renderer_| here to avoid re-creating the
204 // |audio_renderer_|.
205 audio_renderer_->Pause();
206 }
207 }
208 if (demuxer_ && !destroy_demuxer_cb_.is_null()) {
209 media_source_delegate_.reset();
210 destroy_demuxer_cb_.Run();
211 }
212 #endif
213 } 173 }
214 174
215 void WebMediaPlayerAndroid::load(LoadType load_type, 175 void WebMediaPlayerAndroid::load(LoadType load_type,
216 const blink::WebURL& url, 176 const blink::WebURL& url,
217 CORSMode cors_mode) { 177 CORSMode cors_mode) {
218 switch (load_type) { 178 switch (load_type) {
219 case LoadTypeURL: 179 case LoadTypeURL:
220 player_type_ = MEDIA_PLAYER_TYPE_URL; 180 player_type_ = MEDIA_PLAYER_TYPE_URL;
221 break; 181 break;
222 182
223 case LoadTypeMediaSource: 183 case LoadTypeMediaSource:
224 player_type_ = MEDIA_PLAYER_TYPE_MEDIA_SOURCE; 184 player_type_ = MEDIA_PLAYER_TYPE_MEDIA_SOURCE;
225 break; 185 break;
226 186
227 case LoadTypeMediaStream: 187 case LoadTypeMediaStream:
228 #if defined(GOOGLE_TV)
229 player_type_ = MEDIA_PLAYER_TYPE_MEDIA_STREAM;
230 break;
231 #else
232 CHECK(false) << "WebMediaPlayerAndroid doesn't support MediaStream on " 188 CHECK(false) << "WebMediaPlayerAndroid doesn't support MediaStream on "
233 "this platform"; 189 "this platform";
234 return; 190 return;
235 #endif
236 } 191 }
237 192
238 has_media_metadata_ = false; 193 has_media_metadata_ = false;
239 has_media_info_ = false; 194 has_media_info_ = false;
240 195
241 media::SetDecryptorReadyCB set_decryptor_ready_cb; 196 media::SetDecryptorReadyCB set_decryptor_ready_cb;
242 if (decryptor_) { // |decryptor_| can be NULL is EME if not enabled. 197 if (decryptor_) { // |decryptor_| can be NULL is EME if not enabled.
243 set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB, 198 set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB,
244 base::Unretained(decryptor_.get())); 199 base::Unretained(decryptor_.get()));
245 } 200 }
(...skipping 14 matching lines...) Expand all
260 media_source_delegate_->InitializeMediaSource( 215 media_source_delegate_->InitializeMediaSource(
261 base::Bind(&WebMediaPlayerAndroid::OnMediaSourceOpened, 216 base::Bind(&WebMediaPlayerAndroid::OnMediaSourceOpened,
262 weak_factory_.GetWeakPtr()), 217 weak_factory_.GetWeakPtr()),
263 base::Bind(&WebMediaPlayerAndroid::OnNeedKey, base::Unretained(this)), 218 base::Bind(&WebMediaPlayerAndroid::OnNeedKey, base::Unretained(this)),
264 set_decryptor_ready_cb, 219 set_decryptor_ready_cb,
265 base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState, 220 base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,
266 weak_factory_.GetWeakPtr()), 221 weak_factory_.GetWeakPtr()),
267 base::Bind(&WebMediaPlayerAndroid::OnDurationChanged, 222 base::Bind(&WebMediaPlayerAndroid::OnDurationChanged,
268 weak_factory_.GetWeakPtr())); 223 weak_factory_.GetWeakPtr()));
269 } 224 }
270 #if defined(GOOGLE_TV)
271 // TODO(xhwang): Pass set_decryptor_ready_cb in InitializeMediaStream() to
272 // enable ClearKey support for Google TV.
273 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_STREAM) {
274 media_source_delegate_->InitializeMediaStream(
275 demuxer_,
276 base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,
277 weak_factory_.GetWeakPtr()));
278 audio_renderer_ = media_stream_client_->GetAudioRenderer(url);
279 if (audio_renderer_)
280 audio_renderer_->Start();
281 }
282 #endif
283 } else { 225 } else {
284 info_loader_.reset( 226 info_loader_.reset(
285 new MediaInfoLoader( 227 new MediaInfoLoader(
286 url, 228 url,
287 cors_mode, 229 cors_mode,
288 base::Bind(&WebMediaPlayerAndroid::DidLoadMediaInfo, 230 base::Bind(&WebMediaPlayerAndroid::DidLoadMediaInfo,
289 base::Unretained(this)))); 231 base::Unretained(this))));
290 info_loader_->Start(frame_); 232 info_loader_->Start(frame_);
291 } 233 }
292 234
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 } 267 }
326 268
327 void WebMediaPlayerAndroid::play() { 269 void WebMediaPlayerAndroid::play() {
328 #if defined(VIDEO_HOLE) 270 #if defined(VIDEO_HOLE)
329 if (hasVideo() && needs_external_surface_ && 271 if (hasVideo() && needs_external_surface_ &&
330 !manager_->IsInFullscreen(frame_)) { 272 !manager_->IsInFullscreen(frame_)) {
331 DCHECK(!needs_establish_peer_); 273 DCHECK(!needs_establish_peer_);
332 manager_->RequestExternalSurface(player_id_, last_computed_rect_); 274 manager_->RequestExternalSurface(player_id_, last_computed_rect_);
333 } 275 }
334 #endif // defined(VIDEO_HOLE) 276 #endif // defined(VIDEO_HOLE)
335 #if defined(GOOGLE_TV)
336 if (audio_renderer_ && paused())
337 audio_renderer_->Play();
338 #endif // defined(GOOGLE_TV)
339 277
340 TryCreateStreamTextureProxyIfNeeded(); 278 TryCreateStreamTextureProxyIfNeeded();
341 if (hasVideo() && needs_establish_peer_) 279 if (hasVideo() && needs_establish_peer_)
342 EstablishSurfaceTexturePeer(); 280 EstablishSurfaceTexturePeer();
343 281
344 if (paused()) 282 if (paused())
345 manager_->Start(player_id_); 283 manager_->Start(player_id_);
346 UpdatePlayingState(true); 284 UpdatePlayingState(true);
347 UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); 285 UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
348 playing_started_ = true; 286 playing_started_ = true;
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 } 662 }
725 client_->repaint(); 663 client_->repaint();
726 } 664 }
727 665
728 void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) { 666 void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
729 has_size_info_ = true; 667 has_size_info_ = true;
730 if (natural_size_.width == width && natural_size_.height == height) 668 if (natural_size_.width == width && natural_size_.height == height)
731 return; 669 return;
732 670
733 #if defined(VIDEO_HOLE) 671 #if defined(VIDEO_HOLE)
734 bool has_surface_size_restriction = false;
735 #if defined(GOOGLE_TV)
736 has_surface_size_restriction = external_surface_threshold_ >= 0 &&
737 external_surface_threshold_ <= width * height;
738 #endif // defined(GOOGLE_TV)
739 // Use H/W surface for MSE as the content might be protected. 672 // Use H/W surface for MSE as the content might be protected.
740 // TODO(qinmin): Change this so that only EME needs the H/W surface 673 // TODO(qinmin): Change this so that only EME needs the H/W surface
741 if (media_source_delegate_ || has_surface_size_restriction) { 674 if (media_source_delegate_) {
742 needs_external_surface_ = true; 675 needs_external_surface_ = true;
743 if (!paused() && !manager_->IsInFullscreen(frame_)) 676 if (!paused() && !manager_->IsInFullscreen(frame_))
744 manager_->RequestExternalSurface(player_id_, last_computed_rect_); 677 manager_->RequestExternalSurface(player_id_, last_computed_rect_);
745 } else if (stream_texture_factory_ && !stream_id_) { 678 } else if (stream_texture_factory_ && !stream_id_) {
746 // Do deferred stream texture creation finally. 679 // Do deferred stream texture creation finally.
747 DoCreateStreamTexture(); 680 DoCreateStreamTexture();
748 if (paused()) { 681 if (paused()) {
749 SetNeedsEstablishPeer(true); 682 SetNeedsEstablishPeer(true);
750 } else { 683 } else {
751 EstablishSurfaceTexturePeer(); 684 EstablishSurfaceTexturePeer();
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 media_source_delegate_.reset(); 843 media_source_delegate_.reset();
911 { 844 {
912 base::AutoLock auto_lock(current_frame_lock_); 845 base::AutoLock auto_lock(current_frame_lock_);
913 current_frame_ = NULL; 846 current_frame_ = NULL;
914 } 847 }
915 is_remote_ = false; 848 is_remote_ = false;
916 manager_ = NULL; 849 manager_ = NULL;
917 } 850 }
918 851
919 void WebMediaPlayerAndroid::Pause(bool is_media_related_action) { 852 void WebMediaPlayerAndroid::Pause(bool is_media_related_action) {
920 #if defined(GOOGLE_TV)
921 if (audio_renderer_ && !paused())
922 audio_renderer_->Pause();
923 #endif
924 manager_->Pause(player_id_, is_media_related_action); 853 manager_->Pause(player_id_, is_media_related_action);
925 UpdatePlayingState(false); 854 UpdatePlayingState(false);
926 } 855 }
927 856
928 void WebMediaPlayerAndroid::DrawRemotePlaybackIcon() { 857 void WebMediaPlayerAndroid::DrawRemotePlaybackIcon() {
929 DCHECK(main_thread_checker_.CalledOnValidThread()); 858 DCHECK(main_thread_checker_.CalledOnValidThread());
930 if (!video_weblayer_) 859 if (!video_weblayer_)
931 return; 860 return;
932 blink::WebGraphicsContext3D* context = stream_texture_factory_->Context3d(); 861 blink::WebGraphicsContext3D* context = stream_texture_factory_->Context3d();
933 if (!context->makeContextCurrent()) 862 if (!context->makeContextCurrent())
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 if (current_key_system_.isEmpty() || key_system != current_key_system_) 1286 if (current_key_system_.isEmpty() || key_system != current_key_system_)
1358 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState; 1287 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
1359 1288
1360 decryptor_->CancelKeyRequest(session_id.utf8()); 1289 decryptor_->CancelKeyRequest(session_id.utf8());
1361 return WebMediaPlayer::MediaKeyExceptionNoError; 1290 return WebMediaPlayer::MediaKeyExceptionNoError;
1362 } 1291 }
1363 1292
1364 void WebMediaPlayerAndroid::OnKeyAdded(const std::string& session_id) { 1293 void WebMediaPlayerAndroid::OnKeyAdded(const std::string& session_id) {
1365 EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1); 1294 EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
1366 1295
1367 #if defined(GOOGLE_TV)
1368 if (media_source_delegate_)
1369 media_source_delegate_->NotifyKeyAdded(current_key_system_.utf8());
1370 #endif // defined(GOOGLE_TV)
1371
1372 client_->keyAdded(current_key_system_, WebString::fromUTF8(session_id)); 1296 client_->keyAdded(current_key_system_, WebString::fromUTF8(session_id));
1373 } 1297 }
1374 1298
1375 void WebMediaPlayerAndroid::OnKeyError(const std::string& session_id, 1299 void WebMediaPlayerAndroid::OnKeyError(const std::string& session_id,
1376 media::MediaKeys::KeyError error_code, 1300 media::MediaKeys::KeyError error_code,
1377 int system_code) { 1301 int system_code) {
1378 EmeUMAHistogramEnumeration(current_key_system_, "KeyError", 1302 EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
1379 error_code, media::MediaKeys::kMaxKeyError); 1303 error_code, media::MediaKeys::kMaxKeyError);
1380 1304
1381 client_->keyError( 1305 client_->keyError(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1420 init_data_type_ = type; 1344 init_data_type_ = type;
1421 1345
1422 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0]; 1346 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
1423 // TODO(xhwang): Drop |keySystem| and |sessionId| in keyNeeded() call. 1347 // TODO(xhwang): Drop |keySystem| and |sessionId| in keyNeeded() call.
1424 client_->keyNeeded(WebString(), 1348 client_->keyNeeded(WebString(),
1425 WebString(), 1349 WebString(),
1426 init_data_ptr, 1350 init_data_ptr,
1427 init_data.size()); 1351 init_data.size());
1428 } 1352 }
1429 1353
1430 #if defined(GOOGLE_TV)
1431 bool WebMediaPlayerAndroid::InjectMediaStream(
1432 MediaStreamClient* media_stream_client,
1433 media::Demuxer* demuxer,
1434 const base::Closure& destroy_demuxer_cb) {
1435 DCHECK(!demuxer);
1436 media_stream_client_ = media_stream_client;
1437 demuxer_ = demuxer;
1438 destroy_demuxer_cb_ = destroy_demuxer_cb;
1439 return true;
1440 }
1441 #endif
1442
1443 void WebMediaPlayerAndroid::DoReleaseRemotePlaybackTexture(uint32 sync_point) { 1354 void WebMediaPlayerAndroid::DoReleaseRemotePlaybackTexture(uint32 sync_point) {
1444 DCHECK(main_thread_checker_.CalledOnValidThread()); 1355 DCHECK(main_thread_checker_.CalledOnValidThread());
1445 DCHECK(remote_playback_texture_id_); 1356 DCHECK(remote_playback_texture_id_);
1446 1357
1447 blink::WebGraphicsContext3D* context = 1358 blink::WebGraphicsContext3D* context =
1448 stream_texture_factory_->Context3d(); 1359 stream_texture_factory_->Context3d();
1449 1360
1450 if (sync_point) 1361 if (sync_point)
1451 context->waitSyncPoint(sync_point); 1362 context->waitSyncPoint(sync_point);
1452 context->deleteTexture(remote_playback_texture_id_); 1363 context->deleteTexture(remote_playback_texture_id_);
1453 remote_playback_texture_id_ = 0; 1364 remote_playback_texture_id_ = 0;
1454 } 1365 }
1455 1366
1456 void WebMediaPlayerAndroid::enterFullscreen() { 1367 void WebMediaPlayerAndroid::enterFullscreen() {
1457 if (manager_->CanEnterFullscreen(frame_)) { 1368 if (manager_->CanEnterFullscreen(frame_)) {
1458 manager_->EnterFullscreen(player_id_); 1369 manager_->EnterFullscreen(player_id_);
1459 SetNeedsEstablishPeer(false); 1370 SetNeedsEstablishPeer(false);
1460 } 1371 }
1461 } 1372 }
1462 1373
1463 void WebMediaPlayerAndroid::exitFullscreen() { 1374 void WebMediaPlayerAndroid::exitFullscreen() {
1464 manager_->ExitFullscreen(player_id_); 1375 manager_->ExitFullscreen(player_id_);
1465 } 1376 }
1466 1377
1467 bool WebMediaPlayerAndroid::canEnterFullscreen() const { 1378 bool WebMediaPlayerAndroid::canEnterFullscreen() const {
1468 return manager_->CanEnterFullscreen(frame_); 1379 return manager_->CanEnterFullscreen(frame_);
1469 } 1380 }
1470 1381
1471 } // namespace content 1382 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698