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

Side by Side Diff: chrome/browser/media/webrtc_logging_handler_host.cc

Issue 1978183003: Refactor WebRtcLoggingHandlerHost in preparation of automatic upload of WebRtcEventLogs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix race when renderer is closing while the log is in STARTING or STOPPING state Created 4 years, 5 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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 "chrome/browser/media/webrtc_logging_handler_host.h" 5 #include "chrome/browser/media/webrtc_logging_handler_host.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/cpu.h"
13 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/sys_info.h"
17 #include "base/time/time.h"
18 #include "build/build_config.h" 14 #include "build/build_config.h"
19 #include "chrome/browser/bad_message.h" 15 #include "chrome/browser/bad_message.h"
20 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chromeos/settings/cros_settings.h"
22 #include "chrome/browser/media/webrtc_log_list.h" 17 #include "chrome/browser/media/webrtc_log_list.h"
23 #include "chrome/browser/media/webrtc_log_uploader.h" 18 #include "chrome/browser/media/webrtc_log_uploader.h"
24 #include "chrome/browser/media/webrtc_rtp_dump_handler.h" 19 #include "chrome/browser/media/webrtc_rtp_dump_handler.h"
25 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/common/channel_info.h"
27 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/media/webrtc_logging_messages.h" 22 #include "chrome/common/media/webrtc_logging_messages.h"
29 #include "chromeos/settings/cros_settings_names.h"
30 #include "components/prefs/pref_service.h"
31 #include "components/version_info/version_info.h"
32 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/content_browser_client.h" 24 #include "content/public/browser/content_browser_client.h"
34 #include "content/public/browser/gpu_data_manager.h"
35 #include "content/public/browser/render_process_host.h" 25 #include "content/public/browser/render_process_host.h"
36 #include "gpu/config/gpu_info.h"
37 #include "net/base/ip_address.h"
38 #include "net/url_request/url_request_context_getter.h"
39 26
40 #if defined(OS_LINUX)
41 #include "base/linux_util.h"
42 #endif
43
44 #if defined(OS_MACOSX)
45 #include "base/mac/mac_util.h"
46 #endif
47
48 #if defined(OS_CHROMEOS)
49 #include "chromeos/system/statistics_provider.h"
50 #endif
51
52 using base::IntToString;
53 using content::BrowserThread; 27 using content::BrowserThread;
54 28
55 // Key used to attach the handler to the RenderProcessHost. 29 // Key used to attach the handler to the RenderProcessHost.
56 const char WebRtcLoggingHandlerHost::kWebRtcLoggingHandlerHostKey[] = 30 const char WebRtcLoggingHandlerHost::kWebRtcLoggingHandlerHostKey[] =
57 "kWebRtcLoggingHandlerHostKey"; 31 "kWebRtcLoggingHandlerHostKey";
58 32
59 namespace {
60
61 const char kLogNotStoppedOrNoLogOpen[] =
62 "Logging not stopped or no log open.";
63
64 // For privacy reasons when logging IP addresses. The returned "sensitive
65 // string" is for release builds a string with the end stripped away. Last
66 // octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be
67 // "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is
68 // not stripped.
69 std::string IPAddressToSensitiveString(const net::IPAddress& address) {
70 #if defined(NDEBUG)
71 std::string sensitive_address;
72 switch (address.size()) {
73 case net::IPAddress::kIPv4AddressSize: {
74 sensitive_address = address.ToString();
75 size_t find_pos = sensitive_address.rfind('.');
76 if (find_pos == std::string::npos)
77 return std::string();
78 sensitive_address.resize(find_pos);
79 sensitive_address += ".x";
80 break;
81 }
82 case net::IPAddress::kIPv6AddressSize: {
83 // TODO(grunell): Create a string of format "1:2:3:x:x:x:x:x" to clarify
84 // that the end has been stripped out.
85 std::vector<uint8_t> bytes = address.bytes();
86 std::fill(bytes.begin() + 6, bytes.end(), 0);
87 net::IPAddress stripped_address(bytes);
88 sensitive_address = stripped_address.ToString();
89 break;
90 }
91 default: { break; }
92 }
93 return sensitive_address;
94 #else
95 return address.ToString();
96 #endif
97 }
98
99 void FormatMetaDataAsLogMessage(
100 const MetaDataMap& meta_data,
101 std::string* message) {
102 for (MetaDataMap::const_iterator it = meta_data.begin();
103 it != meta_data.end(); ++it) {
104 *message += it->first + ": " + it->second + '\n';
105 }
106 // Remove last '\n'.
107 message->resize(message->size() - 1);
108 }
109
110 } // namespace
111
112 WebRtcLogBuffer::WebRtcLogBuffer()
113 : buffer_(),
114 circular_(&buffer_[0], sizeof(buffer_), sizeof(buffer_) / 2, false),
115 read_only_(false) {
116 }
117
118 WebRtcLogBuffer::~WebRtcLogBuffer() {
119 DCHECK(read_only_ || thread_checker_.CalledOnValidThread());
120 }
121
122 void WebRtcLogBuffer::Log(const std::string& message) {
123 DCHECK(thread_checker_.CalledOnValidThread());
124 DCHECK(!read_only_);
125 circular_.Write(message.c_str(), message.length());
126 const char eol = '\n';
127 circular_.Write(&eol, 1);
128 }
129
130 PartialCircularBuffer WebRtcLogBuffer::Read() {
131 DCHECK(thread_checker_.CalledOnValidThread());
132 DCHECK(read_only_);
133 return PartialCircularBuffer(&buffer_[0], sizeof(buffer_));
134 }
135
136 void WebRtcLogBuffer::SetComplete() {
137 DCHECK(thread_checker_.CalledOnValidThread());
138 DCHECK(!read_only_) << "Already set? (programmer error)";
139 read_only_ = true;
140 // Detach from the current thread so that we can check reads on a different
141 // thread. This is to make sure that Read()s still happen on one thread only.
142 thread_checker_.DetachFromThread();
143 }
144
145 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost( 33 WebRtcLoggingHandlerHost::WebRtcLoggingHandlerHost(
146 int render_process_id, 34 int render_process_id,
147 Profile* profile, 35 Profile* profile,
148 WebRtcLogUploader* log_uploader) 36 WebRtcLogUploader* log_uploader)
149 : BrowserMessageFilter(WebRtcLoggingMsgStart), 37 : BrowserMessageFilter(WebRtcLoggingMsgStart),
38 render_process_id_(render_process_id),
150 profile_(profile), 39 profile_(profile),
151 logging_state_(CLOSED),
152 upload_log_on_render_close_(false), 40 upload_log_on_render_close_(false),
153 log_uploader_(log_uploader), 41 text_log_handler_(new WebRtcTextLogHandler(render_process_id)),
154 render_process_id_(render_process_id) { 42 rtp_dump_handler_(),
43 stop_rtp_dump_callback_(),
44 log_uploader_(log_uploader) {
155 DCHECK(profile_); 45 DCHECK(profile_);
156 DCHECK(log_uploader_); 46 DCHECK(log_uploader_);
157 } 47 }
158 48
159 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() { 49 WebRtcLoggingHandlerHost::~WebRtcLoggingHandlerHost() {
160 // If we hit this, then we might be leaking a log reference count (see 50 // If we hit this, then we might be leaking a log reference count (see
161 // ApplyForStartLogging). 51 // ApplyForStartLogging).
162 DCHECK_EQ(CLOSED, logging_state_); 52 DCHECK_EQ(WebRtcTextLogHandler::CLOSED, text_log_handler_->GetState());
163 } 53 }
164 54
165 void WebRtcLoggingHandlerHost::SetMetaData( 55 void WebRtcLoggingHandlerHost::SetMetaData(
166 std::unique_ptr<MetaDataMap> meta_data, 56 std::unique_ptr<MetaDataMap> meta_data,
167 const GenericDoneCallback& callback) { 57 const GenericDoneCallback& callback) {
168 DCHECK_CURRENTLY_ON(BrowserThread::IO); 58 DCHECK_CURRENTLY_ON(BrowserThread::IO);
169 DCHECK(!callback.is_null()); 59 DCHECK(!callback.is_null());
170 60
171 std::string error_message; 61 text_log_handler_->SetMetaData(std::move(meta_data), callback);
172 if (logging_state_ == CLOSED) {
173 if (!meta_data_.get())
174 meta_data_ = std::move(meta_data);
175 } else if (logging_state_ == STARTED) {
176 std::string meta_data_message;
177 FormatMetaDataAsLogMessage(*meta_data.get(), &meta_data_message);
178 LogToCircularBuffer(meta_data_message);
179 } else {
180 error_message = "Meta data must be set before stop or upload.";
181 }
182
183 if (error_message.empty() && meta_data.get()) {
184 // Keep the meta data around for uploading separately from the log.
185 for (const auto& it : *meta_data.get())
186 (*meta_data_.get())[it.first] = it.second;
187 }
188
189 FireGenericDoneCallback(callback, error_message.empty(), error_message);
190 } 62 }
191 63
192 void WebRtcLoggingHandlerHost::StartLogging( 64 void WebRtcLoggingHandlerHost::StartLogging(
193 const GenericDoneCallback& callback) { 65 const GenericDoneCallback& callback) {
194 DCHECK_CURRENTLY_ON(BrowserThread::IO); 66 DCHECK_CURRENTLY_ON(BrowserThread::IO);
195 DCHECK(!callback.is_null()); 67 DCHECK(!callback.is_null());
196 68
197 if (logging_state_ != CLOSED) { 69 // Request a log_slot from the LogUploader and start logging.
198 FireGenericDoneCallback(callback, false, "A log is already open."); 70 if (text_log_handler_->StartLogging(log_uploader_, callback)) {
199 return; 71 // Start logging in the renderer. The callback has already been fired since
72 // there is no acknowledgement when the renderer actually starts.
73 Send(new WebRtcLoggingMsg_StartLogging());
200 } 74 }
201
202 if (!log_uploader_->ApplyForStartLogging()) {
203 FireGenericDoneCallback(callback, false,
204 "Cannot start, maybe the maximum number of "
205 "simultaneuos logs has been reached.");
206 return;
207 }
208
209 logging_state_ = STARTING;
210
211 DCHECK(!log_buffer_.get());
212 log_buffer_.reset(new WebRtcLogBuffer());
213 if (!meta_data_.get())
214 meta_data_.reset(new MetaDataMap());
215
216 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
217 &WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread, this, callback));
218 } 75 }
219 76
220 void WebRtcLoggingHandlerHost::StopLogging( 77 void WebRtcLoggingHandlerHost::StopLogging(
221 const GenericDoneCallback& callback) { 78 const GenericDoneCallback& callback) {
222 DCHECK_CURRENTLY_ON(BrowserThread::IO); 79 DCHECK_CURRENTLY_ON(BrowserThread::IO);
223 DCHECK(!callback.is_null()); 80 DCHECK(!callback.is_null());
224 81
225 if (logging_state_ != STARTED) { 82 // Change the state to STOPPING and disable logging in the browser.
226 FireGenericDoneCallback(callback, false, "Logging not started."); 83 if (text_log_handler_->StopLogging(callback)) {
227 return; 84 // Stop logging in the renderer. OnLoggingStoppedInRenderer will be called
85 // when this is done to change the state from STOPPING to STOPPED and fire
86 // the callback.
87 Send(new WebRtcLoggingMsg_StopLogging());
228 } 88 }
229
230 stop_callback_ = callback;
231 logging_state_ = STOPPING;
232
233 Send(new WebRtcLoggingMsg_StopLogging());
234
235 BrowserThread::PostTask(
236 BrowserThread::UI, FROM_HERE,
237 base::Bind(
238 &WebRtcLoggingHandlerHost::DisableBrowserProcessLoggingOnUIThread,
239 this));
240 } 89 }
241 90
242 void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) { 91 void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) {
243 DCHECK_CURRENTLY_ON(BrowserThread::IO); 92 DCHECK_CURRENTLY_ON(BrowserThread::IO);
244 DCHECK(!callback.is_null()); 93 DCHECK(!callback.is_null());
245 94
246 if (logging_state_ != STOPPED) { 95 // This functions uploads both text logs (mandatory) and RTP dumps (optional).
247 if (!callback.is_null()) { 96 // TODO(terelius): If there's no text log available (either because it hasn't
248 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, 97 // been started or because it hasn't been stopped), the current implementation
249 base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen)); 98 // will fire an error callback and leave any RTP dumps in a local directory.
250 } 99 // Would it be better to upload whatever logs we have, or would the lack of
251 return; 100 // an error callback make it harder to debug potential errors?
252 }
253 101
254 content::BrowserThread::PostTaskAndReplyWithResult( 102 BrowserThread::PostTaskAndReplyWithResult(
255 content::BrowserThread::FILE, 103 content::BrowserThread::FILE, FROM_HERE,
256 FROM_HERE,
257 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, 104 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
258 this), 105 this),
259 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this, callback)); 106 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this, callback));
260 } 107 }
261 108
262 void WebRtcLoggingHandlerHost::UploadStoredLog( 109 void WebRtcLoggingHandlerHost::UploadStoredLog(
263 const std::string& log_id, 110 const std::string& log_id,
264 const UploadDoneCallback& callback) { 111 const UploadDoneCallback& callback) {
265 DCHECK_CURRENTLY_ON(BrowserThread::IO); 112 DCHECK_CURRENTLY_ON(BrowserThread::IO);
266 DCHECK(!callback.is_null()); 113 DCHECK(!callback.is_null());
(...skipping 13 matching lines...) Expand all
280 upload_data.log_path = GetLogDirectoryAndEnsureExists(); 127 upload_data.log_path = GetLogDirectoryAndEnsureExists();
281 upload_data.callback = callback; 128 upload_data.callback = callback;
282 upload_data.host = this; 129 upload_data.host = this;
283 upload_data.local_log_id = log_id; 130 upload_data.local_log_id = log_id;
284 131
285 log_uploader_->UploadStoredLog(upload_data); 132 log_uploader_->UploadStoredLog(upload_data);
286 } 133 }
287 134
288 void WebRtcLoggingHandlerHost::UploadLogDone() { 135 void WebRtcLoggingHandlerHost::UploadLogDone() {
289 DCHECK_CURRENTLY_ON(BrowserThread::IO); 136 DCHECK_CURRENTLY_ON(BrowserThread::IO);
290 logging_state_ = CLOSED; 137 // The logging state changed to CLOSED when we released the logs prior to
138 // uploading. We can't check the state because a new log might have started
139 // already, so there is nothing for us to do here. In the future, we might
140 // want to use this function to clean up files stored on disc.
291 } 141 }
292 142
293 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) { 143 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) {
294 DCHECK_CURRENTLY_ON(BrowserThread::IO); 144 DCHECK_CURRENTLY_ON(BrowserThread::IO);
295 DCHECK(!callback.is_null()); 145 DCHECK(!callback.is_null());
296 146
297 if (logging_state_ != STOPPED) { 147 if (!text_log_handler_->ExpectLoggingStateStopped(callback)) {
298 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen); 148 // The callback is fired with an error message by ExpectLoggingStateStopped.
299 return; 149 return;
300 } 150 }
301 log_uploader_->LoggingStoppedDontUpload(); 151 log_uploader_->LoggingStoppedDontUpload();
302 log_buffer_.reset(); 152 text_log_handler_->DiscardLog();
303 meta_data_.reset();
304 logging_state_ = CLOSED;
305 rtp_dump_handler_.reset(); 153 rtp_dump_handler_.reset();
306 stop_rtp_dump_callback_.Reset(); 154 stop_rtp_dump_callback_.Reset();
307 FireGenericDoneCallback(callback, true, ""); 155 FireGenericDoneCallback(callback, true, "");
308 } 156 }
309 157
310 // Stores the log locally using a hash of log_id + security origin. 158 // Stores the log locally using a hash of log_id + security origin.
311 void WebRtcLoggingHandlerHost::StoreLog( 159 void WebRtcLoggingHandlerHost::StoreLog(
312 const std::string& log_id, 160 const std::string& log_id,
313 const GenericDoneCallback& callback) { 161 const GenericDoneCallback& callback) {
314 DCHECK_CURRENTLY_ON(BrowserThread::IO); 162 DCHECK_CURRENTLY_ON(BrowserThread::IO);
315 DCHECK(!callback.is_null()); 163 DCHECK(!callback.is_null());
316 164
317 if (logging_state_ != STOPPED) { 165 if (!text_log_handler_->ExpectLoggingStateStopped(callback)) {
318 FireGenericDoneCallback(callback, false, kLogNotStoppedOrNoLogOpen); 166 // The callback is fired with an error message by ExpectLoggingStateStopped.
319 return; 167 return;
320 } 168 }
321 169
322 if (rtp_dump_handler_) { 170 if (rtp_dump_handler_) {
323 BrowserThread::PostTask( 171 BrowserThread::PostTask(
324 BrowserThread::UI, 172 BrowserThread::UI,
325 FROM_HERE, 173 FROM_HERE,
326 base::Bind(stop_rtp_dump_callback_, true, true)); 174 base::Bind(stop_rtp_dump_callback_, true, true));
327 175
328 rtp_dump_handler_->StopOngoingDumps( 176 rtp_dump_handler_->StopOngoingDumps(
(...skipping 15 matching lines...) Expand all
344 ReleaseRtpDumps(log_paths.get()); 192 ReleaseRtpDumps(log_paths.get());
345 193
346 content::BrowserThread::PostTaskAndReplyWithResult( 194 content::BrowserThread::PostTaskAndReplyWithResult(
347 content::BrowserThread::FILE, FROM_HERE, 195 content::BrowserThread::FILE, FROM_HERE,
348 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, 196 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
349 this), 197 this),
350 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory, this, log_id, 198 base::Bind(&WebRtcLoggingHandlerHost::StoreLogInDirectory, this, log_id,
351 base::Passed(&log_paths), callback)); 199 base::Passed(&log_paths), callback));
352 } 200 }
353 201
354 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) {
355 DCHECK_CURRENTLY_ON(BrowserThread::IO);
356 if (logging_state_ == STARTED) {
357 LogToCircularBuffer(WebRtcLoggingMessageData::Format(
358 message, base::Time::Now(), logging_started_time_));
359 }
360 }
361 202
362 void WebRtcLoggingHandlerHost::StartRtpDump( 203 void WebRtcLoggingHandlerHost::StartRtpDump(
363 RtpDumpType type, 204 RtpDumpType type,
364 const GenericDoneCallback& callback, 205 const GenericDoneCallback& callback,
365 const content::RenderProcessHost::WebRtcStopRtpDumpCallback& 206 const content::RenderProcessHost::WebRtcStopRtpDumpCallback&
366 stop_callback) { 207 stop_callback) {
367 DCHECK_CURRENTLY_ON(BrowserThread::IO); 208 DCHECK_CURRENTLY_ON(BrowserThread::IO);
368 DCHECK(stop_rtp_dump_callback_.is_null() || 209 DCHECK(stop_rtp_dump_callback_.is_null() ||
369 stop_rtp_dump_callback_.Equals(stop_callback)); 210 stop_rtp_dump_callback_.Equals(stop_callback));
370 211
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to 278 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to
438 // create/ensure the log directory. 279 // create/ensure the log directory.
439 if (rtp_dump_handler_) { 280 if (rtp_dump_handler_) {
440 rtp_dump_handler_->OnRtpPacket( 281 rtp_dump_handler_->OnRtpPacket(
441 packet_header.get(), header_length, packet_length, incoming); 282 packet_header.get(), header_length, packet_length, incoming);
442 } 283 }
443 } 284 }
444 285
445 void WebRtcLoggingHandlerHost::OnChannelClosing() { 286 void WebRtcLoggingHandlerHost::OnChannelClosing() {
446 DCHECK_CURRENTLY_ON(BrowserThread::IO); 287 DCHECK_CURRENTLY_ON(BrowserThread::IO);
447 if (logging_state_ == STARTED || logging_state_ == STOPPED) { 288 if (text_log_handler_->GetState() == WebRtcTextLogHandler::STARTING ||
tommi (sloooow) - chröme 2016/07/15 10:11:36 Call GetState() only once?
magjed_chromium 2016/07/19 14:53:16 How about a switch? switch (text_log_handler_->Get
terelius-chromium 2016/07/21 16:25:14 Done.
terelius-chromium 2016/07/21 16:25:14 Done.
289 text_log_handler_->GetState() == WebRtcTextLogHandler::STARTED ||
290 text_log_handler_->GetState() == WebRtcTextLogHandler::STOPPING ||
291 text_log_handler_->GetState() == WebRtcTextLogHandler::STOPPED) {
292 text_log_handler_->ChannelClosing();
448 if (upload_log_on_render_close_) { 293 if (upload_log_on_render_close_) {
449 logging_started_time_ = base::Time();
450
451 content::BrowserThread::PostTaskAndReplyWithResult( 294 content::BrowserThread::PostTaskAndReplyWithResult(
452 content::BrowserThread::FILE, 295 content::BrowserThread::FILE,
453 FROM_HERE, 296 FROM_HERE,
454 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, 297 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
455 this), 298 this),
456 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this, 299 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this,
457 UploadDoneCallback())); 300 UploadDoneCallback()));
458 } else { 301 } else {
459 log_uploader_->LoggingStoppedDontUpload(); 302 log_uploader_->LoggingStoppedDontUpload();
460 logging_state_ = CLOSED; 303 text_log_handler_->DiscardLog();
461 } 304 }
462 } 305 }
463 content::BrowserMessageFilter::OnChannelClosing(); 306 content::BrowserMessageFilter::OnChannelClosing();
464 } 307 }
465 308
466 void WebRtcLoggingHandlerHost::OnDestruct() const { 309 void WebRtcLoggingHandlerHost::OnDestruct() const {
467 BrowserThread::DeleteOnIOThread::Destruct(this); 310 BrowserThread::DeleteOnIOThread::Destruct(this);
468 } 311 }
469 312
470 bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) { 313 bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) {
471 DCHECK_CURRENTLY_ON(BrowserThread::IO); 314 DCHECK_CURRENTLY_ON(BrowserThread::IO);
472 bool handled = true; 315 bool handled = true;
473 IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message) 316 IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message)
474 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages) 317 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages)
475 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped, 318 IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_LoggingStopped,
476 OnLoggingStoppedInRenderer) 319 OnLoggingStoppedInRenderer)
477 IPC_MESSAGE_UNHANDLED(handled = false) 320 IPC_MESSAGE_UNHANDLED(handled = false)
478 IPC_END_MESSAGE_MAP() 321 IPC_END_MESSAGE_MAP()
479 322
480 return handled; 323 return handled;
481 } 324 }
482 325
483 void WebRtcLoggingHandlerHost::OnAddLogMessages( 326 void WebRtcLoggingHandlerHost::OnAddLogMessages(
484 const std::vector<WebRtcLoggingMessageData>& messages) { 327 const std::vector<WebRtcLoggingMessageData>& messages) {
485 DCHECK_CURRENTLY_ON(BrowserThread::IO); 328 DCHECK_CURRENTLY_ON(BrowserThread::IO);
486 if (logging_state_ == STARTED || logging_state_ == STOPPING) { 329 if (text_log_handler_->GetState() == WebRtcTextLogHandler::STARTED ||
330 text_log_handler_->GetState() == WebRtcTextLogHandler::STOPPING) {
487 for (size_t i = 0; i < messages.size(); ++i) { 331 for (size_t i = 0; i < messages.size(); ++i) {
488 LogToCircularBuffer(messages[i].Format(logging_started_time_)); 332 text_log_handler_->LogWebRtcLoggingMessageData(messages[i]);
489 } 333 }
490 } 334 }
491 } 335 }
492 336
493 void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() { 337 void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() {
494 DCHECK_CURRENTLY_ON(BrowserThread::IO); 338 DCHECK_CURRENTLY_ON(BrowserThread::IO);
495 if (logging_state_ != STOPPING) { 339 if (text_log_handler_->GetState() != WebRtcTextLogHandler::STOPPING) {
496 // If an out-of-order response is received, stop_callback_ may be invalid, 340 // If an out-of-order response is received, stop_callback_ may be invalid,
497 // and must not be invoked. 341 // and must not be invoked.
498 DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state " 342 DLOG(ERROR) << "OnLoggingStoppedInRenderer invoked in state "
499 << logging_state_; 343 << text_log_handler_->GetState();
500 bad_message::ReceivedBadMessage( 344 bad_message::ReceivedBadMessage(
501 this, bad_message::WRLHH_LOGGING_STOPPED_BAD_STATE); 345 this, bad_message::WRLHH_LOGGING_STOPPED_BAD_STATE);
502 return; 346 return;
503 } 347 }
504 logging_started_time_ = base::Time(); 348 text_log_handler_->StopDone();
505 logging_state_ = STOPPED;
506 FireGenericDoneCallback(stop_callback_, true, "");
507 stop_callback_.Reset();
508 }
509
510 void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread(
511 const GenericDoneCallback& callback) {
512 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
513
514 net::NetworkInterfaceList network_list;
515 net::GetNetworkList(&network_list,
516 net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
517
518 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
519 &WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread, this, network_list,
520 callback));
521 }
522
523 void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread(
524 const net::NetworkInterfaceList& network_list,
525 const GenericDoneCallback& callback) {
526 DCHECK_CURRENTLY_ON(BrowserThread::IO);
527 if (logging_state_ != STARTING) {
528 FireGenericDoneCallback(callback, false, "Logging cancelled.");
529 return;
530 }
531
532 // Tell the renderer and the browser to enable logging. Log messages are
533 // recevied on the IO thread, so the initial info will finish to be written
534 // first.
535 Send(new WebRtcLoggingMsg_StartLogging());
536 BrowserThread::PostTask(
537 BrowserThread::UI, FROM_HERE,
538 base::Bind(
539 &WebRtcLoggingHandlerHost::EnableBrowserProcessLoggingOnUIThread,
540 this));
541
542 // Log start time (current time). We don't use base/i18n/time_formatting.h
543 // here because we don't want the format of the current locale.
544 base::Time::Exploded now = {0};
545 base::Time::Now().LocalExplode(&now);
546 LogToCircularBuffer(base::StringPrintf(
547 "Start %d-%02d-%02d %02d:%02d:%02d", now.year, now.month,
548 now.day_of_month, now.hour, now.minute, now.second));
549
550 // Write metadata if received before logging started.
551 if (meta_data_.get() && !meta_data_->empty()) {
552 std::string info;
553 FormatMetaDataAsLogMessage(*meta_data_.get(), &info);
554 LogToCircularBuffer(info);
555 }
556
557 // Chrome version
558 LogToCircularBuffer("Chrome version: " + version_info::GetVersionNumber() +
559 " " + chrome::GetChannelString());
560
561 // OS
562 LogToCircularBuffer(base::SysInfo::OperatingSystemName() + " " +
563 base::SysInfo::OperatingSystemVersion() + " " +
564 base::SysInfo::OperatingSystemArchitecture());
565 #if defined(OS_LINUX)
566 LogToCircularBuffer("Linux distribution: " + base::GetLinuxDistro());
567 #endif
568
569 // CPU
570 base::CPU cpu;
571 LogToCircularBuffer(
572 "Cpu: " + IntToString(cpu.family()) + "." + IntToString(cpu.model()) +
573 "." + IntToString(cpu.stepping()) + ", x" +
574 IntToString(base::SysInfo::NumberOfProcessors()) + ", " +
575 IntToString(base::SysInfo::AmountOfPhysicalMemoryMB()) + "MB");
576 std::string cpu_brand = cpu.cpu_brand();
577 // Workaround for crbug.com/249713.
578 // TODO(grunell): Remove workaround when bug is fixed.
579 size_t null_pos = cpu_brand.find('\0');
580 if (null_pos != std::string::npos)
581 cpu_brand.erase(null_pos);
582 LogToCircularBuffer("Cpu brand: " + cpu_brand);
583
584 // Computer model
585 std::string computer_model = "Not available";
586 #if defined(OS_MACOSX)
587 computer_model = base::mac::GetModelIdentifier();
588 #elif defined(OS_CHROMEOS)
589 chromeos::system::StatisticsProvider::GetInstance()->
590 GetMachineStatistic(chromeos::system::kHardwareClassKey, &computer_model);
591 #endif
592 LogToCircularBuffer("Computer model: " + computer_model);
593
594 // GPU
595 gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
596 LogToCircularBuffer(
597 "Gpu: machine-model-name=" + gpu_info.machine_model_name +
598 ", machine-model-version=" + gpu_info.machine_model_version +
599 ", vendor-id=" + base::UintToString(gpu_info.gpu.vendor_id) +
600 ", device-id=" + base::UintToString(gpu_info.gpu.device_id) +
601 ", driver-vendor=" + gpu_info.driver_vendor +
602 ", driver-version=" + gpu_info.driver_version);
603 LogToCircularBuffer(
604 "OpenGL: gl-vendor=" + gpu_info.gl_vendor +
605 ", gl-renderer=" + gpu_info.gl_renderer +
606 ", gl-version=" + gpu_info.gl_version);
607
608 // Network interfaces
609 LogToCircularBuffer("Discovered " + base::SizeTToString(network_list.size()) +
610 " network interfaces:");
611 for (net::NetworkInterfaceList::const_iterator it = network_list.begin();
612 it != network_list.end(); ++it) {
613 LogToCircularBuffer(
614 "Name: " + it->friendly_name + ", Address: " +
615 IPAddressToSensitiveString(it->address) + ", Type: " +
616 net::NetworkChangeNotifier::ConnectionTypeToString(it->type));
617 }
618
619 logging_started_time_ = base::Time::Now();
620 logging_state_ = STARTED;
621 FireGenericDoneCallback(callback, true, "");
622 }
623
624 void WebRtcLoggingHandlerHost::EnableBrowserProcessLoggingOnUIThread() {
625 DCHECK_CURRENTLY_ON(BrowserThread::UI);
626 content::RenderProcessHost* host =
627 content::RenderProcessHost::FromID(render_process_id_);
628 if (host) {
629 host->SetWebRtcLogMessageCallback(
630 base::Bind(&WebRtcLoggingHandlerHost::LogMessage, this));
631 }
632 }
633
634 void WebRtcLoggingHandlerHost::DisableBrowserProcessLoggingOnUIThread() {
635 DCHECK_CURRENTLY_ON(BrowserThread::UI);
636 content::RenderProcessHost* host =
637 content::RenderProcessHost::FromID(render_process_id_);
638 if (host)
639 host->ClearWebRtcLogMessageCallback();
640 }
641
642 void WebRtcLoggingHandlerHost::LogToCircularBuffer(const std::string& message) {
643 DCHECK_CURRENTLY_ON(BrowserThread::IO);
644 DCHECK_NE(logging_state_, CLOSED);
645 log_buffer_->Log(message);
646 } 349 }
647 350
648 base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() { 351 base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
649 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 352 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
650 base::FilePath log_dir_path = 353 base::FilePath log_dir_path =
651 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); 354 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
652 base::File::Error error; 355 base::File::Error error;
653 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) { 356 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
654 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error; 357 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
655 return base::FilePath(); 358 return base::FilePath();
(...skipping 24 matching lines...) Expand all
680 } 383 }
681 384
682 void WebRtcLoggingHandlerHost::StoreLogInDirectory( 385 void WebRtcLoggingHandlerHost::StoreLogInDirectory(
683 const std::string& log_id, 386 const std::string& log_id,
684 std::unique_ptr<WebRtcLogPaths> log_paths, 387 std::unique_ptr<WebRtcLogPaths> log_paths,
685 const GenericDoneCallback& done_callback, 388 const GenericDoneCallback& done_callback,
686 const base::FilePath& directory) { 389 const base::FilePath& directory) {
687 DCHECK_CURRENTLY_ON(BrowserThread::IO); 390 DCHECK_CURRENTLY_ON(BrowserThread::IO);
688 log_paths->log_path = directory; 391 log_paths->log_path = directory;
689 392
690 log_buffer_->SetComplete(); 393 std::unique_ptr<WebRtcLogBuffer> log_buffer;
394 std::unique_ptr<MetaDataMap> meta_data;
395 text_log_handler_->ReleaseLog(&log_buffer, &meta_data);
396
691 BrowserThread::PostTask( 397 BrowserThread::PostTask(
692 BrowserThread::FILE, FROM_HERE, 398 BrowserThread::FILE, FROM_HERE,
693 base::Bind(&WebRtcLogUploader::LoggingStoppedDoStore, 399 base::Bind(&WebRtcLogUploader::LoggingStoppedDoStore,
694 base::Unretained(log_uploader_), 400 base::Unretained(log_uploader_), *log_paths.get(), log_id,
695 *log_paths.get(), log_id, base::Passed(&log_buffer_), 401 base::Passed(&log_buffer), base::Passed(&meta_data),
696 base::Passed(&meta_data_), done_callback)); 402 done_callback));
697
698 logging_state_ = CLOSED;
699 } 403 }
700 404
701 void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps( 405 void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps(
702 const base::FilePath& log_directory, 406 const base::FilePath& log_directory,
703 const UploadDoneCallback& callback) { 407 const UploadDoneCallback& callback) {
704 DCHECK_CURRENTLY_ON(BrowserThread::IO); 408 DCHECK_CURRENTLY_ON(BrowserThread::IO);
705 409
410 if (text_log_handler_->GetState() != WebRtcTextLogHandler::STOPPED &&
411 text_log_handler_->GetState() != WebRtcTextLogHandler::CHANNEL_CLOSING) {
412 BrowserThread::PostTask(
413 content::BrowserThread::UI, FROM_HERE,
414 base::Bind(callback, false, "", "Logging not stopped or no log open."));
415 return;
416 }
417
706 WebRtcLogUploadDoneData upload_done_data; 418 WebRtcLogUploadDoneData upload_done_data;
707 upload_done_data.log_path = log_directory; 419 upload_done_data.log_path = log_directory;
708 upload_done_data.callback = callback; 420 upload_done_data.callback = callback;
709 upload_done_data.host = this; 421 upload_done_data.host = this;
710 ReleaseRtpDumps(&upload_done_data); 422 ReleaseRtpDumps(&upload_done_data);
711 423
712 log_buffer_->SetComplete(); 424 std::unique_ptr<WebRtcLogBuffer> log_buffer;
425 std::unique_ptr<MetaDataMap> meta_data;
426 text_log_handler_->ReleaseLog(&log_buffer, &meta_data);
427
713 BrowserThread::PostTask( 428 BrowserThread::PostTask(
714 BrowserThread::FILE, FROM_HERE, 429 BrowserThread::FILE, FROM_HERE,
715 base::Bind(&WebRtcLogUploader::LoggingStoppedDoUpload, 430 base::Bind(&WebRtcLogUploader::LoggingStoppedDoUpload,
716 base::Unretained(log_uploader_), base::Passed(&log_buffer_), 431 base::Unretained(log_uploader_), base::Passed(&log_buffer),
717 base::Passed(&meta_data_), upload_done_data)); 432 base::Passed(&meta_data), upload_done_data));
718
719 logging_state_ = CLOSED;
720 } 433 }
721 434
722 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart( 435 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart(
723 RtpDumpType type, 436 RtpDumpType type,
724 const GenericDoneCallback& callback, 437 const GenericDoneCallback& callback,
725 const base::FilePath& dump_dir) { 438 const base::FilePath& dump_dir) {
726 DCHECK_CURRENTLY_ON(BrowserThread::IO); 439 DCHECK_CURRENTLY_ON(BrowserThread::IO);
727 440
728 // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before 441 // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before
729 // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous 442 // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous
(...skipping 26 matching lines...) Expand all
756 log_paths->incoming_rtp_dump = rtp_dumps.incoming_dump_path; 469 log_paths->incoming_rtp_dump = rtp_dumps.incoming_dump_path;
757 log_paths->outgoing_rtp_dump = rtp_dumps.outgoing_dump_path; 470 log_paths->outgoing_rtp_dump = rtp_dumps.outgoing_dump_path;
758 471
759 rtp_dump_handler_.reset(); 472 rtp_dump_handler_.reset();
760 stop_rtp_dump_callback_.Reset(); 473 stop_rtp_dump_callback_.Reset();
761 474
762 return true; 475 return true;
763 } 476 }
764 477
765 void WebRtcLoggingHandlerHost::FireGenericDoneCallback( 478 void WebRtcLoggingHandlerHost::FireGenericDoneCallback(
766 const WebRtcLoggingHandlerHost::GenericDoneCallback& callback, 479 const GenericDoneCallback& callback,
767 bool success, 480 bool success,
768 const std::string& error_message) { 481 const std::string& error_message) {
769 DCHECK_CURRENTLY_ON(BrowserThread::IO); 482 DCHECK_CURRENTLY_ON(BrowserThread::IO);
770 DCHECK(!callback.is_null()); 483 DCHECK(!callback.is_null());
484 DCHECK_EQ(success, error_message.empty());
771 485
772 if (error_message.empty()) { 486 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
773 DCHECK(success); 487 base::Bind(callback, success, error_message));
774 content::BrowserThread::PostTask(
775 content::BrowserThread::UI,
776 FROM_HERE,
777 base::Bind(callback, success, error_message));
778 return;
779 }
780
781 DCHECK(!success);
782
783 // Add current logging state to error message.
784 std::string error_message_with_state(error_message);
785 switch (logging_state_) {
786 case CLOSED:
787 error_message_with_state += " State=closed.";
788 break;
789 case STARTING:
790 error_message_with_state += " State=starting.";
791 break;
792 case STARTED:
793 error_message_with_state += " State=started.";
794 break;
795 case STOPPING:
796 error_message_with_state += " State=stopping.";
797 break;
798 case STOPPED:
799 error_message_with_state += " State=stopped.";
800 break;
801 }
802
803 content::BrowserThread::PostTask(
804 content::BrowserThread::UI,
805 FROM_HERE,
806 base::Bind(callback, success, error_message_with_state));
807 } 488 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698