1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/media/capture/web_contents_tracker.h" 6 7 #include "base/message_loop/message_loop_proxy.h" 8 #include "content/browser/frame_host/render_frame_host_impl.h" 9 #include "content/browser/renderer_host/render_widget_host_impl.h" 10 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/render_process_host.h" 12 #include "content/public/browser/render_widget_host_view.h" 13 #include "content/public/browser/web_contents.h" 14 15 namespace content { 16 17 WebContentsTracker::WebContentsTracker(bool track_fullscreen_rwh) 18 : track_fullscreen_rwh_(track_fullscreen_rwh), 19 last_target_(NULL) {} 20 21 WebContentsTracker::~WebContentsTracker() { 22 DCHECK(!web_contents()) << "BUG: Still observering!"; 23 } 24 25 void WebContentsTracker::Start(int render_process_id, int main_render_frame_id, 26 const ChangeCallback& callback) { 27 DCHECK(!message_loop_.get() || message_loop_->BelongsToCurrentThread()); 28 29 message_loop_ = base::MessageLoopProxy::current(); 30 DCHECK(message_loop_.get()); 31 callback_ = callback; 32 33 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 34 StartObservingWebContents(render_process_id, main_render_frame_id); 35 } else { 36 BrowserThread::PostTask( 37 BrowserThread::UI, FROM_HERE, 38 base::Bind(&WebContentsTracker::StartObservingWebContents, this, 39 render_process_id, main_render_frame_id)); 40 } 41 } 42 43 void WebContentsTracker::Stop() { 44 DCHECK(message_loop_->BelongsToCurrentThread()); 45 46 callback_.Reset(); 47 48 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 49 WebContentsObserver::Observe(NULL); 50 } else { 51 BrowserThread::PostTask( 52 BrowserThread::UI, FROM_HERE, 53 base::Bind(&WebContentsTracker::Observe, this, 54 static_cast<WebContents*>(NULL))); 55 } 56 } 57 58 RenderWidgetHost* WebContentsTracker::GetTargetRenderWidgetHost() const { 59 DCHECK_CURRENTLY_ON(BrowserThread::UI); 60 61 WebContents* const wc = web_contents(); 62 if (!wc) 63 return NULL; 64 65 RenderWidgetHost* rwh = NULL; 66 if (track_fullscreen_rwh_) { 67 RenderWidgetHostView* const view = wc->GetFullscreenRenderWidgetHostView(); 68 if (view) 69 rwh = view->GetRenderWidgetHost(); 70 } 71 if (!rwh) { 72 RenderFrameHostImpl* const rfh = 73 static_cast<RenderFrameHostImpl*>(wc->GetMainFrame()); 74 if (rfh) 75 rwh = rfh->GetRenderWidgetHost(); 76 } 77 78 return rwh; 79 } 80 81 void WebContentsTracker::OnPossibleTargetChange(bool force_callback_run) { 82 DCHECK_CURRENTLY_ON(BrowserThread::UI); 83 84 RenderWidgetHost* const rwh = GetTargetRenderWidgetHost(); 85 if (rwh == last_target_ && !force_callback_run) 86 return; 87 DVLOG(1) << "Will report target change from RenderWidgetHost@" << last_target_ 88 << " to RenderWidgetHost@" << rwh; 89 last_target_ = rwh; 90 91 if (message_loop_->BelongsToCurrentThread()) { 92 MaybeDoCallback(rwh); 93 } else { 94 message_loop_->PostTask( 95 FROM_HERE, 96 base::Bind(&WebContentsTracker::MaybeDoCallback, this, rwh)); 97 } 98 } 99 100 void WebContentsTracker::MaybeDoCallback(RenderWidgetHost* rwh) { 101 DCHECK(message_loop_->BelongsToCurrentThread()); 102 103 if (!callback_.is_null()) 104 callback_.Run(rwh); 105 } 106 107 void WebContentsTracker::StartObservingWebContents(int render_process_id, 108 int main_render_frame_id) { 109 DCHECK_CURRENTLY_ON(BrowserThread::UI); 110 111 Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID( 112 render_process_id, main_render_frame_id))); 113 DVLOG_IF(1, !web_contents()) 114 << "Could not find WebContents associated with main RenderFrameHost " 115 << "referenced by render_process_id=" << render_process_id 116 << ", routing_id=" << main_render_frame_id; 117 118 OnPossibleTargetChange(true); 119 } 120 121 void WebContentsTracker::RenderFrameDeleted( 122 RenderFrameHost* render_frame_host) { 123 OnPossibleTargetChange(false); 124 } 125 126 void WebContentsTracker::RenderFrameHostChanged(RenderFrameHost* old_host, 127 RenderFrameHost* new_host) { 128 OnPossibleTargetChange(false); 129 } 130 131 void WebContentsTracker::WebContentsDestroyed() { 132 Observe(NULL); 133 OnPossibleTargetChange(false); 134 } 135 136 void WebContentsTracker::DidShowFullscreenWidget(int routing_id) { 137 OnPossibleTargetChange(false); 138 } 139 140 void WebContentsTracker::DidDestroyFullscreenWidget(int routing_id) { 141 OnPossibleTargetChange(false); 142 } 143 144 } // namespace content 145