Index: chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc |
diff --git a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc |
index 502cc1e6f78d79338801c38ebd564869824178d1..6e1bf9bdecd4f15f6d47385134b6e1d2ba6013f7 100644 |
--- a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc |
+++ b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc |
@@ -55,7 +55,6 @@ class WebContentsEntry : public content::WebContentsObserver { |
RenderFrameHost* new_host) override; |
void RenderFrameCreated(RenderFrameHost*) override; |
void WebContentsDestroyed() override; |
- void RenderProcessGone(base::TerminationStatus status) override; |
void OnRendererUnresponsive(RenderWidgetHost* render_widget_host) override; |
void DidFinishNavigation( |
content::NavigationHandle* navigation_handle) override; |
@@ -76,6 +75,10 @@ class WebContentsEntry : public content::WebContentsObserver { |
// Calls |on_task| for each task managed by this WebContentsEntry. |
void ForEachTask(const base::Callback<void(RendererTask*)>& on_task); |
+ // Walks parents until hitting a process boundary. Returns the highest frame |
+ // in the same SiteInstance as |render_frame_host|. |
+ RenderFrameHost* FindLocalRoot(RenderFrameHost* render_frame_host) const; |
+ |
// The provider that owns this entry. |
WebContentsTaskProvider* provider_; |
@@ -135,49 +138,66 @@ void WebContentsEntry::ClearAllTasks(bool notify_observer) { |
RendererTask* WebContentsEntry::GetTaskForFrame( |
RenderFrameHost* render_frame_host) const { |
- auto itr = tasks_by_frames_.find(render_frame_host); |
+ // Only local roots are in |tasks_by_frames_|. |
+ auto itr = tasks_by_frames_.find(FindLocalRoot(render_frame_host)); |
if (itr == tasks_by_frames_.end()) |
return nullptr; |
return itr->second; |
} |
+RenderFrameHost* WebContentsEntry::FindLocalRoot( |
+ RenderFrameHost* render_frame_host) const { |
+ SiteInstance* site_instance = render_frame_host->GetSiteInstance(); |
+ RenderFrameHost* candidate = render_frame_host; |
+ while (RenderFrameHost* parent = candidate->GetParent()) { |
+ if (parent->GetSiteInstance() != site_instance) |
+ break; |
+ candidate = parent; |
+ } |
+ return candidate; |
+} |
+ |
void WebContentsEntry::RenderFrameDeleted(RenderFrameHost* render_frame_host) { |
ClearTaskForFrame(render_frame_host); |
} |
void WebContentsEntry::RenderFrameHostChanged(RenderFrameHost* old_host, |
RenderFrameHost* new_host) { |
+ DCHECK(new_host->IsCurrent()); |
ClearTaskForFrame(old_host); |
CreateTaskForFrame(new_host); |
} |
void WebContentsEntry::RenderFrameCreated(RenderFrameHost* render_frame_host) { |
+ DCHECK(render_frame_host->IsRenderFrameLive()); |
+ |
// Skip pending/speculative hosts. We'll create tasks for these if the |
// navigation commits, at which point RenderFrameHostChanged() will fire. |
if (!render_frame_host->IsCurrent()) |
return; |
- // Task manager will have no separate entry for |render_frame_host| if it has |
- // the same site instance as its parent - quit early in this case. |
- if (render_frame_host->GetParent() && |
- render_frame_host->GetParent()->GetSiteInstance() == |
- render_frame_host->GetSiteInstance()) |
- return; |
- |
- // Postpone processing |render_frame_host| until its process has a PID. |
- render_frame_host->GetProcess()->PostTaskWhenProcessIsReady(base::Bind( |
- &WebContentsEntry::RenderFrameReady, weak_factory_.GetWeakPtr(), |
- render_frame_host->GetProcess()->GetID(), |
- render_frame_host->GetRoutingID())); |
+ CreateTaskForFrame(render_frame_host); |
} |
void WebContentsEntry::RenderFrameReady(int render_process_id, |
int render_frame_id) { |
+ // We get here when a RenderProcessHost we are tracking transitions to the |
+ // IsReady state. This might mean we know its process ID. |
content::RenderFrameHost* render_frame_host = |
content::RenderFrameHost::FromID(render_process_id, render_frame_id); |
- if (render_frame_host) |
- CreateTaskForFrame(render_frame_host); |
+ if (!render_frame_host) |
+ return; |
+ |
+ Task* task = GetTaskForFrame(render_frame_host); |
+ |
+ if (!task) |
+ return; |
+ |
+ const base::ProcessId determine_pid_from_handle = base::kNullProcessId; |
+ provider_->UpdateTaskProcessInfoAndNotifyObserver( |
+ task, render_frame_host->GetProcess()->GetHandle(), |
+ determine_pid_from_handle); |
} |
void WebContentsEntry::WebContentsDestroyed() { |
@@ -185,10 +205,6 @@ void WebContentsEntry::WebContentsDestroyed() { |
provider_->DeleteEntry(web_contents()); |
} |
-void WebContentsEntry::RenderProcessGone(base::TerminationStatus status) { |
- ClearAllTasks(true); |
-} |
- |
void WebContentsEntry::OnRendererUnresponsive( |
RenderWidgetHost* render_widget_host) { |
// Find the first RenderFrameHost matching the RenderWidgetHost. |
@@ -242,23 +258,34 @@ void WebContentsEntry::TitleWasSet(content::NavigationEntry* entry, |
} |
void WebContentsEntry::CreateTaskForFrame(RenderFrameHost* render_frame_host) { |
+ // Currently we do not track pending hosts, or pending delete hosts. |
+ DCHECK(render_frame_host->IsCurrent()); |
DCHECK(render_frame_host); |
DCHECK(!tasks_by_frames_.count(render_frame_host)); |
content::SiteInstance* site_instance = render_frame_host->GetSiteInstance(); |
- if (!site_instance->GetProcess()->HasConnection()) |
- return; |
+ |
+ // Exclude sad tabs and sad oopifs. |
if (!render_frame_host->IsRenderFrameLive()) |
return; |
+ // Exclude frames in the same SiteInstance as their parent; |tasks_by_frames_| |
+ // only contains local roots. |
+ if (render_frame_host->GetParent() && |
+ site_instance == render_frame_host->GetParent()->GetSiteInstance()) { |
+ return; |
+ } |
+ |
bool site_instance_exists = |
frames_by_site_instance_.count(site_instance) != 0; |
bool is_main_frame = (render_frame_host == web_contents()->GetMainFrame()); |
bool site_instance_is_main = (site_instance == main_frame_site_instance_); |
RendererTask* new_task = nullptr; |
- // We don't create a task if there's one for this site_instance AND |
- // if this is not the main frame or we did record a main frame for the entry. |
+ |
+ // We need to create a task if one doesn't already exist for this |
+ // SiteInstance, or if the main frame navigates to a process that currently is |
+ // represented by a SubframeTask. |
if (!site_instance_exists || (is_main_frame && !site_instance_is_main)) { |
if (is_main_frame) { |
const WebContentsTag* tag = |
@@ -280,7 +307,7 @@ void WebContentsEntry::CreateTaskForFrame(RenderFrameHost* render_frame_host) { |
RendererTask* old_task = tasks_by_frames_[existing_rfh]; |
if (!new_task) { |
- // We didn't create any new task, so we keep appending the old one. |
+ // We didn't create any new task, so we keep using the old one. |
tasks_by_frames_[render_frame_host] = old_task; |
} else { |
// Overwrite all the existing old tasks with the new one, and delete the |
@@ -298,6 +325,15 @@ void WebContentsEntry::CreateTaskForFrame(RenderFrameHost* render_frame_host) { |
if (new_task) { |
tasks_by_frames_[render_frame_host] = new_task; |
provider_->NotifyObserverTaskAdded(new_task); |
+ |
+ // If we don't know the OS process handle yet (e.g., because this task is |
+ // still launching), update the task when it becomes available. |
+ if (new_task->process_id() == base::kNullProcessId) { |
+ render_frame_host->GetProcess()->PostTaskWhenProcessIsReady(base::Bind( |
+ &WebContentsEntry::RenderFrameReady, weak_factory_.GetWeakPtr(), |
+ render_frame_host->GetProcess()->GetID(), |
+ render_frame_host->GetRoutingID())); |
+ } |
} |
} |
@@ -320,6 +356,9 @@ void WebContentsEntry::ClearTaskForFrame(RenderFrameHost* render_frame_host) { |
if (site_instance == main_frame_site_instance_) |
main_frame_site_instance_ = nullptr; |
} |
+ |
+ // Whenever we have a task, we should have a main frame site instance. |
+ DCHECK(tasks_by_frames_.empty() == (main_frame_site_instance_ == nullptr)); |
} |
void WebContentsEntry::ForEachTask( |
@@ -335,9 +374,7 @@ void WebContentsEntry::ForEachTask( |
//////////////////////////////////////////////////////////////////////////////// |
-WebContentsTaskProvider::WebContentsTaskProvider() |
- : is_updating_(false) { |
-} |
+WebContentsTaskProvider::WebContentsTaskProvider() : is_updating_(false) {} |
WebContentsTaskProvider::~WebContentsTaskProvider() { |
if (is_updating_) { |