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/renderer_host/media/web_contents_tracker.h"
6
7#include "base/message_loop/message_loop_proxy.h"
8#include "content/public/browser/browser_thread.h"
9#include "content/public/browser/render_process_host.h"
10#include "content/public/browser/render_view_host.h"
11#include "content/public/browser/web_contents.h"
12
13namespace content {
14
15WebContentsTracker::WebContentsTracker() {}
16
17WebContentsTracker::~WebContentsTracker() {
18  DCHECK(!web_contents()) << "BUG: Still observering!";
19}
20
21void WebContentsTracker::Start(int render_process_id, int render_view_id,
22                               const ChangeCallback& callback) {
23  DCHECK(!message_loop_.get() || message_loop_->BelongsToCurrentThread());
24
25  message_loop_ = base::MessageLoopProxy::current();
26  DCHECK(message_loop_.get());
27  callback_ = callback;
28
29  BrowserThread::PostTask(
30      BrowserThread::UI, FROM_HERE,
31      base::Bind(&WebContentsTracker::LookUpAndObserveWebContents, this,
32                 render_process_id, render_view_id));
33}
34
35void WebContentsTracker::Stop() {
36  DCHECK(message_loop_->BelongsToCurrentThread());
37
38  callback_.Reset();
39
40  BrowserThread::PostTask(
41      BrowserThread::UI, FROM_HERE,
42      base::Bind(&WebContentsTracker::Observe, this,
43                 static_cast<WebContents*>(NULL)));
44}
45
46void WebContentsTracker::OnWebContentsChangeEvent() {
47  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48
49  WebContents* const wc = web_contents();
50  RenderViewHost* const rvh = wc ? wc->GetRenderViewHost() : NULL;
51  RenderProcessHost* const rph = rvh ? rvh->GetProcess() : NULL;
52
53  const int render_process_id = rph ? rph->GetID() : MSG_ROUTING_NONE;
54  const int render_view_id = rvh ? rvh->GetRoutingID() : MSG_ROUTING_NONE;
55
56  message_loop_->PostTask(FROM_HERE,
57      base::Bind(&WebContentsTracker::MaybeDoCallback, this,
58                 render_process_id, render_view_id));
59}
60
61void WebContentsTracker::MaybeDoCallback(int render_process_id,
62                                         int render_view_id) {
63  DCHECK(message_loop_->BelongsToCurrentThread());
64
65  if (!callback_.is_null())
66    callback_.Run(render_process_id, render_view_id);
67}
68
69void WebContentsTracker::LookUpAndObserveWebContents(int render_process_id,
70                                                     int render_view_id) {
71  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
72
73  RenderViewHost* const rvh =
74      RenderViewHost::FromID(render_process_id, render_view_id);
75  DVLOG_IF(1, !rvh) << "RenderViewHost::FromID("
76                    << render_process_id << ", " << render_view_id
77                    << ") returned NULL.";
78  Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
79  DVLOG_IF(1, !web_contents())
80      << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL.";
81
82  OnWebContentsChangeEvent();
83}
84
85void WebContentsTracker::RenderViewReady() {
86  OnWebContentsChangeEvent();
87}
88
89void WebContentsTracker::AboutToNavigateRenderView(RenderViewHost* rvh) {
90  OnWebContentsChangeEvent();
91}
92
93void WebContentsTracker::DidNavigateMainFrame(
94    const LoadCommittedDetails& details, const FrameNavigateParams& params) {
95  OnWebContentsChangeEvent();
96}
97
98void WebContentsTracker::WebContentsDestroyed(WebContents* web_contents) {
99  OnWebContentsChangeEvent();
100}
101
102}  // namespace content
103