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" |
22 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
23 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
24 #include "chrome/common/media/webrtc_logging_messages.h" | 25 #include "chrome/common/media/webrtc_logging_messages.h" |
25 #include "chrome/common/partial_circular_buffer.h" | 26 #include "chrome/common/partial_circular_buffer.h" |
26 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
27 #include "chromeos/settings/cros_settings_names.h" | 28 #include "chromeos/settings/cros_settings_names.h" |
28 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
29 #include "content/public/browser/content_browser_client.h" | 30 #include "content/public/browser/content_browser_client.h" |
30 #include "content/public/browser/gpu_data_manager.h" | 31 #include "content/public/browser/gpu_data_manager.h" |
31 #include "content/public/browser/render_process_host.h" | 32 #include "content/public/browser/render_process_host.h" |
32 #include "gpu/config/gpu_info.h" | 33 #include "gpu/config/gpu_info.h" |
33 #include "net/base/address_family.h" | 34 #include "net/base/address_family.h" |
34 #include "net/url_request/url_request_context_getter.h" | 35 #include "net/url_request/url_request_context_getter.h" |
35 | 36 |
36 #if defined(OS_LINUX) | 37 #if defined(OS_LINUX) |
37 #include "base/linux_util.h" | 38 #include "base/linux_util.h" |
38 #endif | 39 #endif |
39 | 40 |
40 #if defined(OS_MACOSX) | 41 #if defined(OS_MACOSX) |
41 #include "base/mac/mac_util.h" | 42 #include "base/mac/mac_util.h" |
42 #endif | 43 #endif |
43 | 44 |
44 #if defined(OS_CHROMEOS) | 45 #if defined(OS_CHROMEOS) |
45 #include "chromeos/system/statistics_provider.h" | 46 #include "chromeos/system/statistics_provider.h" |
46 #endif | 47 #endif |
47 | 48 |
48 using base::IntToString; | 49 using base::IntToString; |
49 using content::BrowserThread; | 50 using content::BrowserThread; |
50 | 51 |
| 52 namespace { |
51 | 53 |
52 #if defined(OS_ANDROID) | 54 #if defined(OS_ANDROID) |
53 const size_t kWebRtcLogSize = 1 * 1024 * 1024; // 1 MB | 55 const size_t kWebRtcLogSize = 1 * 1024 * 1024; // 1 MB |
54 #else | 56 #else |
55 const size_t kWebRtcLogSize = 6 * 1024 * 1024; // 6 MB | 57 const size_t kWebRtcLogSize = 6 * 1024 * 1024; // 6 MB |
56 #endif | 58 #endif |
57 | 59 |
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 |
186 upload_callback_ = callback; | 187 upload_callback_ = callback; |
187 logging_state_ = UPLOADING; | 188 logging_state_ = UPLOADING; |
188 content::BrowserThread::PostTaskAndReplyWithResult( | 189 content::BrowserThread::PostTaskAndReplyWithResult( |
189 content::BrowserThread::FILE, | 190 content::BrowserThread::FILE, |
190 FROM_HERE, | 191 FROM_HERE, |
191 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, | 192 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
192 this), | 193 this), |
193 base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this)); | 194 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this)); |
194 } | 195 } |
195 | 196 |
196 void WebRtcLoggingHandlerHost::UploadLogDone() { | 197 void WebRtcLoggingHandlerHost::UploadLogDone() { |
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
198 logging_state_ = CLOSED; | 199 logging_state_ = CLOSED; |
199 } | 200 } |
200 | 201 |
201 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) { | 202 void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) { |
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
203 DCHECK(!callback.is_null()); | 204 DCHECK(!callback.is_null()); |
204 | 205 |
205 GenericDoneCallback discard_callback = callback; | 206 GenericDoneCallback discard_callback = callback; |
206 if (logging_state_ != STOPPED) { | 207 if (logging_state_ != STOPPED) { |
207 FireGenericDoneCallback(&discard_callback, false, | 208 FireGenericDoneCallback(&discard_callback, false, |
208 kLogNotStoppedOrNoLogOpen); | 209 kLogNotStoppedOrNoLogOpen); |
209 return; | 210 return; |
210 } | 211 } |
211 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); | 212 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); |
212 circular_buffer_.reset(); | 213 circular_buffer_.reset(); |
213 log_buffer_.reset(); | 214 log_buffer_.reset(); |
214 logging_state_ = CLOSED; | 215 logging_state_ = CLOSED; |
| 216 rtp_dump_handler_.reset(); |
| 217 stop_rtp_dump_callback_.Reset(); |
215 FireGenericDoneCallback(&discard_callback, true, ""); | 218 FireGenericDoneCallback(&discard_callback, true, ""); |
216 } | 219 } |
217 | 220 |
218 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) { | 221 void WebRtcLoggingHandlerHost::LogMessage(const std::string& message) { |
219 BrowserThread::PostTask( | 222 BrowserThread::PostTask( |
220 BrowserThread::IO, | 223 BrowserThread::IO, |
221 FROM_HERE, | 224 FROM_HERE, |
222 base::Bind( | 225 base::Bind( |
223 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser, | 226 &WebRtcLoggingHandlerHost::AddLogMessageFromBrowser, |
224 this, | 227 this, |
225 WebRtcLoggingMessageData(base::Time::Now(), message))); | 228 WebRtcLoggingMessageData(base::Time::Now(), message))); |
226 } | 229 } |
227 | 230 |
228 void WebRtcLoggingHandlerHost::StartRtpDump( | 231 void WebRtcLoggingHandlerHost::StartRtpDump( |
229 bool incoming, | 232 RtpDumpType type, |
230 bool outgoing, | 233 const GenericDoneCallback& callback, |
231 const GenericDoneCallback& callback) { | 234 const content::RenderProcessHost::WebRtcStopRtpDumpCallback& |
232 NOTIMPLEMENTED(); | 235 stop_callback) { |
| 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); |
233 } | 257 } |
234 | 258 |
235 void WebRtcLoggingHandlerHost::StopRtpDump( | 259 void WebRtcLoggingHandlerHost::StopRtpDump( |
236 bool incoming, | 260 RtpDumpType type, |
237 bool outgoing, | |
238 const GenericDoneCallback& callback) { | 261 const GenericDoneCallback& callback) { |
239 NOTIMPLEMENTED(); | 262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 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 } |
240 } | 317 } |
241 | 318 |
242 void WebRtcLoggingHandlerHost::OnChannelClosing() { | 319 void WebRtcLoggingHandlerHost::OnChannelClosing() { |
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
244 if (logging_state_ == STARTED || logging_state_ == STOPPED) { | 321 if (logging_state_ == STARTED || logging_state_ == STOPPED) { |
245 if (upload_log_on_render_close_) { | 322 if (upload_log_on_render_close_) { |
246 logging_state_ = UPLOADING; | 323 logging_state_ = UPLOADING; |
247 logging_started_time_ = base::Time(); | 324 logging_started_time_ = base::Time(); |
| 325 |
248 content::BrowserThread::PostTaskAndReplyWithResult( | 326 content::BrowserThread::PostTaskAndReplyWithResult( |
249 content::BrowserThread::FILE, | 327 content::BrowserThread::FILE, |
250 FROM_HERE, | 328 FROM_HERE, |
251 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, | 329 base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists, |
252 this), | 330 this), |
253 base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this)); | 331 base::Bind(&WebRtcLoggingHandlerHost::TriggerUpload, this)); |
254 } else { | 332 } else { |
255 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); | 333 g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload(); |
256 } | 334 } |
257 } | 335 } |
258 content::BrowserMessageFilter::OnChannelClosing(); | 336 content::BrowserMessageFilter::OnChannelClosing(); |
259 } | 337 } |
260 | 338 |
261 void WebRtcLoggingHandlerHost::OnDestruct() const { | 339 void WebRtcLoggingHandlerHost::OnDestruct() const { |
262 BrowserThread::DeleteOnIOThread::Destruct(this); | 340 BrowserThread::DeleteOnIOThread::Destruct(this); |
263 } | 341 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 base::FilePath log_dir_path = | 523 base::FilePath log_dir_path = |
446 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); | 524 WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); |
447 base::File::Error error; | 525 base::File::Error error; |
448 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) { | 526 if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) { |
449 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error; | 527 DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error; |
450 return base::FilePath(); | 528 return base::FilePath(); |
451 } | 529 } |
452 return log_dir_path; | 530 return log_dir_path; |
453 } | 531 } |
454 | 532 |
455 void WebRtcLoggingHandlerHost::TriggerUploadLog( | 533 void WebRtcLoggingHandlerHost::TriggerUpload( |
456 const base::FilePath& log_directory) { | 534 const base::FilePath& log_directory) { |
457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
458 DCHECK_EQ(logging_state_, UPLOADING); | 536 DCHECK_EQ(logging_state_, UPLOADING); |
459 | 537 |
| 538 if (rtp_dump_handler_) { |
| 539 BrowserThread::PostTask( |
| 540 BrowserThread::UI, |
| 541 FROM_HERE, |
| 542 base::Bind(stop_rtp_dump_callback_, true, true)); |
| 543 |
| 544 rtp_dump_handler_->StopOngoingDumps( |
| 545 base::Bind(&WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps, |
| 546 this, |
| 547 log_directory)); |
| 548 return; |
| 549 } |
| 550 |
| 551 DoUploadLogAndRtpDumps(log_directory); |
| 552 } |
| 553 |
| 554 void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps( |
| 555 const base::FilePath& log_directory) { |
460 WebRtcLogUploadDoneData upload_done_data; | 556 WebRtcLogUploadDoneData upload_done_data; |
461 upload_done_data.log_path = log_directory; | 557 upload_done_data.log_path = log_directory; |
| 558 |
| 559 if (rtp_dump_handler_) { |
| 560 WebRtcRtpDumpHandler::ReleasedDumps rtp_dumps( |
| 561 rtp_dump_handler_->ReleaseDumps()); |
| 562 upload_done_data.incoming_rtp_dump = rtp_dumps.incoming_dump_path; |
| 563 upload_done_data.outgoing_rtp_dump = rtp_dumps.outgoing_dump_path; |
| 564 |
| 565 rtp_dump_handler_.reset(); |
| 566 stop_rtp_dump_callback_.Reset(); |
| 567 } |
| 568 |
462 upload_done_data.callback = upload_callback_; | 569 upload_done_data.callback = upload_callback_; |
463 upload_done_data.host = this; | 570 upload_done_data.host = this; |
464 upload_callback_.Reset(); | 571 upload_callback_.Reset(); |
465 | 572 |
466 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( | 573 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind( |
467 &WebRtcLogUploader::LoggingStoppedDoUpload, | 574 &WebRtcLogUploader::LoggingStoppedDoUpload, |
468 base::Unretained(g_browser_process->webrtc_log_uploader()), | 575 base::Unretained(g_browser_process->webrtc_log_uploader()), |
469 Passed(&log_buffer_), | 576 Passed(&log_buffer_), |
470 kWebRtcLogSize, | 577 kWebRtcLogSize, |
471 meta_data_, | 578 meta_data_, |
472 upload_done_data)); | 579 upload_done_data)); |
473 | 580 |
474 meta_data_.clear(); | 581 meta_data_.clear(); |
475 circular_buffer_.reset(); | 582 circular_buffer_.reset(); |
476 } | 583 } |
477 | 584 |
478 void WebRtcLoggingHandlerHost::FireGenericDoneCallback( | 585 void WebRtcLoggingHandlerHost::FireGenericDoneCallback( |
479 GenericDoneCallback* callback, bool success, | 586 GenericDoneCallback* callback, |
| 587 bool success, |
480 const std::string& error_message) { | 588 const std::string& error_message) { |
481 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 589 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
482 DCHECK(!(*callback).is_null()); | 590 DCHECK(!(*callback).is_null()); |
483 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 591 content::BrowserThread::PostTask( |
484 base::Bind(*callback, success, | 592 content::BrowserThread::UI, |
485 error_message)); | 593 FROM_HERE, |
| 594 base::Bind(*callback, success, error_message)); |
486 (*callback).Reset(); | 595 (*callback).Reset(); |
487 } | 596 } |
| 597 |
| 598 void WebRtcLoggingHandlerHost::CreateRtpDumpHandlerAndStart( |
| 599 RtpDumpType type, |
| 600 GenericDoneCallback callback, |
| 601 const base::FilePath& dump_dir) { |
| 602 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 603 |
| 604 // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before |
| 605 // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous |
| 606 // StartRtpDump. |
| 607 if (!rtp_dump_handler_) |
| 608 rtp_dump_handler_.reset(new WebRtcRtpDumpHandler(dump_dir)); |
| 609 |
| 610 DoStartRtpDump(type, &callback); |
| 611 } |
| 612 |
| 613 void WebRtcLoggingHandlerHost::DoStartRtpDump(RtpDumpType type, |
| 614 GenericDoneCallback* callback) { |
| 615 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 616 DCHECK(rtp_dump_handler_); |
| 617 |
| 618 std::string error; |
| 619 |
| 620 bool result = rtp_dump_handler_->StartDump(type, &error); |
| 621 FireGenericDoneCallback(callback, result, error); |
| 622 } |
OLD | NEW |