
The methodology used to generate this CL is documented in https://crbug.com/1098010#c34. No-Try: true No-Presubmit: true Bug: 1098010 Change-Id: I8c0f009d16350271f07d8e5e561085822cc9dd27 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3895935 Owners-Override: Avi Drissman <avi@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Mark Mentovai <mark@chromium.org> Auto-Submit: Avi Drissman <avi@chromium.org> Cr-Commit-Position: refs/heads/main@{#1047456}
197 lines
7.2 KiB
C++
197 lines
7.2 KiB
C++
// Copyright 2019 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "content/renderer/browser_exposed_renderer_interfaces.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "base/bind.h"
|
|
#include "base/feature_list.h"
|
|
#include "base/memory/scoped_refptr.h"
|
|
#include "base/memory/weak_ptr.h"
|
|
#include "base/task/task_runner.h"
|
|
#include "base/task/thread_pool.h"
|
|
#include "base/threading/thread_task_runner_handle.h"
|
|
#include "base/time/time.h"
|
|
#include "build/build_config.h"
|
|
#include "content/common/frame.mojom.h"
|
|
#include "content/public/common/content_client.h"
|
|
#include "content/public/common/resource_usage_reporter.mojom.h"
|
|
#include "content/public/common/resource_usage_reporter_type_converters.h"
|
|
#include "content/public/renderer/content_renderer_client.h"
|
|
#include "content/renderer/render_thread_impl.h"
|
|
#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
|
|
#include "content/renderer/worker/shared_worker_factory_impl.h"
|
|
#include "content/services/auction_worklet/auction_worklet_service_impl.h"
|
|
#include "mojo/public/cpp/bindings/binder_map.h"
|
|
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
|
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
|
#include "v8/include/v8-isolate.h"
|
|
#include "v8/include/v8-statistics.h"
|
|
|
|
namespace content {
|
|
|
|
namespace {
|
|
|
|
constexpr int kWaitForWorkersStatsTimeoutMS = 20;
|
|
|
|
class ResourceUsageReporterImpl : public content::mojom::ResourceUsageReporter {
|
|
public:
|
|
explicit ResourceUsageReporterImpl(base::WeakPtr<RenderThread> thread)
|
|
: thread_(std::move(thread)) {}
|
|
ResourceUsageReporterImpl(const ResourceUsageReporterImpl&) = delete;
|
|
~ResourceUsageReporterImpl() override = default;
|
|
|
|
ResourceUsageReporterImpl& operator=(const ResourceUsageReporterImpl&) =
|
|
delete;
|
|
|
|
private:
|
|
static void CollectOnWorkerThread(
|
|
const scoped_refptr<base::TaskRunner>& master,
|
|
base::WeakPtr<ResourceUsageReporterImpl> impl) {
|
|
size_t total_bytes = 0;
|
|
size_t used_bytes = 0;
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
|
if (isolate) {
|
|
v8::HeapStatistics heap_stats;
|
|
isolate->GetHeapStatistics(&heap_stats);
|
|
total_bytes = heap_stats.total_heap_size();
|
|
used_bytes = heap_stats.used_heap_size();
|
|
}
|
|
master->PostTask(FROM_HERE,
|
|
base::BindOnce(&ResourceUsageReporterImpl::ReceiveStats,
|
|
impl, total_bytes, used_bytes));
|
|
}
|
|
|
|
void ReceiveStats(size_t total_bytes, size_t used_bytes) {
|
|
usage_data_->v8_bytes_allocated += total_bytes;
|
|
usage_data_->v8_bytes_used += used_bytes;
|
|
workers_to_go_--;
|
|
if (!workers_to_go_)
|
|
SendResults();
|
|
}
|
|
|
|
void SendResults() {
|
|
if (!callback_.is_null())
|
|
std::move(callback_).Run(std::move(usage_data_));
|
|
callback_.Reset();
|
|
weak_factory_.InvalidateWeakPtrs();
|
|
workers_to_go_ = 0;
|
|
}
|
|
|
|
void GetUsageData(GetUsageDataCallback callback) override {
|
|
DCHECK(callback_.is_null());
|
|
weak_factory_.InvalidateWeakPtrs();
|
|
usage_data_ = mojom::ResourceUsageData::New();
|
|
usage_data_->reports_v8_stats = true;
|
|
callback_ = std::move(callback);
|
|
|
|
// Since it is not safe to call any Blink or V8 functions until Blink has
|
|
// been initialized (which also initializes V8), early out and send 0 back
|
|
// for all resources.
|
|
if (!thread_) {
|
|
SendResults();
|
|
return;
|
|
}
|
|
|
|
blink::WebCacheResourceTypeStats stats;
|
|
blink::WebCache::GetResourceTypeStats(&stats);
|
|
usage_data_->web_cache_stats = mojom::ResourceTypeStats::From(stats);
|
|
|
|
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
|
if (isolate) {
|
|
v8::HeapStatistics heap_stats;
|
|
isolate->GetHeapStatistics(&heap_stats);
|
|
usage_data_->v8_bytes_allocated = heap_stats.total_heap_size();
|
|
usage_data_->v8_bytes_used = heap_stats.used_heap_size();
|
|
}
|
|
base::RepeatingClosure collect = base::BindRepeating(
|
|
&ResourceUsageReporterImpl::CollectOnWorkerThread,
|
|
base::ThreadTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr());
|
|
workers_to_go_ =
|
|
RenderThread::Get()->PostTaskToAllWebWorkers(std::move(collect));
|
|
if (workers_to_go_) {
|
|
// The guard task to send out partial stats
|
|
// in case some workers are not responsive.
|
|
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
|
FROM_HERE,
|
|
base::BindOnce(&ResourceUsageReporterImpl::SendResults,
|
|
weak_factory_.GetWeakPtr()),
|
|
base::Milliseconds(kWaitForWorkersStatsTimeoutMS));
|
|
} else {
|
|
// No worker threads so just send out the main thread data right away.
|
|
SendResults();
|
|
}
|
|
}
|
|
|
|
const base::WeakPtr<RenderThread> thread_;
|
|
mojom::ResourceUsageDataPtr usage_data_;
|
|
GetUsageDataCallback callback_;
|
|
int workers_to_go_ = 0;
|
|
|
|
base::WeakPtrFactory<ResourceUsageReporterImpl> weak_factory_{this};
|
|
};
|
|
|
|
void CreateResourceUsageReporter(
|
|
base::WeakPtr<RenderThreadImpl> render_thread,
|
|
mojo::PendingReceiver<mojom::ResourceUsageReporter> receiver) {
|
|
mojo::MakeSelfOwnedReceiver(
|
|
std::make_unique<ResourceUsageReporterImpl>(std::move(render_thread)),
|
|
std::move(receiver));
|
|
}
|
|
|
|
void CreateEmbeddedWorker(
|
|
scoped_refptr<base::SingleThreadTaskRunner> initiator_task_runner,
|
|
base::WeakPtr<RenderThreadImpl> render_thread,
|
|
mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient>
|
|
receiver) {
|
|
initiator_task_runner->PostTask(
|
|
FROM_HERE, base::BindOnce(&EmbeddedWorkerInstanceClientImpl::Create,
|
|
initiator_task_runner,
|
|
render_thread->cors_exempt_header_list(),
|
|
std::move(receiver)));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void ExposeRendererInterfacesToBrowser(
|
|
base::WeakPtr<RenderThreadImpl> render_thread,
|
|
mojo::BinderMap* binders) {
|
|
DCHECK(render_thread);
|
|
|
|
binders->Add<blink::mojom::SharedWorkerFactory>(
|
|
base::BindRepeating(&SharedWorkerFactoryImpl::Create),
|
|
base::ThreadTaskRunnerHandle::Get());
|
|
binders->Add<mojom::ResourceUsageReporter>(
|
|
base::BindRepeating(&CreateResourceUsageReporter, render_thread),
|
|
base::ThreadTaskRunnerHandle::Get());
|
|
#if BUILDFLAG(IS_ANDROID)
|
|
binders->Add<auction_worklet::mojom::AuctionWorkletService>(
|
|
base::BindRepeating(
|
|
&auction_worklet::AuctionWorkletServiceImpl::CreateForRenderer),
|
|
base::ThreadTaskRunnerHandle::Get());
|
|
#endif
|
|
|
|
auto task_runner_for_service_worker_startup =
|
|
base::ThreadPool::CreateSingleThreadTaskRunner(
|
|
{base::MayBlock(), base::TaskPriority::USER_BLOCKING,
|
|
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
|
|
// TODO(crbug.com/1186912): Bind on `task_runner_for_service_worker_startup`
|
|
// instead of the main thread, so startup isn't blocked on the main thread.
|
|
// Currently it's on the main thread as CreateEmbeddedWorker accesses
|
|
// `cors_exempt_header_list` from `render_thread`.
|
|
binders->Add<blink::mojom::EmbeddedWorkerInstanceClient>(
|
|
base::BindRepeating(&CreateEmbeddedWorker,
|
|
task_runner_for_service_worker_startup,
|
|
render_thread),
|
|
base::ThreadTaskRunnerHandle::Get());
|
|
|
|
GetContentClient()->renderer()->ExposeInterfacesToBrowser(binders);
|
|
}
|
|
|
|
} // namespace content
|