Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(585)

Side by Side Diff: components/net_log/net_log_file_writer.cc

Issue 2603523002: Move net-export thread-hopping code into NetLogFileWriter and add IO polled data. (Closed)
Patch Set: Various refactors to make code cleaner Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/net_log/net_log_file_writer.h" 5 #include "components/net_log/net_log_file_writer.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h"
10 #include "base/callback.h"
9 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
10 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
11 #include "base/files/scoped_file.h" 13 #include "base/files/scoped_file.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/task_runner_util.h"
12 #include "base/values.h" 16 #include "base/values.h"
13 #include "build/build_config.h" 17 #include "build/build_config.h"
14 #include "components/net_log/chrome_net_log.h" 18 #include "components/net_log/chrome_net_log.h"
15 #include "net/log/write_to_file_net_log_observer.h" 19 #include "net/log/file_net_log_observer.h"
20 #include "net/log/net_log_util.h"
21 #include "net/url_request/url_request_context_getter.h"
16 22
17 namespace net_log { 23 namespace net_log {
18 24
19 // Path of logs if relative to default temporary directory of 25 // Path of logs if relative to default temporary directory of
20 // base::GetTempDir(). Must be kept in sync with 26 // base::GetTempDir(). Must be kept in sync with
21 // chrome/android/java/res/xml/file_paths.xml. Only used if 27 // chrome/android/java/res/xml/file_paths.xml. Only used if
22 // not saving log file to a custom path. 28 // not saving log file to a custom path.
23 base::FilePath::CharType kLogRelativePath[] = 29 base::FilePath::CharType kLogRelativePath[] =
24 FILE_PATH_LITERAL("net-export/chrome-net-export-log.json"); 30 FILE_PATH_LITERAL("net-export/chrome-net-export-log.json");
25 31
26 // Old path used by net-export. Used to delete old files. 32 // Old path used by net-export. Used to delete old files.
27 // TODO(mmenke): Should remove at some point. Added in M46. 33 // TODO(mmenke): Should remove at some point. Added in M46.
28 base::FilePath::CharType kOldLogRelativePath[] = 34 base::FilePath::CharType kOldLogRelativePath[] =
29 FILE_PATH_LITERAL("chrome-net-export-log.json"); 35 FILE_PATH_LITERAL("chrome-net-export-log.json");
30 36
31 NetLogFileWriter::~NetLogFileWriter() { 37 NetLogFileWriter::~NetLogFileWriter() {
32 if (write_to_file_observer_) 38 if (write_to_file_observer_)
33 write_to_file_observer_->StopObserving(nullptr); 39 write_to_file_observer_->StopObserving(nullptr, base::Bind([] {}));
34 } 40 }
35 41
36 void NetLogFileWriter::ProcessCommand(Command command) { 42 NetLogFileWriter::NetLogFileWriter(
43 ChromeNetLog* chrome_net_log,
44 const base::CommandLine::StringType& command_line_string,
45 const std::string& channel_string)
46 : state_(STATE_UNINITIALIZED),
47 log_exists_(false),
48 log_capture_mode_known_(false),
49 log_capture_mode_(net::NetLogCaptureMode::Default()),
50 chrome_net_log_(chrome_net_log),
51 command_line_string_(command_line_string),
52 channel_string_(channel_string),
53 weak_ptr_factory_(this) {
54 // NetLogFileWriter can be created on one thread and used on another.
55 thread_checker_.DetachFromThread();
eroman 2017/01/06 21:46:23 Is this necessary? I believe the creation and dest
wangyix1 2017/01/10 22:20:15 Done.
56 }
57
58 void NetLogFileWriter::StartNetLog(net::NetLogCaptureMode capture_mode,
59 StateCallback state_callback) {
37 DCHECK(thread_checker_.CalledOnValidThread()); 60 DCHECK(thread_checker_.CalledOnValidThread());
38 if (!EnsureInit()) 61 if (state_ == STATE_UNINITIALIZED) {
39 return; 62 InitAndCallback(
40 63 base::Bind(&NetLogFileWriter::StartLogging,
41 switch (command) { 64 weak_ptr_factory_.GetWeakPtr(), capture_mode,
42 case DO_START_LOG_BYTES: 65 state_callback));
43 StartNetLog(LOG_TYPE_LOG_BYTES); 66 } else if (state_ == STATE_NOT_LOGGING) {
44 break; 67 StartLogging(capture_mode, state_callback);
45 case DO_START:
46 StartNetLog(LOG_TYPE_NORMAL);
47 break;
48 case DO_START_STRIP_PRIVATE_DATA:
49 StartNetLog(LOG_TYPE_STRIP_PRIVATE_DATA);
50 break;
51 case DO_STOP:
52 StopNetLog();
53 break;
54 default:
55 NOTREACHED();
56 break;
57 } 68 }
58 } 69 }
59 70
60 bool NetLogFileWriter::GetFilePath(base::FilePath* path) { 71 void NetLogFileWriter::StartLogging(net::NetLogCaptureMode capture_mode,
72 StateCallback state_callback) {
61 DCHECK(thread_checker_.CalledOnValidThread()); 73 DCHECK(thread_checker_.CalledOnValidThread());
62 if (log_type_ == LOG_TYPE_NONE || state_ == STATE_LOGGING) 74 DCHECK(file_task_runner_);
63 return false;
64 75
65 if (!NetExportLogExists()) 76 DCHECK_EQ(STATE_NOT_LOGGING, state_);
66 return false; 77 DCHECK(!log_path_.empty());
67 78
68 DCHECK(!log_path_.empty()); 79 state_ = STATE_LOGGING;
69 #if defined(OS_POSIX) 80 log_exists_ = true;
70 // Users, group and others can read, write and traverse. 81 log_capture_mode_known_ = true;
71 int mode = base::FILE_PERMISSION_MASK; 82 log_capture_mode_ = capture_mode;
72 base::SetPosixFilePermissions(log_path_, mode);
73 #endif // defined(OS_POSIX)
74 83
75 *path = log_path_; 84 std::unique_ptr<base::Value> constants(
76 return true; 85 ChromeNetLog::GetConstants(command_line_string_, channel_string_));
86 write_to_file_observer_.reset(new net::FileNetLogObserver(file_task_runner_));
87 write_to_file_observer_->StartObservingUnbounded(chrome_net_log_,
eroman 2017/01/06 21:46:23 StartLogging() will eventually need to take a URLR
wangyix1 2017/01/10 22:20:15 Acknowledged.
88 capture_mode, log_path_, std::move(constants), nullptr);
89
90 RunStateCallback(state_callback);
91 }
92
93 void NetLogFileWriter::StopNetLog(
94 std::unique_ptr<base::DictionaryValue> polled_data,
95 scoped_refptr<net::URLRequestContextGetter> context_getter,
96 StateCallback state_callback) {
97 DCHECK(thread_checker_.CalledOnValidThread());
98 DCHECK(net_task_runner_);
99 DCHECK(context_getter);
100 if (state_ == STATE_LOGGING) {
101 base::PostTaskAndReplyWithResult(
102 net_task_runner_.get(), FROM_HERE,
103 base::Bind(&NetLogFileWriter::AddNetInfo, context_getter,
104 base::Passed(&polled_data)),
105 base::Bind(&NetLogFileWriter::StopLogging,
106 weak_ptr_factory_.GetWeakPtr(), state_callback));
107 }
108 }
109
110 std::unique_ptr<base::DictionaryValue> NetLogFileWriter::AddNetInfo(
111 scoped_refptr<net::URLRequestContextGetter> context_getter,
112 std::unique_ptr<base::DictionaryValue> polled_data) {
113 DCHECK(context_getter);
114 std::unique_ptr<base::DictionaryValue> net_info =
115 net::GetNetInfo(context_getter->GetURLRequestContext(),
116 net::NET_INFO_ALL_SOURCES);
117 if (polled_data)
118 net_info->MergeDictionary(polled_data.get());
119 return net_info;
120 }
121
122 void NetLogFileWriter::StopLogging(StateCallback state_callback,
123 std::unique_ptr<base::DictionaryValue> polled_data) {
124 DCHECK(thread_checker_.CalledOnValidThread());
125 DCHECK_EQ(STATE_LOGGING, state_);
eroman 2017/01/06 21:46:23 I don't think this DCHECK holds() -- Let's say Sto
wangyix1 2017/01/10 22:20:15 Done.
126 write_to_file_observer_->StopObserving(std::move(polled_data),
127 base::Bind([] {}));
eroman 2017/01/06 21:46:23 Shouldn't we wait for this to complete before repo
wangyix1 2017/01/10 22:20:15 Done.
128 write_to_file_observer_.reset();
129 state_ = STATE_NOT_LOGGING;
130
131 RunStateCallback(state_callback);
132 }
133
134 void NetLogFileWriter::GetState(StateCallback state_callback) {
135 DCHECK(thread_checker_.CalledOnValidThread());
136 if (state_ == STATE_UNINITIALIZED) {
137 InitAndCallback(base::Bind(&NetLogFileWriter::RunStateCallback,
138 weak_ptr_factory_.GetWeakPtr(), state_callback));
139 } else {
140 RunStateCallback(state_callback);
141 }
77 } 142 }
78 143
79 base::DictionaryValue* NetLogFileWriter::GetState() { 144 base::DictionaryValue* NetLogFileWriter::GetState() {
80 DCHECK(thread_checker_.CalledOnValidThread()); 145 DCHECK(thread_checker_.CalledOnValidThread());
81 base::DictionaryValue* dict = new base::DictionaryValue; 146 base::DictionaryValue* dict = new base::DictionaryValue;
82 147
83 EnsureInit();
84
85 #ifndef NDEBUG 148 #ifndef NDEBUG
86 dict->SetString("file", log_path_.LossyDisplayName()); 149 dict->SetString("file", log_path_.LossyDisplayName());
87 #endif // NDEBUG 150 #endif // NDEBUG
88 151
89 switch (state_) { 152 switch (state_) {
90 case STATE_NOT_LOGGING: 153 case STATE_NOT_LOGGING:
91 dict->SetString("state", "NOT_LOGGING"); 154 dict->SetString("state", "NOT_LOGGING");
92 break; 155 break;
93 case STATE_LOGGING: 156 case STATE_LOGGING:
94 dict->SetString("state", "LOGGING"); 157 dict->SetString("state", "LOGGING");
95 break; 158 break;
96 case STATE_UNINITIALIZED: 159 case STATE_UNINITIALIZED:
97 dict->SetString("state", "UNINITIALIZED"); 160 dict->SetString("state", "UNINITIALIZED");
98 break; 161 break;
99 } 162 }
100 163
101 switch (log_type_) { 164 dict->SetBoolean("logExists", log_exists_);
102 case LOG_TYPE_NONE: 165 dict->SetBoolean("logCaptureModeKnown", log_capture_mode_known_);
103 dict->SetString("logType", "NONE"); 166
104 break; 167 if (log_capture_mode_ == net::NetLogCaptureMode::Default())
105 case LOG_TYPE_UNKNOWN: 168 dict->SetString("captureMode", "STRIP_PRIVATE_DATA");
106 dict->SetString("logType", "UNKNOWN"); 169 else if (log_capture_mode_ ==
107 break; 170 net::NetLogCaptureMode::IncludeCookiesAndCredentials())
108 case LOG_TYPE_LOG_BYTES: 171 dict->SetString("captureMode", "NORMAL");
109 dict->SetString("logType", "LOG_BYTES"); 172 else if (log_capture_mode_ == net::NetLogCaptureMode::IncludeSocketBytes())
110 break; 173 dict->SetString("captureMode", "LOG_BYTES");
eroman 2017/01/06 21:46:23 Formatting.
wangyix1 2017/01/10 22:20:15 Done.
111 case LOG_TYPE_NORMAL:
112 dict->SetString("logType", "NORMAL");
113 break;
114 case LOG_TYPE_STRIP_PRIVATE_DATA:
115 dict->SetString("logType", "STRIP_PRIVATE_DATA");
116 break;
117 }
118 174
119 return dict; 175 return dict;
120 } 176 }
121 177
122 NetLogFileWriter::NetLogFileWriter( 178 void NetLogFileWriter::RunStateCallback(StateCallback state_callback) {
123 ChromeNetLog* chrome_net_log, 179 DCHECK(thread_checker_.CalledOnValidThread());
124 const base::CommandLine::StringType& command_line_string, 180 state_callback.Run(std::unique_ptr<base::DictionaryValue>(GetState()));
eroman 2017/01/06 21:46:22 See comment about making GetState() return a uniqu
wangyix1 2017/01/10 22:20:15 Done.
125 const std::string& channel_string)
126 : state_(STATE_UNINITIALIZED),
127 log_type_(LOG_TYPE_NONE),
128 chrome_net_log_(chrome_net_log),
129 command_line_string_(command_line_string),
130 channel_string_(channel_string) {
131 // NetLogFileWriter can be created on one thread and used on another.
132 thread_checker_.DetachFromThread();
133 } 181 }
134 182
135 bool NetLogFileWriter::GetNetExportLogBaseDirectory( 183 void NetLogFileWriter::GetFilePath(FilePathCallback success_callback) {
136 base::FilePath* path) const {
137 DCHECK(thread_checker_.CalledOnValidThread()); 184 DCHECK(thread_checker_.CalledOnValidThread());
138 return base::GetTempDir(path); 185 if (!log_exists_ || state_ == STATE_LOGGING)
186 return;
eroman 2017/01/06 21:46:23 Would it make sense to always invoke the callback,
wangyix1 2017/01/10 22:20:15 Done.
187
188 DCHECK(file_task_runner_);
189 DCHECK(!log_path_.empty());
190
191 base::PostTaskAndReplyWithResult(
192 file_task_runner_.get(), FROM_HERE,
193 base::Bind(&NetLogFileWriter::SetPosixFilePermissionsAll, log_path_),
194 base::Bind(&NetLogFileWriter::RunFilePathCallback, success_callback,
195 log_path_));
139 } 196 }
140 197
141 net::NetLogCaptureMode NetLogFileWriter::GetCaptureModeForLogType( 198 bool NetLogFileWriter::SetPosixFilePermissionsAll(const base::FilePath& path) {
142 LogType log_type) { 199 if (!base::PathExists(path))
143 switch (log_type) { 200 return false;
144 case LOG_TYPE_LOG_BYTES: 201 #if defined(OS_POSIX)
145 return net::NetLogCaptureMode::IncludeSocketBytes(); 202 return base::SetPosixFilePermissions(path, base::FILE_PERMISSION_MASK);
146 case LOG_TYPE_NORMAL: 203 #else
147 return net::NetLogCaptureMode::IncludeCookiesAndCredentials(); 204 return true;
148 case LOG_TYPE_STRIP_PRIVATE_DATA: 205 #endif
149 return net::NetLogCaptureMode::Default();
150 case LOG_TYPE_NONE:
151 case LOG_TYPE_UNKNOWN:
152 NOTREACHED();
153 }
154 return net::NetLogCaptureMode::Default();
155 } 206 }
156 207
157 bool NetLogFileWriter::EnsureInit() { 208 void NetLogFileWriter::RunFilePathCallback(FilePathCallback path_callback,
158 DCHECK(thread_checker_.CalledOnValidThread()); 209 const base::FilePath& path,
159 if (state_ != STATE_UNINITIALIZED) 210 bool runCallback) {
160 return true; 211 if (runCallback)
eroman 2017/01/06 21:46:22 hacker_style_notation rather than camelCaseNotatio
wangyix1 2017/01/10 22:20:15 Done.
161 212 path_callback.Run(path);
162 if (log_path_.empty() && !SetUpDefaultNetExportLogPath())
163 return false;
164
165 state_ = STATE_NOT_LOGGING;
166 if (NetExportLogExists())
167 log_type_ = LOG_TYPE_UNKNOWN;
168 else
169 log_type_ = LOG_TYPE_NONE;
170
171 return true;
172 }
173
174 void NetLogFileWriter::StartNetLog(LogType log_type) {
175 DCHECK(thread_checker_.CalledOnValidThread());
176 if (state_ == STATE_LOGGING)
177 return;
178
179 DCHECK_NE(STATE_UNINITIALIZED, state_);
180 DCHECK(!log_path_.empty());
181
182 // Try to make sure we can create the file.
183 // TODO(rtenneti): Find a better for doing the following. Surface some error
184 // to the user if we couldn't create the file.
185 base::ScopedFILE file(base::OpenFile(log_path_, "w"));
186 if (!file)
187 return;
188
189 log_type_ = log_type;
190 state_ = STATE_LOGGING;
191
192 std::unique_ptr<base::Value> constants(
193 ChromeNetLog::GetConstants(command_line_string_, channel_string_));
194 write_to_file_observer_.reset(new net::WriteToFileNetLogObserver());
195 write_to_file_observer_->set_capture_mode(GetCaptureModeForLogType(log_type));
196 write_to_file_observer_->StartObserving(chrome_net_log_, std::move(file),
197 constants.get(), nullptr);
198 }
199
200 void NetLogFileWriter::StopNetLog() {
201 DCHECK(thread_checker_.CalledOnValidThread());
202 if (state_ != STATE_LOGGING)
203 return;
204
205 write_to_file_observer_->StopObserving(nullptr);
206 write_to_file_observer_.reset();
207 state_ = STATE_NOT_LOGGING;
208 } 213 }
209 214
210 void NetLogFileWriter::SetUpNetExportLogPath( 215 void NetLogFileWriter::SetUpNetExportLogPath(
211 const base::FilePath& custom_path) { 216 const base::FilePath& custom_path) {
212 DCHECK(thread_checker_.CalledOnValidThread()); 217 DCHECK(thread_checker_.CalledOnValidThread());
213
214 // The directory should always exist because the custom path
215 // is taken from a file selector dialog window.
216 DCHECK(base::PathExists(custom_path.DirName()));
217
218 log_path_ = custom_path; 218 log_path_ = custom_path;
219 } 219 }
220 220
221 bool NetLogFileWriter::SetUpDefaultNetExportLogPath() { 221 void NetLogFileWriter::InitAndCallback(base::Closure success_callback) {
222 DCHECK(thread_checker_.CalledOnValidThread()); 222 DCHECK(thread_checker_.CalledOnValidThread());
223 DCHECK(file_task_runner_);
224
225 base::PostTaskAndReplyWithResult(
226 file_task_runner_.get(), FROM_HERE,
227 base::Bind(&NetLogFileWriter::SetUpDefaultLogPath),
228 base::Bind(&NetLogFileWriter::InitStateAndCallback,
229 weak_ptr_factory_.GetWeakPtr(), success_callback));
230 }
231
232 NetLogFileWriter::DefaultLogPathResults
233 NetLogFileWriter::SetUpDefaultLogPath() {
234 DefaultLogPathResults results;
235 results.default_log_path_success = false;
236
223 base::FilePath temp_dir; 237 base::FilePath temp_dir;
224 if (!GetNetExportLogBaseDirectory(&temp_dir)) 238 if (!base::GetTempDir(&temp_dir))
225 return false; 239 return results;
226 240
227 // Delete log file at old location, if present. 241 // Delete log file at old location, if present.
228 DeleteFile(temp_dir.Append(kOldLogRelativePath), false); 242 base::DeleteFile(temp_dir.Append(kOldLogRelativePath), false);
229 243
230 base::FilePath log_path = temp_dir.Append(kLogRelativePath); 244 results.default_log_path = temp_dir.Append(kLogRelativePath);
245 if (!base::CreateDirectoryAndGetError(results.default_log_path.DirName(),
246 nullptr))
247 return results;
231 248
232 if (!base::CreateDirectoryAndGetError(log_path.DirName(), nullptr)) { 249 results.log_exists = base::PathExists(results.default_log_path);
233 return false; 250 results.default_log_path_success = true;
234 } 251 return results;
235
236 log_path_ = log_path;
237 return true;
238 } 252 }
239 253
240 bool NetLogFileWriter::NetExportLogExists() const { 254 void NetLogFileWriter::InitStateAndCallback(base::Closure sucess_callback,
255 const DefaultLogPathResults& results) {
241 DCHECK(thread_checker_.CalledOnValidThread()); 256 DCHECK(thread_checker_.CalledOnValidThread());
242 DCHECK(!log_path_.empty()); 257
243 return base::PathExists(log_path_); 258 if (!results.default_log_path_success)
259 return;
260
261 log_path_ = results.default_log_path;
262 state_ = STATE_NOT_LOGGING;
263 log_exists_ = results.log_exists;
264 DCHECK(!log_capture_mode_known_);
265
266 sucess_callback.Run();
267 }
268
269 void NetLogFileWriter::SetFileTaskRunner(
270 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
271 file_task_runner_ = file_task_runner;
272 }
273
274 void NetLogFileWriter::SetNetTaskRunner(
275 scoped_refptr<base::SingleThreadTaskRunner> net_task_runner) {
276 net_task_runner_ = net_task_runner;
277 }
278
279 scoped_refptr<base::SingleThreadTaskRunner>
280 NetLogFileWriter::GetFileTaskRunner() const {
281 return file_task_runner_;
282 }
283
284 scoped_refptr<base::SingleThreadTaskRunner>
285 NetLogFileWriter::GetNetTaskRunner() const {
286 return net_task_runner_;
244 } 287 }
245 288
246 } // namespace net_log 289 } // namespace net_log
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698