File: render_process_host_task_provider.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (153 lines) | stat: -rw-r--r-- 5,200 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/task_manager/providers/render_process_host_task_provider.h"

#include "base/process/process.h"
#include "chrome/browser/task_manager/providers/child_process_task.h"
#include "chrome/common/buildflags.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/process_type.h"
#include "extensions/buildflags/buildflags.h"

#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/process_map.h"  // nogncheck
#endif

#if BUILDFLAG(ENABLE_GLIC)
#include "chrome/browser/glic/glic_enabling.h"
#include "chrome/browser/glic/glic_keyed_service_factory.h"
#include "chrome/browser/glic/widget/glic_window_controller.h"
#endif

using content::BrowserThread;
using content::ChildProcessData;
using content::RenderProcessHost;

namespace task_manager {

namespace {

#if BUILDFLAG(ENABLE_GLIC)
bool IsHostForGlic(content::RenderProcessHost* host) {
  // This needs to match the GlicKeyedServiceFactory initialization logic in
  // EnsureBrowserContextKeyedServiceFactoriesBuilt().
  if (!glic::GlicEnabling::IsEnabledByFlags()) {
    return false;
  }

  auto* glic_service = glic::GlicKeyedServiceFactory::GetGlicKeyedService(
      host->GetBrowserContext());
  return glic_service && glic_service->IsProcessHostForGlic(host);
}
#endif  // BUILDFLAG(ENABLE_GLIC)

}  // namespace

RenderProcessHostTaskProvider::RenderProcessHostTaskProvider() = default;

RenderProcessHostTaskProvider::~RenderProcessHostTaskProvider() = default;

Task* RenderProcessHostTaskProvider::GetTaskOfUrlRequest(int child_id,
                                                         int route_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  auto itr = tasks_by_rph_id_.find(content::ChildProcessId(child_id));
  return itr != tasks_by_rph_id_.end() ? itr->second.get() : nullptr;
}

void RenderProcessHostTaskProvider::StartUpdating() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(tasks_by_rph_id_.empty());
  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
       !it.IsAtEnd(); it.Advance()) {
    RenderProcessHost* host = it.GetCurrentValue();
    host_observation_.AddObservation(host);
    if (host->GetProcess().IsValid()) {
      CreateTask(host);
    } else {
      // If the host isn't ready, do nothing and wait for the
      // OnRenderProcessHostCreated() notification.
    }
  }

  is_updating_ = true;
}

void RenderProcessHostTaskProvider::StopUpdating() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Then delete all tasks (if any).
  host_observation_.RemoveAllObservations();
  tasks_by_rph_id_.clear();

  is_updating_ = false;
}

void RenderProcessHostTaskProvider::CreateTask(
    content::RenderProcessHost* host) {
  // Checks that the task by RenderProcessHost ID isn't already a task in the
  // map and deletes it if it is so they new task can be cleanly added.
  const content::ChildProcessId render_process_host_id = host->GetID();
  DeleteTask(render_process_host_id);

  // TODO(cburn): plumb out something from RPH so the title can be set here.
  // Create the task and notify the observer.
  ChildProcessData data(content::PROCESS_TYPE_RENDERER, host->GetID());
  data.SetProcess(host->GetProcess().Duplicate());

  auto subtype = ChildProcessTask::ProcessSubtype::kUnknownRenderProcess;
#if BUILDFLAG(ENABLE_GLIC)
  if (IsHostForGlic(host)) {
    subtype = ChildProcessTask::ProcessSubtype::kGlicRenderProcess;
  }
#endif
  std::unique_ptr<ChildProcessTask>& task =
      tasks_by_rph_id_[render_process_host_id];
  task = std::make_unique<ChildProcessTask>(data, subtype);
  NotifyObserverTaskAdded(task.get());
}

void RenderProcessHostTaskProvider::DeleteTask(
    const content::ChildProcessId render_process_host_id) {
  auto itr = tasks_by_rph_id_.find(render_process_host_id);
  // If the render process host id isn't being tracked in `tasks_by_rph_id` do
  // nothing.
  if (itr == tasks_by_rph_id_.end())
    return;

  NotifyObserverTaskRemoved(itr->second.get());

  // Finally delete the task.
  tasks_by_rph_id_.erase(itr);
}

void RenderProcessHostTaskProvider::OnRenderProcessHostCreated(
    content::RenderProcessHost* host) {
  if (is_updating_) {
    CreateTask(host);
    // If the host is reused after the process exited, it is possible to get a
    // second created notification for the same host.
    if (!host_observation_.IsObservingSource(host)) {
      host_observation_.AddObservation(host);
    }
  }
}

void RenderProcessHostTaskProvider::RenderProcessExited(
    content::RenderProcessHost* host,
    const content::ChildProcessTerminationInfo& info) {
  DeleteTask(host->GetID());
  host_observation_.RemoveObservation(host);
}

void RenderProcessHostTaskProvider::RenderProcessHostDestroyed(
    content::RenderProcessHost* host) {
  DeleteTask(host->GetID());
  host_observation_.RemoveObservation(host);
}

}  // namespace task_manager