blob: 5007a583af89f3d6ece16ee01ce1b815e3932239 [file] [log] [blame]
// 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