[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / chrome / browser / caps / generate_state_json.cc
blob3857d27a2477be44095046ace8f8f744ea82f562
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/caps/generate_state_json.h"
7 #include <string>
8 #include <utility>
10 #include "base/bind.h"
11 #include "base/cpu.h"
12 #include "base/files/file.h"
13 #include "base/json/json_writer.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/sys_info.h"
19 #include "base/threading/thread_restrictions.h"
20 #include "base/time/time.h"
21 #include "base/values.h"
22 #include "chrome/browser/task_manager/task_manager.h"
24 namespace {
26 std::string Key(base::ProcessId pid, const char* category) {
27 return category ?
28 base::StringPrintf("process.%d.%s", pid, category) :
29 base::StringPrintf("process.%d", pid);
32 using MemoryFn1 = bool (TaskManagerModel::*)(
33 int index, size_t* result1) const;
34 using MemoryFn2 = bool (TaskManagerModel::*)(
35 int index, size_t* result1, bool*) const;
37 int InMBFromB(size_t result_in_bytes) {
38 return static_cast<int>(result_in_bytes / (1024 * 1024));
41 int InMBFromB(const TaskManagerModel* model, MemoryFn1 mfn, int index) {
42 size_t result_in_bytes = 0;
43 bool res = (model->*mfn)(index, &result_in_bytes);
44 return res ? InMBFromB(result_in_bytes) : 0;
47 int InMBFromB(const TaskManagerModel* model, MemoryFn2 mfn, int index) {
48 size_t result_in_bytes = 0;
49 bool ignored;
50 bool res = (model->*mfn)(index, &result_in_bytes, &ignored);
51 return res ? InMBFromB(result_in_bytes) : 0;
54 class TaskManagerDataDumper :
55 public base::RefCountedThreadSafe<TaskManagerDataDumper> {
56 public:
57 TaskManagerDataDumper(scoped_refptr<TaskManagerModel> model,
58 base::File file)
59 : model_(model), file_(file.Pass()) {
60 model_->RegisterOnDataReadyCallback(
61 base::Bind(&TaskManagerDataDumper::OnDataReady, this));
62 model->StartListening();
63 // Note that GenerateStateJSON 'new's this object which is reference
64 // counted.
65 AddRef();
68 private:
69 friend class base::RefCountedThreadSafe<TaskManagerDataDumper>;
70 ~TaskManagerDataDumper() {
73 void OnDataReady() {
74 // Some data (for example V8 memory) has not yet arrived, so we wait.
75 // TODO(cpu): Figure out how to make this reliable.
76 static base::TimeDelta delay = base::TimeDelta::FromMilliseconds(250);
77 base::MessageLoop::current()->PostDelayedTask(
78 FROM_HERE,
79 base::Bind(&TaskManagerDataDumper::OnDataReadyDelayed, this),
80 delay);
83 void OnDataReadyDelayed() {
84 model_->StopListening();
85 // Task manager finally computed (most) values. Lets generate the JSON
86 // data and send it over the pipe.
87 base::DictionaryValue dict;
88 GatherComputerValues(&dict);
89 GatherChromeValues(&dict);
91 std::string json;
92 auto options = base::JSONWriter::OPTIONS_PRETTY_PRINT;
93 if (!base::JSONWriter::WriteWithOptions(&dict, options, &json))
94 return;
96 file_.WriteAtCurrentPos(json.c_str(), json.size());
97 file_.Close();
98 // this Release() causes our destruction.
99 Release();
102 private:
103 // TODO(cpu): split the key names below into a separate header that both
104 // caps and chrome can use.
106 void GatherComputerValues(base::DictionaryValue* dict) {
107 base::CPU cpu;
108 dict->SetInteger("system.cpu.type", cpu.type());
109 dict->SetInteger("system.cpu.family", cpu.family());
110 dict->SetInteger("system.cpu.model", cpu.model());
111 dict->SetInteger("system.cpu.stepping", cpu.stepping());
112 dict->SetString("system.cpu.brand", cpu.cpu_brand());
113 dict->SetInteger("system.cpu.logicalprocessors",
114 base::SysInfo::NumberOfProcessors());
115 dict->SetInteger("system.cpu.logicalprocessors",
116 base::SysInfo::NumberOfProcessors());
117 int64 memory = base::SysInfo::AmountOfPhysicalMemory();
118 dict->SetInteger("system.memory.physical", InMBFromB(memory));
119 memory = base::SysInfo::AmountOfAvailablePhysicalMemory();
120 dict->SetInteger("system.memory.available", InMBFromB(memory));
121 dict->SetInteger("system.uptime", base::SysInfo::Uptime() / 1000 );
122 dict->SetString("os.name", base::SysInfo::OperatingSystemName());
123 #if !defined(OS_LINUX)
124 int32 major, minor, bugfix;
125 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
126 dict->SetInteger("os.version.major", major);
127 dict->SetInteger("os.version.minor", minor);
128 dict->SetInteger("os.version.bugfix", bugfix);
129 dict->SetString("os.arch", base::SysInfo::OperatingSystemArchitecture());
130 #endif
133 void GatherChromeValues(base::DictionaryValue* dict) {
134 for (int index = 0; index != model_->ResourceCount(); ++index) {
135 auto pid = model_->GetProcessId(index);
136 auto tabs_key = Key(pid, "tabs");
137 base::ListValue* tabs;
138 if (!dict->GetList(tabs_key, &tabs)) {
139 tabs = new base::ListValue;
140 dict->Set(tabs_key, tabs);
141 tabs->AppendString(model_->GetResourceTitle(index));
143 dict->SetInteger(Key(pid, "memory.physical"),
144 InMBFromB(model_.get(),
145 &TaskManagerModel::GetPhysicalMemory, index));
146 dict->SetInteger(Key(pid, "memory.private"),
147 InMBFromB(model_.get(),
148 &TaskManagerModel::GetPrivateMemory, index));
149 dict->SetInteger(Key(pid, "memory.shared"),
150 InMBFromB(model_.get(),
151 &TaskManagerModel::GetSharedMemory, index));
152 dict->SetInteger(Key(pid, "memory.video"),
153 InMBFromB(model_.get(),
154 &TaskManagerModel::GetVideoMemory, index));
155 dict->SetInteger(Key(pid, "memory.V8.total"),
156 InMBFromB(model_.get(),
157 &TaskManagerModel::GetV8Memory, index));
158 dict->SetInteger(Key(pid, "memory.V8.used"),
159 InMBFromB(model_.get(),
160 &TaskManagerModel::GetV8MemoryUsed, index));
161 dict->SetInteger(Key(pid, "memory.sqlite"),
162 InMBFromB(model_.get(),
163 &TaskManagerModel::GetSqliteMemoryUsedBytes, index));
164 dict->SetString(Key(pid, "uptime"),
165 ProcessUptime(model_->GetProcess(index)));
166 } else {
167 // TODO(cpu): Probably best to write the MD5 hash of the title.
168 tabs->AppendString(model_->GetResourceTitle(index));
173 std::string ProcessUptime(base::ProcessHandle process) {
174 #if defined(OS_WIN)
175 FILETIME creation_time;
176 FILETIME exit_time;
177 FILETIME kernel_time;
178 FILETIME user_time;
180 if (!GetProcessTimes(process, &creation_time, &exit_time,
181 &kernel_time, &user_time))
182 return std::string("~");
184 auto ct_delta = base::Time::Now() - base::Time::FromFileTime(creation_time);
185 return base::StringPrintf("%lld", ct_delta.InSeconds());
186 #else
187 return std::string();
188 #endif
191 scoped_refptr<TaskManagerModel> model_;
192 base::File file_;
195 } // namespace
197 namespace caps {
199 void GenerateStateJSON(
200 scoped_refptr<TaskManagerModel> model, base::File file) {
201 new TaskManagerDataDumper(model, file.Pass());