Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / power / freezer_cgroup_process_manager.cc
blobaa412a9fef8dca2f5f279717bb1f75710d5f9975
1 // Copyright 2014 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/chromeos/power/freezer_cgroup_process_manager.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/files/file_util.h"
12 #include "base/logging.h"
13 #include "base/sequenced_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "content/public/browser/browser_thread.h"
17 namespace chromeos {
19 namespace {
20 const char kFreezerPath[] = "/sys/fs/cgroup/freezer/chrome_renderers";
21 const char kToBeFrozen[] = "to_be_frozen";
22 const char kFreezerState[] = "freezer.state";
23 const char kCgroupProcs[] = "cgroup.procs";
25 const char kFreezeCommand[] = "FROZEN";
26 const char kThawCommand[] = "THAWED";
28 } // namespace
30 class FreezerCgroupProcessManager::FileWorker {
31 public:
32 // Called on UI thread.
33 explicit FileWorker(scoped_refptr<base::SequencedTaskRunner> file_thread)
34 : ui_thread_(content::BrowserThread::GetMessageLoopProxyForThread(
35 content::BrowserThread::UI)),
36 file_thread_(file_thread) {
37 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
40 // Called on FILE thread.
41 virtual ~FileWorker() { DCHECK(file_thread_->RunsTasksOnCurrentThread()); }
43 void Start() {
44 DCHECK(file_thread_->RunsTasksOnCurrentThread());
46 default_control_path_ = base::FilePath(kFreezerPath).Append(kCgroupProcs);
47 to_be_frozen_control_path_ = base::FilePath(kFreezerPath)
48 .AppendASCII(kToBeFrozen)
49 .AppendASCII(kCgroupProcs);
50 to_be_frozen_state_path_ = base::FilePath(kFreezerPath)
51 .AppendASCII(kToBeFrozen)
52 .AppendASCII(kFreezerState);
53 enabled_ = base::PathIsWritable(default_control_path_) &&
54 base::PathIsWritable(to_be_frozen_control_path_) &&
55 base::PathIsWritable(to_be_frozen_state_path_);
57 if (!enabled_) {
58 LOG(WARNING) << "Cgroup freezer does not exist or is not writable. "
59 << "Unable to freeze renderer processes.";
63 void SetShouldFreezeRenderer(base::ProcessHandle handle, bool frozen) {
64 DCHECK(file_thread_->RunsTasksOnCurrentThread());
66 WriteCommandToFile(base::IntToString(handle),
67 frozen ? to_be_frozen_control_path_
68 : default_control_path_);
71 void FreezeRenderers() {
72 DCHECK(file_thread_->RunsTasksOnCurrentThread());
74 if (!enabled_) {
75 LOG(ERROR) << "Attempting to freeze renderers when the freezer cgroup is "
76 << "not available.";
77 return;
80 WriteCommandToFile(kFreezeCommand, to_be_frozen_state_path_);
83 void ThawRenderers(ResultCallback callback) {
84 DCHECK(file_thread_->RunsTasksOnCurrentThread());
86 if (!enabled_) {
87 LOG(ERROR) << "Attempting to thaw renderers when the freezer cgroup is "
88 << "not available.";
89 return;
92 bool result = WriteCommandToFile(kThawCommand, to_be_frozen_state_path_);
93 ui_thread_->PostTask(FROM_HERE, base::Bind(callback, result));
96 void CheckCanFreezeRenderers(ResultCallback callback) {
97 DCHECK(file_thread_->RunsTasksOnCurrentThread());
99 ui_thread_->PostTask(FROM_HERE, base::Bind(callback, enabled_));
102 private:
103 bool WriteCommandToFile(const std::string& command,
104 const base::FilePath& file) {
105 int bytes = base::WriteFile(file, command.c_str(), command.size());
106 if (bytes == -1) {
107 PLOG(ERROR) << "Writing " << command << " to " << file.value()
108 << " failed";
109 return false;
110 } else if (bytes != static_cast<int>(command.size())) {
111 LOG(ERROR) << "Only wrote " << bytes << " byte(s) when writing "
112 << command << " to " << file.value();
113 return false;
115 return true;
118 scoped_refptr<base::SequencedTaskRunner> ui_thread_;
119 scoped_refptr<base::SequencedTaskRunner> file_thread_;
121 // Control path for the cgroup that is not frozen.
122 base::FilePath default_control_path_;
124 // Control and state paths for the cgroup whose processes will be frozen.
125 base::FilePath to_be_frozen_control_path_;
126 base::FilePath to_be_frozen_state_path_;
128 bool enabled_;
130 DISALLOW_COPY_AND_ASSIGN(FileWorker);
133 FreezerCgroupProcessManager::FreezerCgroupProcessManager()
134 : file_thread_(content::BrowserThread::GetMessageLoopProxyForThread(
135 content::BrowserThread::FILE)),
136 file_worker_(new FileWorker(file_thread_)) {
137 file_thread_->PostTask(FROM_HERE,
138 base::Bind(&FileWorker::Start,
139 base::Unretained(file_worker_.get())));
142 FreezerCgroupProcessManager::~FreezerCgroupProcessManager() {
143 file_thread_->DeleteSoon(FROM_HERE, file_worker_.release());
146 void FreezerCgroupProcessManager::SetShouldFreezeRenderer(
147 base::ProcessHandle handle,
148 bool frozen) {
149 file_thread_->PostTask(FROM_HERE,
150 base::Bind(&FileWorker::SetShouldFreezeRenderer,
151 base::Unretained(file_worker_.get()),
152 handle, frozen));
155 void FreezerCgroupProcessManager::FreezeRenderers() {
156 file_thread_->PostTask(FROM_HERE,
157 base::Bind(&FileWorker::FreezeRenderers,
158 base::Unretained(file_worker_.get())));
161 void FreezerCgroupProcessManager::ThawRenderers(ResultCallback callback) {
162 file_thread_->PostTask(FROM_HERE,
163 base::Bind(&FileWorker::ThawRenderers,
164 base::Unretained(file_worker_.get()),
165 callback));
168 void FreezerCgroupProcessManager::CheckCanFreezeRenderers(
169 ResultCallback callback) {
170 file_thread_->PostTask(FROM_HERE,
171 base::Bind(&FileWorker::CheckCanFreezeRenderers,
172 base::Unretained(file_worker_.get()),
173 callback));
176 } // namespace chromeos