OLD | NEW |
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 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/cpu.h" | 11 #include "base/cpu.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
16 #include "base/sys_info.h" | 16 #include "base/sys_info.h" |
17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
18 #include "chrome/browser/browser_process.h" | 18 #include "chrome/browser/browser_process.h" |
19 #include "chrome/browser/chromeos/settings/cros_settings.h" | 19 #include "chrome/browser/chromeos/settings/cros_settings.h" |
20 #include "chrome/browser/media/webrtc_log_list.h" | 20 #include "chrome/browser/media/webrtc_log_list.h" |
21 #include "chrome/browser/media/webrtc_log_uploader.h" | 21 #include "chrome/browser/media/webrtc_log_uploader.h" |
22 #include "chrome/browser/media/webrtc_rtp_dump_handler.h" | |
23 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
24 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
25 #include "chrome/common/media/webrtc_logging_messages.h" | 24 #include "chrome/common/media/webrtc_logging_messages.h" |
26 #include "chrome/common/partial_circular_buffer.h" | 25 #include "chrome/common/partial_circular_buffer.h" |
27 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
28 #include "chromeos/settings/cros_settings_names.h" | 27 #include "chromeos/settings/cros_settings_names.h" |
29 #include "content/public/browser/browser_thread.h" | 28 #include "content/public/browser/browser_thread.h" |
30 #include "content/public/browser/content_browser_client.h" | 29 #include "content/public/browser/content_browser_client.h" |
31 #include "content/public/browser/gpu_data_manager.h" | 30 #include "content/public/browser/gpu_data_manager.h" |
32 #include "content/public/browser/render_process_host.h" | 31 #include "content/public/browser/render_process_host.h" |
33 #include "gpu/config/gpu_info.h" | 32 #include "gpu/config/gpu_info.h" |
34 #include "net/base/address_family.h" | 33 #include "net/base/address_family.h" |
35 #include "net/url_request/url_request_context_getter.h" | 34 #include "net/url_request/url_request_context_getter.h" |
36 | 35 |
37 #if defined(OS_LINUX) | 36 #if defined(OS_LINUX) |
38 #include "base/linux_util.h" | 37 #include "base/linux_util.h" |
39 #endif | 38 #endif |
40 | 39 |
41 #if defined(OS_MACOSX) | 40 #if defined(OS_MACOSX) |
42 #include "base/mac/mac_util.h" | 41 #include "base/mac/mac_util.h" |
43 #endif | 42 #endif |
44 | 43 |
45 #if defined(OS_CHROMEOS) | 44 #if defined(OS_CHROMEOS) |
46 #include "chromeos/system/statistics_provider.h" | 45 #include "chromeos/system/statistics_provider.h" |
47 #endif | 46 #endif |
48 | 47 |
49 using base::IntToString; | 48 using base::IntToString; |
50 using content::BrowserThread; | 49 using content::BrowserThread; |
51 | 50 |
52 namespace { | |
53 | 51 |
54 #if defined(OS_ANDROID) | 52 #if defined(OS_ANDROID) |
55 const size_t kWebRtcLogSize = 1 * 1024 * 1024; // 1 MB | 53 const size_t kWebRtcLogSize = 1 * 1024 * 1024; // 1 MB |
56 #else | 54 #else |
57 const size_t kWebRtcLogSize = 6 * 1024 * 1024; // 6 MB | 55 const size_t kWebRtcLogSize = 6 * 1024 * 1024; // 6 MB |
58 #endif | 56 #endif |
59 | 57 |
| 58 namespace { |
| 59 |
60 const char kLogNotStoppedOrNoLogOpen[] = | 60 const char kLogNotStoppedOrNoLogOpen[] = |
61 "Logging not stopped or no log open."; | 61 "Logging not stopped or no log open."; |
62 | 62 |
63 // For privacy reasons when logging IP addresses. The returned "sensitive | 63 // For privacy reasons when logging IP addresses. The returned "sensitive |
64 // string" is for release builds a string with the end stripped away. Last | 64 // string" is for release builds a string with the end stripped away. Last |
65 // octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be | 65 // octet for IPv4 and last 80 bits (5 groups) for IPv6. String will be |
66 // "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is | 66 // "1.2.3.x" and "1.2.3::" respectively. For debug builds, the string is |
67 // not stripped. | 67 // not stripped. |
68 std::string IPAddressToSensitiveString(const net::IPAddressNumber& address) { | 68 std::string IPAddressToSensitiveString(const net::IPAddressNumber& address) { |
69 #if defined(NDEBUG) | 69 #if defined(NDEBUG) |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
177 DCHECK(!callback.is_null()); | 177 DCHECK(!callback.is_null()); |
178 | 178 |
179 if (logging_state_ != STOPPED) { | 179 if (logging_state_ != STOPPED) { |
180 if (!callback.is_null()) { | 180 if (!callback.is_null()) { |
181 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 181 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
182 base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen)); | 182 base::Bind(callback, false, "", kLogNotStoppedOrNoLogOpen)); |
183 } | 183 } |
184 return; | 184 return; |
185 } | 185 } |
186 | |
187 upload_callback_ = callback; | 186 upload_callback_ = callback; |
188 logging_state_ = UPLOADING; | 187 logging_state_ = UPLOADING; |
189 content::BrowserThread::PostTaskAndReplyWithResult( | 188 content::BrowserThread::PostTaskAndReplyWithResult( |
190 content::BrowserThread::FILE, | 189 content::BrowserThread::FILE, |
191 FROM_HERE, | 190 FROM_HERE, |
192 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, | 191 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
193 this), | 192 this), |
194 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this)); | 193 base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this)); |
195 } | 194 } |
196 | 195 |
197 void WebRtcLoggingHandlerHost::UploadLogDone() { | 196 void WebRtcLoggingHandlerHost::UploadLogDone() { |
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
199 logging_state_ = CLOSED; | 198 logging_state_ = CLOSED; |
200 } | 199 } |
201 | 200 |
202 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) { | 201 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) { |
203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
204 DCHECK(!callback.is_null()); | 203 DCHECK(!callback.is_null()); |
205 | 204 |
206 GenericDoneCallback discard_callback = callback; | 205 GenericDoneCallback discard_callback = callback; |
207 if (logging_state_ != STOPPED) { | 206 if (logging_state_ != STOPPED) { |
208 FireGenericDoneCallback(&discard_callback, false, | 207 FireGenericDoneCallback(&discard_callback, false, |
209 kLogNotStoppedOrNoLogOpen); | 208 kLogNotStoppedOrNoLogOpen); |
210 return; | 209 return; |
211 } | 210 } |
212 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); | 211 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); |
213 circular_buffer_.reset(); | 212 circular_buffer_.reset(); |
214 log_buffer_.reset(); | 213 log_buffer_.reset(); |
215 logging_state_ = CLOSED; | 214 logging_state_ = CLOSED; |
216 rtp_dump_handler_.reset(); | |
217 stop_rtp_dump_callback_.Reset(); | |
218 FireGenericDoneCallback(&discard_callback, true, ""); | 215 FireGenericDoneCallback(&discard_callback, true, ""); |
219 } | 216 } |
220 | 217 |
221 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) { | 218 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) { |
222 BrowserThread::PostTask( | 219 BrowserThread::PostTask( |
223 BrowserThread::IO, | 220 BrowserThread::IO, |
224 FROM_HERE, | 221 FROM_HERE, |
225 base::Bind( | 222 base::Bind( |
226 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser, | 223 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser, |
227 this, | 224 this, |
228 WebRtcLoggingMessageData(base::Time::Now(), message))); | 225 WebRtcLoggingMessageData(base::Time::Now(), message))); |
229 } | 226 } |
230 | 227 |
231 void WebRtcLoggingHandlerHost::StartRtpDump( | 228 void WebRtcLoggingHandlerHost::StartRtpDump( |
232 RtpDumpType type, | 229 bool incoming, |
233 const GenericDoneCallback& callback, | 230 bool outgoing, |
234 const content::RenderProcessHost::WebRtcStopRtpDumpCallback& | 231 const GenericDoneCallback& callback) { |
235 stop_callback) { | 232 NOTIMPLEMENTED(); |
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
237 DCHECK(stop_rtp_dump_callback_.is_null() || | |
238 stop_rtp_dump_callback_.Equals(stop_callback)); | |
239 | |
240 stop_rtp_dump_callback_ = stop_callback; | |
241 | |
242 if (!rtp_dump_handler_) { | |
243 content::BrowserThread::PostTaskAndReplyWithResult( | |
244 content::BrowserThread::FILE, | |
245 FROM_HERE, | |
246 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, | |
247 this), | |
248 base::Bind(&WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart, | |
249 this, | |
250 type, | |
251 callback)); | |
252 return; | |
253 } | |
254 | |
255 GenericDoneCallback start_callback = callback; | |
256 DoStartRtpDump(type, &start_callback); | |
257 } | 233 } |
258 | 234 |
259 void WebRtcLoggingHandlerHost::StopRtpDump( | 235 void WebRtcLoggingHandlerHost::StopRtpDump( |
260 RtpDumpType type, | 236 bool incoming, |
| 237 bool outgoing, |
261 const GenericDoneCallback& callback) { | 238 const GenericDoneCallback& callback) { |
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 239 NOTIMPLEMENTED(); |
263 DCHECK(!callback.is_null()); | |
264 | |
265 if (!rtp_dump_handler_) { | |
266 GenericDoneCallback stop_callback = callback; | |
267 FireGenericDoneCallback( | |
268 &stop_callback, false, "RTP dump has not been started."); | |
269 return; | |
270 } | |
271 | |
272 if (!stop_rtp_dump_callback_.is_null()) { | |
273 BrowserThread::PostTask( | |
274 BrowserThread::UI, | |
275 FROM_HERE, | |
276 base::Bind(stop_rtp_dump_callback_, | |
277 type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH, | |
278 type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH)); | |
279 } | |
280 | |
281 rtp_dump_handler_->StopDump(type, callback); | |
282 } | |
283 | |
284 void WebRtcLoggingHandlerHost::OnRtpPacket(const uint8* packet_header, | |
285 size_t header_length, | |
286 size_t packet_length, | |
287 bool incoming) { | |
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
289 | |
290 scoped_ptr<uint8[]> header_data(new uint8[header_length]); | |
291 memcpy(header_data.get(), packet_header, header_length); | |
292 | |
293 BrowserThread::PostTask( | |
294 BrowserThread::IO, | |
295 FROM_HERE, | |
296 base::Bind(&WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread, | |
297 this, | |
298 base::Passed(&header_data), | |
299 header_length, | |
300 packet_length, | |
301 incoming)); | |
302 } | |
303 | |
304 void WebRtcLoggingHandlerHost::DumpRtpPacketOnIOThread( | |
305 scoped_ptr<uint8[]> packet_header, | |
306 size_t header_length, | |
307 size_t packet_length, | |
308 bool incoming) { | |
309 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
310 | |
311 // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to | |
312 // create/ensure the log directory. | |
313 if (rtp_dump_handler_) { | |
314 rtp_dump_handler_->OnRtpPacket( | |
315 packet_header.get(), header_length, packet_length, incoming); | |
316 } | |
317 } | 240 } |
318 | 241 |
319 void WebRtcLoggingHandlerHost::OnChannelClosing() { | 242 void WebRtcLoggingHandlerHost::OnChannelClosing() { |
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
321 if (logging_state_ == STARTED || logging_state_ == STOPPED) { | 244 if (logging_state_ == STARTED || logging_state_ == STOPPED) { |
322 if (upload_log_on_render_close_) { | 245 if (upload_log_on_render_close_) { |
323 logging_state_ = UPLOADING; | 246 logging_state_ = UPLOADING; |
324 logging_started_time_ = base::Time(); | 247 logging_started_time_ = base::Time(); |
325 | |
326 content::BrowserThread::PostTaskAndReplyWithResult( | 248 content::BrowserThread::PostTaskAndReplyWithResult( |
327 content::BrowserThread::FILE, | 249 content::BrowserThread::FILE, |
328 FROM_HERE, | 250 FROM_HERE, |
329 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, | 251 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
330 this), | 252 this), |
331 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this)); | 253 base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this)); |
332 } else { | 254 } else { |
333 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); | 255 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); |
334 } | 256 } |
335 } | 257 } |
336 content::BrowserMessageFilter::OnChannelClosing(); | 258 content::BrowserMessageFilter::OnChannelClosing(); |
337 } | 259 } |
338 | 260 |
339 void WebRtcLoggingHandlerHost::OnDestruct() const { | 261 void WebRtcLoggingHandlerHost::OnDestruct() const { |
340 BrowserThread::DeleteOnIOThread::Destruct(this); | 262 BrowserThread::DeleteOnIOThread::Destruct(this); |
341 } | 263 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 base::FilePath log_dir_path = | 444 base::FilePath log_dir_path = |
523 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); | 445 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); |
524 base::File::Error error; | 446 base::File::Error error; |
525 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) { | 447 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) { |
526 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error; | 448 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error; |
527 return base::FilePath(); | 449 return base::FilePath(); |
528 } | 450 } |
529 return log_dir_path; | 451 return log_dir_path; |
530 } | 452 } |
531 | 453 |
532 void WebRtcLoggingHandlerHost::TriggerUpload( | 454 void WebRtcLoggingHandlerHost::TriggerUploadLog( |
533 const base::FilePath& log_directory) { | 455 const base::FilePath& log_directory) { |
534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
535 DCHECK_EQ(logging_state_, UPLOADING); | 457 DCHECK_EQ(logging_state_, UPLOADING); |
536 | 458 |
537 if (rtp_dump_handler_) { | |
538 BrowserThread::PostTask( | |
539 BrowserThread::UI, | |
540 FROM_HERE, | |
541 base::Bind(stop_rtp_dump_callback_, true, true)); | |
542 | |
543 rtp_dump_handler_->StopOngoingDumps( | |
544 base::Bind(&WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps, | |
545 this, | |
546 log_directory)); | |
547 return; | |
548 } | |
549 | |
550 DoUploadLogAndRtpDumps(log_directory); | |
551 } | |
552 | |
553 void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps( | |
554 const base::FilePath& log_directory) { | |
555 WebRtcLogUploadDoneData upload_done_data; | 459 WebRtcLogUploadDoneData upload_done_data; |
556 upload_done_data.log_path = log_directory; | 460 upload_done_data.log_path = log_directory; |
557 | |
558 if (rtp_dump_handler_) { | |
559 WebRtcRtpDumpHandler::ReleasedDumps rtp_dumps( | |
560 rtp_dump_handler_->ReleaseDumps()); | |
561 upload_done_data.incoming_rtp_dump = rtp_dumps.incoming_dump_path; | |
562 upload_done_data.outgoing_rtp_dump = rtp_dumps.outgoing_dump_path; | |
563 | |
564 rtp_dump_handler_.reset(); | |
565 stop_rtp_dump_callback_.Reset(); | |
566 } | |
567 | |
568 upload_done_data.callback = upload_callback_; | 461 upload_done_data.callback = upload_callback_; |
569 upload_done_data.host = this; | 462 upload_done_data.host = this; |
570 upload_callback_.Reset(); | 463 upload_callback_.Reset(); |
571 | 464 |
572 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( | 465 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( |
573 &WebRtcLogUploader::LoggingStoppedDoUpload, | 466 &WebRtcLogUploader::LoggingStoppedDoUpload, |
574 base::Unretained(g_browser_process->webrtc_log_uploader()), | 467 base::Unretained(g_browser_process->webrtc_log_uploader()), |
575 Passed(&log_buffer_), | 468 Passed(&log_buffer_), |
576 kWebRtcLogSize, | 469 kWebRtcLogSize, |
577 meta_data_, | 470 meta_data_, |
578 upload_done_data)); | 471 upload_done_data)); |
579 | 472 |
580 meta_data_.clear(); | 473 meta_data_.clear(); |
581 circular_buffer_.reset(); | 474 circular_buffer_.reset(); |
582 } | 475 } |
583 | 476 |
584 void WebRtcLoggingHandlerHost::FireGenericDoneCallback( | 477 void WebRtcLoggingHandlerHost::FireGenericDoneCallback( |
585 GenericDoneCallback* callback, | 478 GenericDoneCallback* callback, bool success, |
586 bool success, | |
587 const std::string& error_message) { | 479 const std::string& error_message) { |
588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
589 DCHECK(!(*callback).is_null()); | 481 DCHECK(!(*callback).is_null()); |
590 content::BrowserThread::PostTask( | 482 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
591 content::BrowserThread::UI, | 483 base::Bind(*callback, success, |
592 FROM_HERE, | 484 error_message)); |
593 base::Bind(*callback, success, error_message)); | |
594 (*callback).Reset(); | 485 (*callback).Reset(); |
595 } | 486 } |
596 | |
597 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart( | |
598 RtpDumpType type, | |
599 GenericDoneCallback callback, | |
600 const base::FilePath& dump_dir) { | |
601 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
602 | |
603 // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before | |
604 // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous | |
605 // StartRtpDump. | |
606 if (!rtp_dump_handler_) | |
607 rtp_dump_handler_.reset(new WebRtcRtpDumpHandler(dump_dir)); | |
608 | |
609 DoStartRtpDump(type, &callback); | |
610 } | |
611 | |
612 void WebRtcLoggingHandlerHost::DoStartRtpDump(RtpDumpType type, | |
613 GenericDoneCallback* callback) { | |
614 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
615 DCHECK(rtp_dump_handler_); | |
616 | |
617 std::string error; | |
618 | |
619 bool result = rtp_dump_handler_->StartDump(type, &error); | |
620 FireGenericDoneCallback(callback, result, error); | |
621 } | |
OLD | NEW |