summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc')
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc589
1 files changed, 589 insertions, 0 deletions
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc b/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc
new file mode 100644
index 00000000000..824464ffdca
--- /dev/null
+++ b/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc
@@ -0,0 +1,589 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/webrtc/webrtc_logging_controller.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/supports_user_data.h"
+#include "base/task/post_task.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "chrome/browser/media/webrtc/webrtc_event_log_manager.h"
+#include "chrome/browser/media/webrtc/webrtc_log_uploader.h"
+#include "chrome/browser/media/webrtc/webrtc_rtp_dump_handler.h"
+#include "components/webrtc_logging/browser/text_log_list.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_process_host.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#include "content/public/browser/child_process_security_policy.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+
+using webrtc_event_logging::WebRtcEventLogManager;
+
+namespace {
+
+// Key used to attach the handler to the RenderProcessHost.
+constexpr char kRenderProcessHostKey[] = "kWebRtcLoggingControllerKey";
+
+} // namespace
+
+// static
+void WebRtcLoggingController::AttachToRenderProcessHost(
+ content::RenderProcessHost* host,
+ WebRtcLogUploader* log_uploader) {
+ host->SetUserData(
+ kRenderProcessHostKey,
+ std::make_unique<base::UserDataAdapter<WebRtcLoggingController>>(
+ new WebRtcLoggingController(host->GetID(), host->GetBrowserContext(),
+ log_uploader)));
+}
+
+// static
+WebRtcLoggingController* WebRtcLoggingController::FromRenderProcessHost(
+ content::RenderProcessHost* host) {
+ return base::UserDataAdapter<WebRtcLoggingController>::Get(
+ host, kRenderProcessHostKey);
+}
+
+void WebRtcLoggingController::SetMetaData(
+ std::unique_ptr<WebRtcLogMetaDataMap> meta_data,
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ // Set the web app ID if there's a "client" key, otherwise leave it unchanged.
+ for (const auto& it : *meta_data) {
+ if (it.first == "client") {
+ web_app_id_ = static_cast<int>(base::PersistentHash(it.second));
+ text_log_handler_->SetWebAppId(web_app_id_);
+ break;
+ }
+ }
+
+ text_log_handler_->SetMetaData(std::move(meta_data), callback);
+}
+
+void WebRtcLoggingController::StartLogging(
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ // Request a log_slot from the LogUploader and start logging.
+ if (text_log_handler_->StartLogging(log_uploader_, callback)) {
+ // Start logging in the renderer. The callback has already been fired since
+ // there is no acknowledgement when the renderer actually starts.
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id_);
+
+ // OK for this to replace an existing logging_agent_ connection.
+ host->BindReceiver(logging_agent_.BindNewPipeAndPassReceiver());
+ logging_agent_.set_disconnect_handler(
+ base::BindOnce(&WebRtcLoggingController::OnAgentDisconnected, this));
+ logging_agent_->Start(receiver_.BindNewPipeAndPassRemote());
+ }
+}
+
+void WebRtcLoggingController::StopLogging(const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ // Change the state to STOPPING and disable logging in the browser.
+ if (text_log_handler_->StopLogging(callback)) {
+ // Stop logging in the renderer. OnStopped will be called when this is done
+ // to change the state from STOPPING to STOPPED and fire the callback.
+ logging_agent_->Stop();
+ }
+}
+
+void WebRtcLoggingController::UploadLog(const UploadDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ // This functions uploads both text logs (mandatory) and RTP dumps (optional).
+ // TODO(terelius): If there's no text log available (either because it hasn't
+ // been started or because it hasn't been stopped), the current implementation
+ // will fire an error callback and leave any RTP dumps in a local directory.
+ // Would it be better to upload whatever logs we have, or would the lack of
+ // an error callback make it harder to debug potential errors?
+
+ base::UmaHistogramSparse("WebRtcTextLogging.UploadStarted", web_app_id_);
+
+ base::PostTaskAndReplyWithResult(
+ log_uploader_->background_task_runner().get(), FROM_HERE,
+ base::BindOnce(log_directory_getter_),
+ base::BindOnce(&WebRtcLoggingController::TriggerUpload, this, callback));
+}
+
+void WebRtcLoggingController::UploadStoredLog(
+ const std::string& log_id,
+ const UploadDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ base::UmaHistogramSparse("WebRtcTextLogging.UploadStoredStarted",
+ web_app_id_);
+
+ // Make this a method call on log_uploader_
+
+ WebRtcLogUploader::UploadDoneData upload_data;
+ upload_data.callback = callback;
+ upload_data.local_log_id = log_id;
+ upload_data.web_app_id = web_app_id_;
+
+ log_uploader_->background_task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(
+ [](WebRtcLogUploader* log_uploader,
+ WebRtcLogUploader::UploadDoneData upload_data,
+ base::RepeatingCallback<base::FilePath(void)>
+ log_directory_getter) {
+ upload_data.paths.directory = log_directory_getter.Run();
+ log_uploader->UploadStoredLog(upload_data);
+ },
+ log_uploader_, upload_data, log_directory_getter_));
+}
+
+void WebRtcLoggingController::DiscardLog(const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ if (!text_log_handler_->ExpectLoggingStateStopped(callback)) {
+ // The callback is fired with an error message by ExpectLoggingStateStopped.
+ return;
+ }
+ log_uploader_->LoggingStoppedDontUpload();
+ text_log_handler_->DiscardLog();
+ rtp_dump_handler_.reset();
+ stop_rtp_dump_callback_.Reset();
+ FireGenericDoneCallback(callback, true, "");
+}
+
+// Stores the log locally using a hash of log_id + security origin.
+void WebRtcLoggingController::StoreLog(const std::string& log_id,
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ if (!text_log_handler_->ExpectLoggingStateStopped(callback)) {
+ // The callback is fired with an error message by ExpectLoggingStateStopped.
+ return;
+ }
+
+ if (rtp_dump_handler_) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(stop_rtp_dump_callback_, true, true));
+
+ rtp_dump_handler_->StopOngoingDumps(base::Bind(
+ &WebRtcLoggingController::StoreLogContinue, this, log_id, callback));
+ return;
+ }
+
+ StoreLogContinue(log_id, callback);
+}
+
+void WebRtcLoggingController::StoreLogContinue(
+ const std::string& log_id,
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ std::unique_ptr<WebRtcLogPaths> log_paths(new WebRtcLogPaths());
+ ReleaseRtpDumps(log_paths.get());
+
+ base::PostTaskAndReplyWithResult(
+ log_uploader_->background_task_runner().get(), FROM_HERE,
+ base::BindOnce(log_directory_getter_),
+ base::BindOnce(&WebRtcLoggingController::StoreLogInDirectory, this,
+ log_id, base::Passed(&log_paths), callback));
+}
+
+void WebRtcLoggingController::StartRtpDump(
+ RtpDumpType type,
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(stop_rtp_dump_callback_.is_null());
+
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id_);
+
+ // This call cannot fail.
+ stop_rtp_dump_callback_ = host->StartRtpDump(
+ type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
+ type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH,
+ base::Bind(&WebRtcLoggingController::OnRtpPacket, this));
+
+ if (!rtp_dump_handler_) {
+ base::PostTaskAndReplyWithResult(
+ log_uploader_->background_task_runner().get(), FROM_HERE,
+ base::BindOnce(log_directory_getter_),
+ base::BindOnce(&WebRtcLoggingController::CreateRtpDumpHandlerAndStart,
+ this, type, callback));
+ return;
+ }
+
+ DoStartRtpDump(type, callback);
+}
+
+void WebRtcLoggingController::StopRtpDump(RtpDumpType type,
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+
+ if (!rtp_dump_handler_) {
+ FireGenericDoneCallback(callback, false, "RTP dump has not been started.");
+ return;
+ }
+
+ if (!stop_rtp_dump_callback_.is_null()) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(stop_rtp_dump_callback_,
+ type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
+ type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH));
+ }
+
+ rtp_dump_handler_->StopDump(type, callback);
+}
+
+void WebRtcLoggingController::StartEventLogging(
+ const std::string& session_id,
+ size_t max_log_size_bytes,
+ int output_period_ms,
+ size_t web_app_id,
+ const StartEventLoggingCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ WebRtcEventLogManager::GetInstance()->StartRemoteLogging(
+ render_process_id_, session_id, max_log_size_bytes, output_period_ms,
+ web_app_id, callback);
+}
+
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+void WebRtcLoggingController::GetLogsDirectory(
+ const LogsDirectoryCallback& callback,
+ const LogsDirectoryErrorCallback& error_callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+ base::PostTaskAndReplyWithResult(
+ log_uploader_->background_task_runner().get(), FROM_HERE,
+ base::BindOnce(log_directory_getter_),
+ base::BindOnce(&WebRtcLoggingController::GrantLogsDirectoryAccess, this,
+ callback, error_callback));
+}
+
+void WebRtcLoggingController::GrantLogsDirectoryAccess(
+ const LogsDirectoryCallback& callback,
+ const LogsDirectoryErrorCallback& error_callback,
+ const base::FilePath& logs_path) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (logs_path.empty()) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(error_callback, "Logs directory not available"));
+ return;
+ }
+
+ storage::IsolatedContext* isolated_context =
+ storage::IsolatedContext::GetInstance();
+ DCHECK(isolated_context);
+
+ std::string registered_name;
+ storage::IsolatedContext::ScopedFSHandle file_system =
+ isolated_context->RegisterFileSystemForPath(
+ storage::kFileSystemTypeNativeLocal, std::string(), logs_path,
+ &registered_name);
+
+ // Only granting read and delete access to reduce contention with
+ // webrtcLogging APIs that modify files in that folder.
+ content::ChildProcessSecurityPolicy* policy =
+ content::ChildProcessSecurityPolicy::GetInstance();
+ policy->GrantReadFileSystem(render_process_id_, file_system.id());
+ // Delete is needed to prevent accumulation of files.
+ policy->GrantDeleteFromFileSystem(render_process_id_, file_system.id());
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(callback, file_system.id(), registered_name));
+}
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+
+void WebRtcLoggingController::OnRtpPacket(
+ std::unique_ptr<uint8_t[]> packet_header,
+ size_t header_length,
+ size_t packet_length,
+ bool incoming) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // |rtp_dump_handler_| could be null if we are waiting for the FILE thread to
+ // create/ensure the log directory.
+ if (rtp_dump_handler_) {
+ rtp_dump_handler_->OnRtpPacket(packet_header.get(), header_length,
+ packet_length, incoming);
+ }
+}
+
+void WebRtcLoggingController::OnAddMessages(
+ std::vector<chrome::mojom::WebRtcLoggingMessagePtr> messages) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (text_log_handler_->GetState() == WebRtcTextLogHandler::STARTED ||
+ text_log_handler_->GetState() == WebRtcTextLogHandler::STOPPING) {
+ for (auto& message : messages)
+ text_log_handler_->LogWebRtcLoggingMessage(message.get());
+ }
+}
+
+void WebRtcLoggingController::OnStopped() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (text_log_handler_->GetState() != WebRtcTextLogHandler::STOPPING) {
+ // If an out-of-order response is received, stop_callback_ may be invalid,
+ // and must not be invoked.
+ DLOG(ERROR) << "OnStopped invoked in state "
+ << text_log_handler_->GetState();
+ mojo::ReportBadMessage("WRLHH: OnStopped invoked in unexpected state.");
+ return;
+ }
+ text_log_handler_->StopDone();
+}
+
+WebRtcLoggingController::WebRtcLoggingController(
+ int render_process_id,
+ content::BrowserContext* browser_context,
+ WebRtcLogUploader* log_uploader)
+ : receiver_(this),
+ render_process_id_(render_process_id),
+ log_directory_getter_(base::BindRepeating(
+ &WebRtcLoggingController::GetLogDirectoryAndEnsureExists,
+ browser_context->GetPath())),
+ upload_log_on_render_close_(false),
+ text_log_handler_(
+ std::make_unique<WebRtcTextLogHandler>(render_process_id)),
+ rtp_dump_handler_(),
+ stop_rtp_dump_callback_(),
+ log_uploader_(log_uploader) {
+ DCHECK(log_uploader_);
+}
+
+WebRtcLoggingController::~WebRtcLoggingController() {
+ // If we hit this, then we might be leaking a log reference count (see
+ // ApplyForStartLogging).
+ DCHECK_EQ(WebRtcTextLogHandler::CLOSED, text_log_handler_->GetState());
+}
+
+void WebRtcLoggingController::OnAgentDisconnected() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (text_log_handler_->GetChannelIsClosing())
+ return;
+
+ switch (text_log_handler_->GetState()) {
+ case WebRtcTextLogHandler::STARTING:
+ case WebRtcTextLogHandler::STARTED:
+ case WebRtcTextLogHandler::STOPPING:
+ case WebRtcTextLogHandler::STOPPED:
+ text_log_handler_->ChannelClosing();
+ if (upload_log_on_render_close_) {
+ base::PostTaskAndReplyWithResult(
+ log_uploader_->background_task_runner().get(), FROM_HERE,
+ base::BindOnce(log_directory_getter_),
+ base::BindOnce(&WebRtcLoggingController::TriggerUpload, this,
+ UploadDoneCallback()));
+ } else {
+ log_uploader_->LoggingStoppedDontUpload();
+ text_log_handler_->DiscardLog();
+ }
+ break;
+ case WebRtcTextLogHandler::CLOSED:
+ // Do nothing
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void WebRtcLoggingController::TriggerUpload(
+ const UploadDoneCallback& callback,
+ const base::FilePath& log_directory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (rtp_dump_handler_) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(stop_rtp_dump_callback_, true, true));
+
+ rtp_dump_handler_->StopOngoingDumps(
+ base::Bind(&WebRtcLoggingController::DoUploadLogAndRtpDumps, this,
+ log_directory, callback));
+ return;
+ }
+
+ DoUploadLogAndRtpDumps(log_directory, callback);
+}
+
+void WebRtcLoggingController::StoreLogInDirectory(
+ const std::string& log_id,
+ std::unique_ptr<WebRtcLogPaths> log_paths,
+ const GenericDoneCallback& done_callback,
+ const base::FilePath& directory) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // If channel is not closing, storing is only allowed when in STOPPED state.
+ // If channel is closing, storing is allowed for all states except CLOSED.
+ const WebRtcTextLogHandler::LoggingState text_logging_state =
+ text_log_handler_->GetState();
+ const bool channel_is_closing = text_log_handler_->GetChannelIsClosing();
+ if ((!channel_is_closing &&
+ text_logging_state != WebRtcTextLogHandler::STOPPED) ||
+ (channel_is_closing &&
+ text_log_handler_->GetState() == WebRtcTextLogHandler::CLOSED)) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(done_callback, false,
+ "Logging not stopped or no log open."));
+ return;
+ }
+
+ log_paths->directory = directory;
+
+ std::unique_ptr<WebRtcLogBuffer> log_buffer;
+ std::unique_ptr<WebRtcLogMetaDataMap> meta_data;
+ text_log_handler_->ReleaseLog(&log_buffer, &meta_data);
+ CHECK(log_buffer.get()) << "State=" << text_log_handler_->GetState()
+ << ", uorc=" << upload_log_on_render_close_;
+
+ log_uploader_->background_task_runner()->PostTask(
+ FROM_HERE, base::BindOnce(&WebRtcLogUploader::LoggingStoppedDoStore,
+ base::Unretained(log_uploader_), *log_paths,
+ log_id, std::move(log_buffer),
+ std::move(meta_data), done_callback));
+}
+
+void WebRtcLoggingController::DoUploadLogAndRtpDumps(
+ const base::FilePath& log_directory,
+ const UploadDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // If channel is not closing, upload is only allowed when in STOPPED state.
+ // If channel is closing, uploading is allowed for all states except CLOSED.
+ const WebRtcTextLogHandler::LoggingState text_logging_state =
+ text_log_handler_->GetState();
+ const bool channel_is_closing = text_log_handler_->GetChannelIsClosing();
+ if ((!channel_is_closing &&
+ text_logging_state != WebRtcTextLogHandler::STOPPED) ||
+ (channel_is_closing &&
+ text_log_handler_->GetState() == WebRtcTextLogHandler::CLOSED)) {
+ // If the channel is not closing the log is expected to be uploaded, so
+ // it's considered a failure if it isn't.
+ // If the channel is closing we don't log failure to UMA for consistency,
+ // since there are other cases during shutdown were we don't get a chance
+ // to log.
+ if (!channel_is_closing) {
+ base::UmaHistogramSparse("WebRtcTextLogging.UploadFailed", web_app_id_);
+ base::UmaHistogramSparse("WebRtcTextLogging.UploadFailureReason",
+ WebRtcLogUploadFailureReason::kInvalidState);
+ }
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(callback, false, "",
+ "Logging not stopped or no log open."));
+ return;
+ }
+
+ WebRtcLogUploader::UploadDoneData upload_done_data;
+ upload_done_data.paths.directory = log_directory;
+ upload_done_data.callback = callback;
+ upload_done_data.web_app_id = web_app_id_;
+ ReleaseRtpDumps(&upload_done_data.paths);
+
+ std::unique_ptr<WebRtcLogBuffer> log_buffer;
+ std::unique_ptr<WebRtcLogMetaDataMap> meta_data;
+ text_log_handler_->ReleaseLog(&log_buffer, &meta_data);
+ CHECK(log_buffer.get()) << "State=" << text_log_handler_->GetState()
+ << ", uorc=" << upload_log_on_render_close_;
+
+ log_uploader_->background_task_runner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&WebRtcLogUploader::LoggingStoppedDoUpload,
+ base::Unretained(log_uploader_), std::move(log_buffer),
+ std::move(meta_data), upload_done_data));
+}
+
+void WebRtcLoggingController::CreateRtpDumpHandlerAndStart(
+ RtpDumpType type,
+ const GenericDoneCallback& callback,
+ const base::FilePath& dump_dir) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // |rtp_dump_handler_| may be non-null if StartRtpDump is called again before
+ // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous
+ // StartRtpDump.
+ if (!rtp_dump_handler_)
+ rtp_dump_handler_.reset(new WebRtcRtpDumpHandler(dump_dir));
+
+ DoStartRtpDump(type, callback);
+}
+
+void WebRtcLoggingController::DoStartRtpDump(
+ RtpDumpType type,
+ const GenericDoneCallback& callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(rtp_dump_handler_);
+
+ std::string error;
+ bool result = rtp_dump_handler_->StartDump(type, &error);
+ FireGenericDoneCallback(callback, result, error);
+}
+
+bool WebRtcLoggingController::ReleaseRtpDumps(WebRtcLogPaths* log_paths) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(log_paths);
+
+ if (!rtp_dump_handler_)
+ return false;
+
+ WebRtcRtpDumpHandler::ReleasedDumps rtp_dumps(
+ rtp_dump_handler_->ReleaseDumps());
+ log_paths->incoming_rtp_dump = rtp_dumps.incoming_dump_path;
+ log_paths->outgoing_rtp_dump = rtp_dumps.outgoing_dump_path;
+
+ rtp_dump_handler_.reset();
+ stop_rtp_dump_callback_.Reset();
+
+ return true;
+}
+
+void WebRtcLoggingController::FireGenericDoneCallback(
+ const GenericDoneCallback& callback,
+ bool success,
+ const std::string& error_message) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!callback.is_null());
+ DCHECK_EQ(success, error_message.empty());
+
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(callback, success, error_message));
+}
+
+// static
+base::FilePath WebRtcLoggingController::GetLogDirectoryAndEnsureExists(
+ const base::FilePath& browser_context_directory_path) {
+ DCHECK(!browser_context_directory_path.empty());
+ // Since we can be alive after the RenderProcessHost and the BrowserContext
+ // (profile) have gone away, we could create the log directory here after a
+ // profile has been deleted and removed from disk. If that happens it will be
+ // cleaned up (at a higher level) the next browser restart.
+ base::FilePath log_dir_path =
+ webrtc_logging::TextLogList::GetWebRtcLogDirectoryForBrowserContextPath(
+ browser_context_directory_path);
+ base::File::Error error;
+ if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
+ DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
+ return base::FilePath();
+ }
+ return log_dir_path;
+}