• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WebContentsTracker(bool track_fullscreen_rwh)17 WebContentsTracker::WebContentsTracker(bool track_fullscreen_rwh)
18     : track_fullscreen_rwh_(track_fullscreen_rwh),
19       last_target_(NULL) {}
20 
~WebContentsTracker()21 WebContentsTracker::~WebContentsTracker() {
22   DCHECK(!web_contents()) << "BUG: Still observering!";
23 }
24 
Start(int render_process_id,int main_render_frame_id,const ChangeCallback & callback)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 
Stop()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 
GetTargetRenderWidgetHost() const58 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 
OnPossibleTargetChange(bool force_callback_run)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 
MaybeDoCallback(RenderWidgetHost * rwh)100 void WebContentsTracker::MaybeDoCallback(RenderWidgetHost* rwh) {
101   DCHECK(message_loop_->BelongsToCurrentThread());
102 
103   if (!callback_.is_null())
104     callback_.Run(rwh);
105 }
106 
StartObservingWebContents(int render_process_id,int main_render_frame_id)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 
RenderFrameDeleted(RenderFrameHost * render_frame_host)121 void WebContentsTracker::RenderFrameDeleted(
122     RenderFrameHost* render_frame_host) {
123   OnPossibleTargetChange(false);
124 }
125 
RenderFrameHostChanged(RenderFrameHost * old_host,RenderFrameHost * new_host)126 void WebContentsTracker::RenderFrameHostChanged(RenderFrameHost* old_host,
127                                                 RenderFrameHost* new_host) {
128   OnPossibleTargetChange(false);
129 }
130 
WebContentsDestroyed()131 void WebContentsTracker::WebContentsDestroyed() {
132   Observe(NULL);
133   OnPossibleTargetChange(false);
134 }
135 
DidShowFullscreenWidget(int routing_id)136 void WebContentsTracker::DidShowFullscreenWidget(int routing_id) {
137   OnPossibleTargetChange(false);
138 }
139 
DidDestroyFullscreenWidget(int routing_id)140 void WebContentsTracker::DidDestroyFullscreenWidget(int routing_id) {
141   OnPossibleTargetChange(false);
142 }
143 
144 }  // namespace content
145