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 WebContentsDestroyed(WebContents
* web_contents
) OVERRIDE
{
46 provider_
->RemoveFromTaskManager(web_contents
);
47 provider_
->DeleteObserver(this); // Deletes |this|.
51 WebContentsResourceProvider
* provider_
;
54 ////////////////////////////////////////////////////////////////////////////////
55 // WebContentsResourceProvider class
56 ////////////////////////////////////////////////////////////////////////////////
58 WebContentsResourceProvider::WebContentsResourceProvider(
59 TaskManager
* task_manager
,
60 scoped_ptr
<WebContentsInformation
> info
)
61 : updating_(false), task_manager_(task_manager
), info_(info
.Pass()) {}
63 WebContentsResourceProvider::~WebContentsResourceProvider() {}
65 RendererResource
* WebContentsResourceProvider::GetResource(int origin_pid
,
68 content::RenderFrameHost
* rfh
=
69 content::RenderFrameHost::FromID(child_id
, route_id
);
70 content::WebContents
* web_contents
=
71 content::WebContents::FromRenderFrameHost(rfh
);
73 // If an origin PID was specified then the request originated in a plugin
74 // working on the WebContents's behalf, so ignore it.
78 std::map
<WebContents
*, RendererResource
*>::iterator res_iter
=
79 resources_
.find(web_contents
);
81 if (res_iter
== resources_
.end()) {
82 // Can happen if the tab was closed while a network request was being
86 return res_iter
->second
;
89 void WebContentsResourceProvider::StartUpdating() {
93 WebContentsInformation::NewWebContentsCallback new_web_contents_callback
=
94 base::Bind(&WebContentsResourceProvider::OnWebContentsCreated
, this);
95 info_
->GetAll(new_web_contents_callback
);
96 info_
->StartObservingCreation(new_web_contents_callback
);
99 void WebContentsResourceProvider::StopUpdating() {
103 info_
->StopObservingCreation();
105 // Delete all observers; this dissassociates them from the WebContents too.
106 STLDeleteElements(&web_contents_observers_
);
107 web_contents_observers_
.clear();
109 // Delete all resources. We don't need to remove them from the TaskManager,
110 // because it's the TaskManager that's asking us to StopUpdating().
111 STLDeleteValues(&resources_
);
115 void WebContentsResourceProvider::OnWebContentsCreated(
116 WebContents
* web_contents
) {
117 // Don't add dead tabs or tabs that haven't yet connected.
118 if (!web_contents
->GetRenderProcessHost()->GetHandle() ||
119 !web_contents
->WillNotifyDisconnection()) {
123 DCHECK(info_
->CheckOwnership(web_contents
));
124 if (AddToTaskManager(web_contents
)) {
125 web_contents_observers_
.insert(
126 new TaskManagerWebContentsObserver(web_contents
, this));
130 bool WebContentsResourceProvider::AddToTaskManager(WebContents
* web_contents
) {
134 if (resources_
.count(web_contents
)) {
135 // The case may happen that we have added a WebContents as part of the
136 // iteration performed during StartUpdating() call but the notification that
137 // it has connected was not fired yet. So when the notification happens, we
138 // are already observing this WebContents and just ignore it.
142 // TODO(nick): If the RenderView is not live, then do we still want to install
143 // the WebContentsObserver? Only some of the original ResourceProviders
145 scoped_ptr
<RendererResource
> resource
= info_
->MakeResource(web_contents
);
149 task_manager_
->AddResource(resource
.get());
150 resources_
[web_contents
] = resource
.release();
154 void WebContentsResourceProvider::RemoveFromTaskManager(
155 WebContents
* web_contents
) {
159 std::map
<WebContents
*, RendererResource
*>::iterator resource_iter
=
160 resources_
.find(web_contents
);
162 if (resource_iter
== resources_
.end()) {
166 RendererResource
* resource
= resource_iter
->second
;
167 task_manager_
->RemoveResource(resource
);
169 // Remove the resource from the Task Manager.
170 // And from the provider.
171 resources_
.erase(resource_iter
);
173 // Finally, delete the resource.
177 void WebContentsResourceProvider::DeleteObserver(
178 TaskManagerWebContentsObserver
* observer
) {
179 if (!web_contents_observers_
.erase(observer
)) {
183 delete observer
; // Typically, this is our caller. Deletion is okay.
186 } // namespace task_manager