blob: 641156f49586d0ceaadc7c7f663f66b5e94ccb18 [file] [log] [blame]
// Copyright 2016 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 "chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/numerics/safe_conversions.h"
#include "base/task_scheduler/task_scheduler.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/task_scheduler_internals_resources.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace {
std::unique_ptr<base::Value> SnapshotHistogramToValue(
const base::HistogramBase* histogram) {
std::unique_ptr<base::ListValue> values = std::make_unique<base::ListValue>();
std::unique_ptr<base::HistogramSamples> samples =
histogram->SnapshotSamples();
std::unique_ptr<base::SampleCountIterator> iterator = samples->Iterator();
while (!iterator->Done()) {
base::HistogramBase::Sample min;
int64_t max;
base::HistogramBase::Count count;
iterator->Get(&min, &max, &count);
std::unique_ptr<base::DictionaryValue> bucket =
std::make_unique<base::DictionaryValue>();
bucket->SetInteger("min", min);
// Note: DictionaryValue does not support 64-bit integer values. The checked
// cast below is OK in this case because none of the histograms passed to
// this function should be logging MaxInt32 as a sparse histogram bucket,
// which is the only case max will exceed 32-bit range.
bucket->SetInteger("max", base::checked_cast<int>(max));
bucket->SetInteger("count", count);
values->Append(std::move(bucket));
iterator->Next();
}
return std::move(values);
}
class TaskSchedulerDataHandler : public content::WebUIMessageHandler {
public:
TaskSchedulerDataHandler() = default;
// content::WebUIMessageHandler:
void RegisterMessages() override {
web_ui()->RegisterMessageCallback(
"getTaskSchedulerData",
base::BindRepeating(&TaskSchedulerDataHandler::GetTaskSchedulerData,
base::Unretained(this)));
}
private:
void GetTaskSchedulerData(const base::ListValue*) {
base::DictionaryValue data;
base::TaskScheduler* task_scheduler = base::TaskScheduler::GetInstance();
data.SetBoolean("instantiated", !!task_scheduler);
if (task_scheduler) {
std::unique_ptr<base::ListValue> histogram_value =
std::make_unique<base::ListValue>();
std::vector<const base::HistogramBase*> histograms =
task_scheduler->GetHistograms();
for (const base::HistogramBase* const histogram : histograms) {
std::unique_ptr<base::DictionaryValue> buckets =
std::make_unique<base::DictionaryValue>();
buckets->SetString("name", histogram->histogram_name());
buckets->Set("buckets", SnapshotHistogramToValue(histogram));
histogram_value->Append(std::move(buckets));
}
data.Set("histograms", std::move(histogram_value));
}
AllowJavascript();
CallJavascriptFunction(
"TaskSchedulerInternals.onGetTaskSchedulerData", data);
}
DISALLOW_COPY_AND_ASSIGN(TaskSchedulerDataHandler);
};
} // namespace
TaskSchedulerInternalsUI::TaskSchedulerInternalsUI(content::WebUI* web_ui)
: content::WebUIController(web_ui) {
web_ui->AddMessageHandler(std::make_unique<TaskSchedulerDataHandler>());
content::WebUIDataSource* html_source =
content::WebUIDataSource::Create(
chrome::kChromeUITaskSchedulerInternalsHost);
html_source->AddResourcePath(
"index.css", IDR_TASK_SCHEDULER_INTERNALS_RESOURCES_INDEX_CSS);
html_source->AddResourcePath(
"index.js", IDR_TASK_SCHEDULER_INTERNALS_RESOURCES_INDEX_JS);
html_source->SetDefaultResource(
IDR_TASK_SCHEDULER_INTERNALS_RESOURCES_INDEX_HTML);
html_source->UseGzip();
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source);
}
TaskSchedulerInternalsUI::~TaskSchedulerInternalsUI() = default;