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
|
// Copyright 2024 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/windows_services/elevated_tracing_service/elevated_tracing_service_delegate.h"
#include <wrl/client.h>
#include <wrl/implements.h>
#include <wrl/module.h>
#include <utility>
#include "base/command_line.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "chrome/common/win/eventlog_messages.h"
#include "chrome/install_static/install_util.h"
#include "chrome/windows_services/elevated_tracing_service/session_registry.h"
#include "chrome/windows_services/elevated_tracing_service/system_tracing_session.h"
#include "mojo/core/embedder/embedder.h"
#include "services/tracing/public/cpp/trace_startup.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
namespace elevated_tracing_service {
namespace {
// A class factory for SystemTracingSession.
class SystemTracingSessionClassFactory : public Microsoft::WRL::ClassFactory<> {
public:
SystemTracingSessionClassFactory() = default;
SystemTracingSessionClassFactory(const SystemTracingSessionClassFactory&) =
delete;
SystemTracingSessionClassFactory& operator=(
const SystemTracingSessionClassFactory&) = delete;
// Sets the task runner to be used for general main-thread processing.
void set_task_runner(scoped_refptr<base::SequencedTaskRunner> task_runner) {
task_runner_ = std::move(task_runner);
}
// IClassFactory:
IFACEMETHODIMP CreateInstance(IUnknown* pUnkOuter,
REFIID riid,
void** ppvObject) override {
// Bump the object count for the duration of this call and reduce it upon
// exit to ensure that the service terminates if the factory fails to
// produce an instance and there is no pre-existing instance.
auto& module =
Microsoft::WRL::Module<Microsoft::WRL::OutOfProc>::GetModule();
module.IncrementObjectCount();
absl::Cleanup count_decrementer = [&module] {
module.DecrementObjectCount();
};
*ppvObject = nullptr;
if (pUnkOuter != nullptr) {
return CLASS_E_NOAGGREGATION;
}
Microsoft::WRL::ComPtr<IUnknown> unknown;
HRESULT hr = Microsoft::WRL::MakeAndInitialize<SystemTracingSession>(
&unknown, task_runner_);
return SUCCEEDED(hr) ? unknown.CopyTo(riid, ppvObject) : hr;
}
private:
// The task runner to be used for general main-thread processing.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
};
} // namespace
Delegate::Delegate() = default;
Delegate::~Delegate() = default;
uint16_t Delegate::GetLogEventCategory() {
return TRACING_SERVICE_CATEGORY;
}
uint32_t Delegate::GetLogEventMessageId() {
return MSG_TRACING_SERVICE_LOG_MESSAGE;
}
base::expected<base::HeapArray<FactoryAndClsid>, HRESULT>
Delegate::CreateClassFactories() {
unsigned int flags = Microsoft::WRL::ModuleType::OutOfProc;
auto result = base::HeapArray<FactoryAndClsid>::WithSize(1);
Microsoft::WRL::ComPtr<IUnknown> unknown;
HRESULT hr = Microsoft::WRL::Details::CreateClassFactory<
SystemTracingSessionClassFactory>(&flags, nullptr,
__uuidof(IClassFactory), &unknown);
if (SUCCEEDED(hr)) {
hr = unknown.As(&result[0].factory);
// CreateClassFactory doesn't support passing arguments while constructing
// the factory, so pass a task runner to be the "main" runner to the factory
// ex post facto.
static_cast<SystemTracingSessionClassFactory*>(result[0].factory.Get())
->set_task_runner(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock{}}));
}
if (FAILED(hr)) {
return base::unexpected(hr);
}
result[0].clsid = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSystemTracingClsIdForTestingSwitch)
? kTestSystemTracingSessionClsid
: install_static::GetTracingServiceClsid();
return base::ok(std::move(result));
}
bool Delegate::PreRun() {
// Initialize mojo and run an IPC thread.
mojo::core::Init();
ipc_thread_.StartWithOptions(
base::Thread::Options(base::MessagePumpType::IO, 0));
ipc_support_.emplace(ipc_thread_.task_runner(),
mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST);
// Run a ThreadPool.
base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
"elevated_tracing_service");
// Initialize tracing in the process.
tracing::InitTracingPostFeatureList(/*enable_consumer=*/false);
// Create the global SessionRegistry.
session_registry_ = base::MakeRefCounted<SessionRegistry>();
return false; // This delegate does not implement `Run()`.
}
void Delegate::PostRun() {
base::ThreadPoolInstance::Get()->Shutdown();
// Destroy the global SessionRegistry.
session_registry_.reset();
}
} // namespace elevated_tracing_service
|