summaryrefslogtreecommitdiff
path: root/chromium/content/browser/service_process_host_impl.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 10:22:43 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:36:28 +0000
commit271a6c3487a14599023a9106329505597638d793 (patch)
treee040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/content/browser/service_process_host_impl.cc
parent7b2ffa587235a47d4094787d72f38102089f402a (diff)
downloadqtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/content/browser/service_process_host_impl.cc')
-rw-r--r--chromium/content/browser/service_process_host_impl.cc210
1 files changed, 210 insertions, 0 deletions
diff --git a/chromium/content/browser/service_process_host_impl.cc b/chromium/content/browser/service_process_host_impl.cc
new file mode 100644
index 00000000000..50034eadc8f
--- /dev/null
+++ b/chromium/content/browser/service_process_host_impl.cc
@@ -0,0 +1,210 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/no_destructor.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
+#include "base/task/post_task.h"
+#include "content/browser/utility_process_host.h"
+#include "content/common/child_process.mojom.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/service_process_host.h"
+#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace content {
+
+namespace {
+
+// Internal helper to track running service processes. Usage of this class is
+// split across the IO thread and UI thread.
+class ServiceProcessTracker {
+ public:
+ ServiceProcessTracker()
+ : ui_task_runner_(
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI})) {
+ }
+ ~ServiceProcessTracker() = default;
+
+ ServiceProcessInfo AddProcess(const base::Process& process,
+ const std::string& service_interface_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ base::AutoLock lock(processes_lock_);
+ auto id = GenerateNextId();
+ ServiceProcessInfo& info = processes_[id];
+ info.service_process_id = id;
+ info.pid = process.Pid();
+ info.service_interface_name = service_interface_name;
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ServiceProcessTracker::NotifyLaunchOnUIThread,
+ base::Unretained(this), info));
+ return info;
+ }
+
+ void NotifyTerminated(ServiceProcessId id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ base::AutoLock lock(processes_lock_);
+ auto iter = processes_.find(id);
+ DCHECK(iter != processes_.end());
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ServiceProcessTracker::NotifyTerminatedOnUIThread,
+ base::Unretained(this), iter->second));
+ }
+
+ void NotifyCrashed(ServiceProcessId id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ base::AutoLock lock(processes_lock_);
+ auto iter = processes_.find(id);
+ DCHECK(iter != processes_.end());
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ServiceProcessTracker::NotifyCrashedOnUIThread,
+ base::Unretained(this), iter->second));
+ }
+
+ void AddObserver(ServiceProcessHost::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(ServiceProcessHost::Observer* observer) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ observers_.RemoveObserver(observer);
+ }
+
+ std::vector<ServiceProcessInfo> GetProcesses() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ base::AutoLock lock(processes_lock_);
+ std::vector<ServiceProcessInfo> processes;
+ for (const auto& entry : processes_)
+ processes.push_back(entry.second);
+ return processes;
+ }
+
+ private:
+ void NotifyLaunchOnUIThread(const content::ServiceProcessInfo& info) {
+ for (auto& observer : observers_)
+ observer.OnServiceProcessLaunched(info);
+ }
+
+ void NotifyTerminatedOnUIThread(const content::ServiceProcessInfo& info) {
+ for (auto& observer : observers_)
+ observer.OnServiceProcessTerminatedNormally(info);
+ }
+
+ void NotifyCrashedOnUIThread(const content::ServiceProcessInfo& info) {
+ for (auto& observer : observers_)
+ observer.OnServiceProcessCrashed(info);
+ }
+
+ ServiceProcessId GenerateNextId() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ auto id = next_id_;
+ next_id_ = ServiceProcessId::FromUnsafeValue(next_id_.GetUnsafeValue() + 1);
+ return id;
+ }
+
+ const scoped_refptr<base::TaskRunner> ui_task_runner_;
+ ServiceProcessId next_id_{1};
+
+ base::Lock processes_lock_;
+ std::map<ServiceProcessId, ServiceProcessInfo> processes_;
+
+ // Observers are owned and used exclusively on the UI thread.
+ base::ObserverList<ServiceProcessHost::Observer> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceProcessTracker);
+};
+
+ServiceProcessTracker& GetServiceProcessTracker() {
+ static base::NoDestructor<ServiceProcessTracker> tracker;
+ return *tracker;
+}
+
+// Helper to bridge UtilityProcessHost IO thread events to the
+// ServiceProcessTracker. Every UtilityProcessHost created for a service process
+// has a unique instance of this class associated with it.
+class UtilityProcessClient : public UtilityProcessHost::Client {
+ public:
+ explicit UtilityProcessClient(const std::string& service_interface_name)
+ : service_interface_name_(service_interface_name) {}
+ ~UtilityProcessClient() override = default;
+
+ // UtilityProcessHost::Client:
+ void OnProcessLaunched(const base::Process& process) override {
+ process_info_ =
+ GetServiceProcessTracker().AddProcess(process, service_interface_name_);
+ }
+
+ void OnProcessTerminatedNormally() override {
+ GetServiceProcessTracker().NotifyTerminated(
+ process_info_.service_process_id);
+ }
+
+ void OnProcessCrashed() override {
+ GetServiceProcessTracker().NotifyCrashed(process_info_.service_process_id);
+ }
+
+ private:
+ const std::string service_interface_name_;
+ ServiceProcessInfo process_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(UtilityProcessClient);
+};
+
+// TODO(crbug.com/977637): Once UtilityProcessHost is used only by service
+// processes, its logic can be inlined here.
+void LaunchServiceProcessOnIOThread(mojo::GenericPendingReceiver receiver,
+ ServiceProcessHost::Options options) {
+ UtilityProcessHost* host = new UtilityProcessHost(
+ std::make_unique<UtilityProcessClient>(*receiver.interface_name()));
+ host->SetName(!options.display_name.empty()
+ ? options.display_name
+ : base::UTF8ToUTF16(*receiver.interface_name()));
+ host->SetMetricsName(*receiver.interface_name());
+ host->SetSandboxType(options.sandbox_type);
+ host->SetExtraCommandLineSwitches(std::move(options.extra_switches));
+ if (options.child_flags)
+ host->set_child_flags(*options.child_flags);
+ host->Start();
+ host->GetChildProcess()->BindServiceInterface(std::move(receiver));
+}
+
+} // namespace
+
+// static
+std::vector<ServiceProcessInfo> ServiceProcessHost::GetRunningProcessInfo() {
+ return GetServiceProcessTracker().GetProcesses();
+}
+
+// static
+void ServiceProcessHost::AddObserver(Observer* observer) {
+ GetServiceProcessTracker().AddObserver(observer);
+}
+
+// static
+void ServiceProcessHost::RemoveObserver(Observer* observer) {
+ GetServiceProcessTracker().RemoveObserver(observer);
+}
+
+// static
+void ServiceProcessHost::Launch(mojo::GenericPendingReceiver receiver,
+ Options options) {
+ DCHECK(receiver.interface_name().has_value());
+ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(&LaunchServiceProcessOnIOThread,
+ std::move(receiver), std::move(options)));
+}
+
+} // namespace content