1 // Copyright 2014 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.
5 #include "chrome/browser/task_manager/web_contents_resource_provider.h"
8 #include "base/bind_helpers.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/prerender/prerender_manager.h"
11 #include "chrome/browser/prerender/prerender_manager_factory.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/task_manager/renderer_resource.h"
15 #include "chrome/browser/task_manager/task_manager.h"
16 #include "chrome/browser/task_manager/task_manager_util.h"
17 #include "chrome/browser/task_manager/web_contents_information.h"
18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/render_widget_host_iterator.h"
22 #include "content/public/browser/web_contents.h"
23 #include "content/public/browser/web_contents_observer.h"
25 using content::WebContents
;
26 using content::RenderViewHost
;
28 namespace task_manager
{
30 // A WebContentsObserver that tracks changes to a WebContents on behalf of
31 // a WebContentsResourceProvider.
32 class TaskManagerWebContentsObserver
: public content::WebContentsObserver
{
34 TaskManagerWebContentsObserver(WebContents
* web_contents
,
35 WebContentsResourceProvider
* provider
)
36 : content::WebContentsObserver(web_contents
), provider_(provider
) {}
38 // content::WebContentsObserver implementation.
39 virtual void RenderViewHostChanged(RenderViewHost
* old_host
,
40 RenderViewHost
* new_host
) OVERRIDE
{
41 provider_
->RemoveFromTaskManager(web_contents());
42 provider_
->AddToTaskManager(web_contents());
45 virtual void RenderViewReady() OVERRIDE
{
46 provider_
->RemoveFromTaskManager(web_contents());
47 provider_
->AddToTaskManager(web_contents());
50 virtual void RenderProcessGone(base::TerminationStatus status
) OVERRIDE
{
51 provider_
->RemoveFromTaskManager(web_contents());
54 virtual void WebContentsDestroyed(WebContents
* web_contents
) OVERRIDE
{
55 provider_
->RemoveFromTaskManager(web_contents
);
56 provider_
->DeleteObserver(this); // Deletes |this|.
60 WebContentsResourceProvider
* provider_
;
63 ////////////////////////////////////////////////////////////////////////////////
64 // WebContentsResourceProvider class
65 ////////////////////////////////////////////////////////////////////////////////
67 WebContentsResourceProvider::WebContentsResourceProvider(
68 TaskManager
* task_manager
,
69 scoped_ptr
<WebContentsInformation
> info
)
70 : updating_(false), task_manager_(task_manager
), info_(info
.Pass()) {}
72 WebContentsResourceProvider::~WebContentsResourceProvider() {}
74 RendererResource
* WebContentsResourceProvider::GetResource(int origin_pid
,
77 content::RenderFrameHost
* rfh
=
78 content::RenderFrameHost::FromID(child_id
, route_id
);
79 content::WebContents
* web_contents
=
80 content::WebContents::FromRenderFrameHost(rfh
);
82 // If an origin PID was specified then the request originated in a plugin
83 // working on the WebContents's behalf, so ignore it.
87 std::map
<WebContents
*, RendererResource
*>::iterator res_iter
=
88 resources_
.find(web_contents
);
90 if (res_iter
== resources_
.end()) {
91 // Can happen if the tab was closed while a network request was being
95 return res_iter
->second
;
98 void WebContentsResourceProvider::StartUpdating() {
102 WebContentsInformation::NewWebContentsCallback new_web_contents_callback
=
103 base::Bind(&WebContentsResourceProvider::OnWebContentsCreated
, this);
104 info_
->GetAll(new_web_contents_callback
);
105 info_
->StartObservingCreation(new_web_contents_callback
);
108 void WebContentsResourceProvider::StopUpdating() {
112 info_
->StopObservingCreation();
114 // Delete all observers; this dissassociates them from the WebContents too.
115 STLDeleteElements(&web_contents_observers_
);
116 web_contents_observers_
.clear();
118 // Delete all resources. We don't need to remove them from the TaskManager,
119 // because it's the TaskManager that's asking us to StopUpdating().
120 STLDeleteValues(&resources_
);
124 void WebContentsResourceProvider::OnWebContentsCreated(
125 WebContents
* web_contents
) {
126 // Don't add dead tabs or tabs that haven't yet connected.
127 if (!web_contents
->GetRenderProcessHost()->GetHandle() ||
128 !web_contents
->WillNotifyDisconnection()) {
132 DCHECK(info_
->CheckOwnership(web_contents
));
133 if (AddToTaskManager(web_contents
)) {
134 web_contents_observers_
.insert(
135 new TaskManagerWebContentsObserver(web_contents
, this));
139 bool WebContentsResourceProvider::AddToTaskManager(WebContents
* web_contents
) {
143 if (resources_
.count(web_contents
)) {
144 // The case may happen that we have added a WebContents as part of the
145 // iteration performed during StartUpdating() call but the notification that
146 // it has connected was not fired yet. So when the notification happens, we
147 // are already observing this WebContents and just ignore it.
151 // TODO(nick): If the RenderView is not live, then do we still want to install
152 // the WebContentsObserver? Only some of the original ResourceProviders
154 scoped_ptr
<RendererResource
> resource
= info_
->MakeResource(web_contents
);
158 task_manager_
->AddResource(resource
.get());
159 resources_
[web_contents
] = resource
.release();
163 void WebContentsResourceProvider::RemoveFromTaskManager(
164 WebContents
* web_contents
) {
168 std::map
<WebContents
*, RendererResource
*>::iterator resource_iter
=
169 resources_
.find(web_contents
);
171 if (resource_iter
== resources_
.end()) {
175 RendererResource
* resource
= resource_iter
->second
;
176 task_manager_
->RemoveResource(resource
);
178 // Remove the resource from the Task Manager.
179 // And from the provider.
180 resources_
.erase(resource_iter
);
182 // Finally, delete the resource.
186 void WebContentsResourceProvider::DeleteObserver(
187 TaskManagerWebContentsObserver
* observer
) {
188 if (!web_contents_observers_
.erase(observer
)) {
192 delete observer
; // Typically, this is our caller. Deletion is okay.
195 } // namespace task_manager