| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/media/capture/web_contents_tracker.h" |
| |
| #include "base/thread_task_runner_handle.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_widget_host_view.h" |
| #include "content/public/browser/web_contents.h" |
| |
| namespace content { |
| |
| WebContentsTracker::WebContentsTracker(bool track_fullscreen_rwh) |
| : track_fullscreen_rwh_(track_fullscreen_rwh), |
| last_target_(NULL) {} |
| |
| WebContentsTracker::~WebContentsTracker() { |
| DCHECK(!web_contents()) << "BUG: Still observering!"; |
| } |
| |
| void WebContentsTracker::Start(int render_process_id, int main_render_frame_id, |
| const ChangeCallback& callback) { |
| DCHECK(!task_runner_.get() || task_runner_->BelongsToCurrentThread()); |
| |
| task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| DCHECK(task_runner_.get()); |
| callback_ = callback; |
| |
| if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| StartObservingWebContents(render_process_id, main_render_frame_id); |
| } else { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&WebContentsTracker::StartObservingWebContents, this, |
| render_process_id, main_render_frame_id)); |
| } |
| } |
| |
| void WebContentsTracker::Stop() { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| |
| callback_.Reset(); |
| resize_callback_.Reset(); |
| |
| if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| WebContentsObserver::Observe(NULL); |
| } else { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&WebContentsTracker::Observe, this, |
| static_cast<WebContents*>(NULL))); |
| } |
| } |
| |
| RenderWidgetHost* WebContentsTracker::GetTargetRenderWidgetHost() const { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| WebContents* const wc = web_contents(); |
| if (!wc) |
| return NULL; |
| |
| RenderWidgetHost* rwh = NULL; |
| if (track_fullscreen_rwh_) { |
| RenderWidgetHostView* const view = wc->GetFullscreenRenderWidgetHostView(); |
| if (view) |
| rwh = view->GetRenderWidgetHost(); |
| } |
| if (!rwh) { |
| RenderFrameHostImpl* const rfh = |
| static_cast<RenderFrameHostImpl*>(wc->GetMainFrame()); |
| if (rfh) |
| rwh = rfh->GetRenderWidgetHost(); |
| } |
| |
| return rwh; |
| } |
| |
| void WebContentsTracker::SetResizeChangeCallback( |
| const base::Closure& callback) { |
| DCHECK(!task_runner_.get() || task_runner_->BelongsToCurrentThread()); |
| resize_callback_ = callback; |
| } |
| |
| void WebContentsTracker::OnPossibleTargetChange(bool force_callback_run) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| RenderWidgetHost* const rwh = GetTargetRenderWidgetHost(); |
| if (rwh == last_target_ && !force_callback_run) |
| return; |
| DVLOG(1) << "Will report target change from RenderWidgetHost@" << last_target_ |
| << " to RenderWidgetHost@" << rwh; |
| last_target_ = rwh; |
| |
| if (task_runner_->BelongsToCurrentThread()) { |
| MaybeDoCallback(rwh != nullptr); |
| return; |
| } |
| |
| task_runner_->PostTask( |
| FROM_HERE, |
| base::Bind(&WebContentsTracker::MaybeDoCallback, this, rwh != nullptr)); |
| } |
| |
| void WebContentsTracker::MaybeDoCallback(bool was_still_tracking) { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| |
| if (!callback_.is_null()) |
| callback_.Run(was_still_tracking); |
| if (was_still_tracking) |
| MaybeDoResizeCallback(); |
| } |
| |
| void WebContentsTracker::MaybeDoResizeCallback() { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| |
| if (!resize_callback_.is_null()) |
| resize_callback_.Run(); |
| } |
| |
| void WebContentsTracker::StartObservingWebContents(int render_process_id, |
| int main_render_frame_id) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID( |
| render_process_id, main_render_frame_id))); |
| DVLOG_IF(1, !web_contents()) |
| << "Could not find WebContents associated with main RenderFrameHost " |
| << "referenced by render_process_id=" << render_process_id |
| << ", routing_id=" << main_render_frame_id; |
| |
| OnPossibleTargetChange(true); |
| } |
| |
| void WebContentsTracker::RenderFrameDeleted( |
| RenderFrameHost* render_frame_host) { |
| OnPossibleTargetChange(false); |
| } |
| |
| void WebContentsTracker::RenderFrameHostChanged(RenderFrameHost* old_host, |
| RenderFrameHost* new_host) { |
| OnPossibleTargetChange(false); |
| } |
| |
| void WebContentsTracker::MainFrameWasResized(bool width_changed) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| |
| if (task_runner_->BelongsToCurrentThread()) { |
| MaybeDoResizeCallback(); |
| return; |
| } |
| |
| task_runner_->PostTask( |
| FROM_HERE, |
| base::Bind(&WebContentsTracker::MaybeDoResizeCallback, this)); |
| } |
| |
| void WebContentsTracker::WebContentsDestroyed() { |
| Observe(NULL); |
| OnPossibleTargetChange(false); |
| } |
| |
| void WebContentsTracker::DidShowFullscreenWidget(int routing_id) { |
| OnPossibleTargetChange(false); |
| } |
| |
| void WebContentsTracker::DidDestroyFullscreenWidget(int routing_id) { |
| OnPossibleTargetChange(false); |
| } |
| |
| } // namespace content |