Commit c318f63a authored by Thomas Anderson's avatar Thomas Anderson Committed by Commit Bot

Revert "Introduce WebRtcRemoteEventLogManager"

This reverts commit 036ea24b.

Reason for revert: Causing build failure on Cast Audio Linux:
https://ci.chromium.org/buildbot/chromium.linux/Cast%20Audio%20Linux/8575

Original change's description:
> Introduce WebRtcRemoteEventLogManager
> 
> WebRtcRemoteEventLogManager is a member of WebRtcEventLogManager, in
> charge of managing remote-bound WebRTC event logs:
> * Store remote-bound log files locally, persisting them between session
>   of Chrome.
> * Uploading them when permissible (when no active peer connections are
>   present, with which the upload's increased bandwidth utilization might
>   interfere).
> * Purge remote-bound log files from local disk once an upload attempt
>   was made, regardless of whether it was successful. (Otherwise, we might
>   end up attempting multiple times, wasting bandwidth on an upload that
>   always fails after a non-trivial amount of data was pushed upstream.
>   More refined retry behavior is to be added at a later stage.)
> 
> Upcoming related work:
> * Actual implementation of the uploader (this CL deals with managing the
>   files to be uploaded, and the timing of the upload).
> * Implementation of the JS hooks.
> 
> Bug: 775415
> Change-Id: Ib5ee6081ca13d85cb8a3f38d6462bbd61a99dcae
> Reviewed-on: https://chromium-review.googlesource.com/891219
> Commit-Queue: Elad Alon <eladalon@chromium.org>
> Reviewed-by: Avi Drissman <avi@chromium.org>
> Reviewed-by: Guido Urdaneta <guidou@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#534826}

TBR=avi@chromium.org,guidou@chromium.org,terelius@chromium.org,eladalon@chromium.org

Change-Id: I2bc87f1002eac26f4c77bc5082be45db80b0449d
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 775415
Reviewed-on: https://chromium-review.googlesource.com/905826Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#534847}
parent 9353670b
......@@ -1800,10 +1800,7 @@ jumbo_source_set("browser") {
"renderer_host/p2p/socket_host_udp.h",
"webrtc/webrtc_event_log_manager.cc",
"webrtc/webrtc_event_log_manager.h",
"webrtc/webrtc_event_log_manager_common.cc",
"webrtc/webrtc_event_log_manager_common.h",
"webrtc/webrtc_event_log_uploader.cc",
"webrtc/webrtc_event_log_uploader.h",
"webrtc/webrtc_internals.cc",
"webrtc/webrtc_internals.h",
"webrtc/webrtc_internals_message_handler.cc",
......@@ -1813,8 +1810,6 @@ jumbo_source_set("browser") {
"webrtc/webrtc_internals_ui_observer.h",
"webrtc/webrtc_local_event_log_manager.cc",
"webrtc/webrtc_local_event_log_manager.h",
"webrtc/webrtc_remote_event_log_manager.cc",
"webrtc/webrtc_remote_event_log_manager.h",
]
deps += [
......
......@@ -33,7 +33,6 @@
#include "content/browser/push_messaging/push_messaging_router.h"
#include "content/browser/service_manager/common_browser_interfaces.h"
#include "content/browser/storage_partition_impl_map.h"
#include "content/browser/webrtc/webrtc_event_log_manager.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_thread.h"
......@@ -446,6 +445,7 @@ void BrowserContext::SetDownloadManagerForTesting(
void BrowserContext::Initialize(
BrowserContext* browser_context,
const base::FilePath& path) {
std::string new_id;
if (GetContentClient() && GetContentClient()->browser()) {
new_id = GetContentClient()->browser()->GetServiceUserIdForBrowserContext(
......@@ -511,13 +511,6 @@ void BrowserContext::Initialize(
RegisterCommonBrowserInterfaces(connection);
connection->Start();
}
if (!browser_context->IsOffTheRecord()) {
auto* webrtc_event_log_manager = WebRtcEventLogManager::GetInstance();
if (webrtc_event_log_manager) {
webrtc_event_log_manager->EnableForBrowserContext(browser_context);
}
}
}
// static
......@@ -568,12 +561,6 @@ BrowserContext::~BrowserContext() {
DCHECK(!GetUserData(kStoragePartitionMapKeyName))
<< "StoragePartitionMap is not shut down properly";
auto* webrtc_event_log_manager = WebRtcEventLogManager::GetInstance();
if (webrtc_event_log_manager) {
const auto id = WebRtcEventLogManager::GetBrowserContextId(this);
webrtc_event_log_manager->DisableForBrowserContext(id);
}
RemoveBrowserContextFromUserIdMap(this);
if (GetUserData(kDownloadManagerKeyName))
......
......@@ -6,57 +6,33 @@
#include "base/task_scheduler/post_task.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
namespace content {
namespace {
using BrowserContextId = WebRtcEventLogManager::BrowserContextId;
class PeerConnectionTrackerProxyImpl
: public WebRtcEventLogManager::PeerConnectionTrackerProxy {
public:
~PeerConnectionTrackerProxyImpl() override = default;
void SetWebRtcEventLoggingState(WebRtcEventLogPeerConnectionKey key,
bool event_logging_enabled) override {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(
&PeerConnectionTrackerProxyImpl::SetWebRtcEventLoggingStateInternal,
key, event_logging_enabled));
void StartEventLogOutput(WebRtcEventLogPeerConnectionKey key) override {
RenderProcessHost* host = RenderProcessHost::FromID(key.render_process_id);
if (!host) {
return; // The host has been asynchronously removed; not a problem.
}
host->Send(new PeerConnectionTracker_StartEventLogOutput(key.lid));
}
private:
static void SetWebRtcEventLoggingStateInternal(
WebRtcEventLogPeerConnectionKey key,
bool event_logging_enabled) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
void StopEventLogOutput(WebRtcEventLogPeerConnectionKey key) override {
RenderProcessHost* host = RenderProcessHost::FromID(key.render_process_id);
if (!host) {
return; // The host has been asynchronously removed; not a problem.
}
if (event_logging_enabled) {
host->Send(new PeerConnectionTracker_StartEventLogOutput(key.lid));
} else {
host->Send(new PeerConnectionTracker_StopEventLog(key.lid));
}
host->Send(new PeerConnectionTracker_StopEventLog(key.lid));
}
};
const BrowserContext* GetBrowserContext(int render_process_id) {
// Since this function is only allowed to be called from the UI thread,
// it is also reasonable to demand that it only be called with a valid
// render_process_id (since those only become invalidated on the UI thread).
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
CHECK(host);
return host->GetBrowserContext();
}
} // namespace
const size_t kWebRtcEventLogManagerUnlimitedFileSize = 0;
......@@ -64,12 +40,6 @@ const size_t kWebRtcEventLogManagerUnlimitedFileSize = 0;
WebRtcEventLogManager* WebRtcEventLogManager::g_webrtc_event_log_manager =
nullptr;
BrowserContextId WebRtcEventLogManager::GetBrowserContextId(
const BrowserContext* browser_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return reinterpret_cast<BrowserContextId>(browser_context);
}
WebRtcEventLogManager* WebRtcEventLogManager::CreateSingletonInstance() {
DCHECK(!g_webrtc_event_log_manager);
g_webrtc_event_log_manager = new WebRtcEventLogManager;
......@@ -82,9 +52,7 @@ WebRtcEventLogManager* WebRtcEventLogManager::GetInstance() {
WebRtcEventLogManager::WebRtcEventLogManager()
: local_logs_observer_(nullptr),
remote_logs_observer_(nullptr),
local_logs_manager_(this),
remote_logs_manager_(this),
pc_tracker_proxy_(new PeerConnectionTrackerProxyImpl),
task_runner_(base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND,
......@@ -95,35 +63,10 @@ WebRtcEventLogManager::WebRtcEventLogManager()
}
WebRtcEventLogManager::~WebRtcEventLogManager() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(g_webrtc_event_log_manager);
g_webrtc_event_log_manager = nullptr;
}
void WebRtcEventLogManager::EnableForBrowserContext(
const BrowserContext* browser_context,
base::OnceClosure reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!browser_context->IsOffTheRecord());
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::EnableForBrowserContextInternal,
base::Unretained(this),
GetBrowserContextId(browser_context),
browser_context->GetPath(), std::move(reply)));
}
void WebRtcEventLogManager::DisableForBrowserContext(
BrowserContextId browser_context_id,
base::OnceClosure reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::DisableForBrowserContextInternal,
base::Unretained(this), browser_context_id,
std::move(reply)));
}
void WebRtcEventLogManager::PeerConnectionAdded(
int render_process_id,
int lid,
......@@ -141,30 +84,15 @@ void WebRtcEventLogManager::PeerConnectionRemoved(
int lid,
base::OnceCallback<void(bool)> reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
if (!host) {
// TODO(eladalon): This should not be possible, but it happens in
// WebRtcMediaRecorderTest.PeerConnection. We should fix that and remove
// this check, using GetBrowserContext() instead.
// https://crbug.com/775415
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(reply), false));
}
return;
}
const BrowserContext* browser_context = host->GetBrowserContext();
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::PeerConnectionRemovedInternal,
base::Unretained(this), render_process_id, lid,
GetBrowserContextId(browser_context), std::move(reply)));
std::move(reply)));
}
void WebRtcEventLogManager::EnableLocalLogging(
const base::FilePath& base_path,
base::FilePath base_path,
size_t max_file_size_bytes,
base::OnceCallback<void(bool)> reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
......@@ -185,39 +113,16 @@ void WebRtcEventLogManager::DisableLocalLogging(
base::Unretained(this), std::move(reply)));
}
void WebRtcEventLogManager::StartRemoteLogging(
int render_process_id,
int lid,
size_t max_file_size_bytes,
base::OnceCallback<void(bool)> reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const BrowserContext* browser_context = GetBrowserContext(render_process_id);
base::Optional<BrowserContextId> browser_context_id;
if (!browser_context->IsOffTheRecord()) {
browser_context_id = GetBrowserContextId(browser_context);
}
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::StartRemoteLoggingInternal,
base::Unretained(this), render_process_id, lid,
browser_context_id, browser_context->GetPath(),
max_file_size_bytes, std::move(reply)));
}
void WebRtcEventLogManager::OnWebRtcEventLogWrite(
int render_process_id,
int lid,
const std::string& message,
base::OnceCallback<void(std::pair<bool, bool>)> reply) {
const std::string& output,
base::OnceCallback<void(bool)> reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const BrowserContext* browser_context = GetBrowserContext(render_process_id);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::OnWebRtcEventLogWriteInternal,
base::Unretained(this), render_process_id, lid,
!browser_context->IsOffTheRecord(), message,
base::Unretained(this), render_process_id, lid, output,
std::move(reply)));
}
......@@ -231,33 +136,33 @@ void WebRtcEventLogManager::SetLocalLogsObserver(
base::Unretained(this), observer, std::move(reply)));
}
void WebRtcEventLogManager::SetRemoteLogsObserver(
WebRtcRemoteEventLogsObserver* observer,
base::OnceClosure reply) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::SetRemoteLogsObserverInternal,
base::Unretained(this), observer, std::move(reply)));
}
void WebRtcEventLogManager::SetTaskRunnerForTesting(
const scoped_refptr<base::SequencedTaskRunner>& task_runner) {
// Testing function only - threading left for the caller's discretion.
task_runner_ = task_runner;
}
scoped_refptr<base::SequencedTaskRunner>&
WebRtcEventLogManager::GetTaskRunnerForTesting() {
// Testing function only - threading left for the caller's discretion.
return task_runner_;
}
void WebRtcEventLogManager::OnLocalLogStarted(PeerConnectionKey peer_connection,
const base::FilePath& file_path) {
base::FilePath file_path) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
OnLoggingTargetStarted(LoggingTarget::kLocalLogging, peer_connection);
auto it = peer_connections_with_event_logging_enabled_.find(peer_connection);
if (it != peer_connections_with_event_logging_enabled_.end()) {
// We're already receiving WebRTC event logs for this peer connection.
// Keep track that we also need it for local logging, so that if all
// other reasons (remote logging) stop holding, we still keep it on for
// local logging.
DCHECK_EQ((it->second & LoggingTarget::kLocalLogging), 0u);
it->second |= LoggingTarget::kLocalLogging;
} else {
// This is the first client for WebRTC event logging - let WebRTC know
// that it should start informing us of events.
peer_connections_with_event_logging_enabled_.emplace(
peer_connection, LoggingTarget::kLocalLogging);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::UpdateWebRtcEventLoggingState,
base::Unretained(this), peer_connection, true));
}
if (local_logs_observer_) {
local_logs_observer_->OnLocalLogStarted(peer_connection, file_path);
......@@ -268,84 +173,24 @@ void WebRtcEventLogManager::OnLocalLogStopped(
PeerConnectionKey peer_connection) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
OnLoggingTargetStopped(LoggingTarget::kLocalLogging, peer_connection);
if (local_logs_observer_) {
local_logs_observer_->OnLocalLogStopped(peer_connection);
}
}
void WebRtcEventLogManager::OnRemoteLogStarted(
PeerConnectionKey key,
const base::FilePath& file_path) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
OnLoggingTargetStarted(LoggingTarget::kRemoteLogging, key);
if (remote_logs_observer_) {
remote_logs_observer_->OnRemoteLogStarted(key, file_path);
}
}
void WebRtcEventLogManager::OnRemoteLogStopped(
WebRtcEventLogPeerConnectionKey key) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
OnLoggingTargetStopped(LoggingTarget::kRemoteLogging, key);
if (remote_logs_observer_) {
remote_logs_observer_->OnRemoteLogStopped(key);
}
}
void WebRtcEventLogManager::OnLoggingTargetStarted(LoggingTarget target,
PeerConnectionKey key) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
auto it = peer_connections_with_event_logging_enabled_.find(key);
if (it != peer_connections_with_event_logging_enabled_.end()) {
DCHECK_EQ((it->second & target), 0u);
it->second |= target;
} else {
// This is the first client for WebRTC event logging - let WebRTC know
// that it should start informing us of events.
peer_connections_with_event_logging_enabled_.emplace(key, target);
pc_tracker_proxy_->SetWebRtcEventLoggingState(key, true);
}
}
void WebRtcEventLogManager::OnLoggingTargetStopped(LoggingTarget target,
PeerConnectionKey key) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
// Record that we're no longer performing this type of logging for this PC.
auto it = peer_connections_with_event_logging_enabled_.find(key);
// Record that we're no longer performing local-logging for this PC.
auto it = peer_connections_with_event_logging_enabled_.find(peer_connection);
CHECK(it != peer_connections_with_event_logging_enabled_.end());
DCHECK_NE(it->second, 0u);
it->second &= ~target;
DCHECK_NE((it->second & LoggingTarget::kLocalLogging), 0u);
it->second &= ~LoggingTarget::kLocalLogging;
// If we're not doing any other type of logging for this peer connection,
// it's time to stop receiving notifications for it from WebRTC.
if (it->second == 0u) {
peer_connections_with_event_logging_enabled_.erase(it);
pc_tracker_proxy_->SetWebRtcEventLoggingState(key, false);
}
}
void WebRtcEventLogManager::EnableForBrowserContextInternal(
BrowserContextId browser_context_id,
const base::FilePath& browser_context_dir,
base::OnceClosure reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
remote_logs_manager_.EnableForBrowserContext(browser_context_id,
browser_context_dir);
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(reply));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WebRtcEventLogManager::UpdateWebRtcEventLoggingState,
base::Unretained(this), peer_connection, false));
}
}
void WebRtcEventLogManager::DisableForBrowserContextInternal(
BrowserContextId browser_context_id,
base::OnceClosure reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
remote_logs_manager_.DisableForBrowserContext(browser_context_id);
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(reply));
if (local_logs_observer_) {
local_logs_observer_->OnLocalLogStopped(peer_connection);
}
}
......@@ -354,36 +199,29 @@ void WebRtcEventLogManager::PeerConnectionAddedInternal(
int lid,
base::OnceCallback<void(bool)> reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
const bool local_result =
const bool result =
local_logs_manager_.PeerConnectionAdded(render_process_id, lid);
const bool remote_result =
remote_logs_manager_.PeerConnectionAdded(render_process_id, lid);
DCHECK_EQ(local_result, remote_result);
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(reply), local_result));
base::BindOnce(std::move(reply), result));
}
}
void WebRtcEventLogManager::PeerConnectionRemovedInternal(
int render_process_id,
int lid,
BrowserContextId browser_context_id,
base::OnceCallback<void(bool)> reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
const bool local_result =
const bool result =
local_logs_manager_.PeerConnectionRemoved(render_process_id, lid);
const bool remote_result = remote_logs_manager_.PeerConnectionRemoved(
render_process_id, lid, browser_context_id);
DCHECK_EQ(local_result, remote_result);
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(reply), local_result));
base::BindOnce(std::move(reply), result));
}
}
void WebRtcEventLogManager::EnableLocalLoggingInternal(
const base::FilePath& base_path,
base::FilePath base_path,
size_t max_file_size_bytes,
base::OnceCallback<void(bool)> reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
......@@ -405,51 +243,20 @@ void WebRtcEventLogManager::DisableLocalLoggingInternal(
}
}
void WebRtcEventLogManager::StartRemoteLoggingInternal(
void WebRtcEventLogManager::OnWebRtcEventLogWriteInternal(
int render_process_id,
int lid,
base::Optional<BrowserContextId> browser_context_id,
const base::FilePath& browser_context_dir,
size_t max_file_size_bytes,
int lid, // Renderer-local PeerConnection ID.
const std::string& output,
base::OnceCallback<void(bool)> reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
bool result;
if (browser_context_id) { // Not off the records.
result = remote_logs_manager_.StartRemoteLogging(
render_process_id, lid, *browser_context_id, browser_context_dir,
max_file_size_bytes);
} else {
result = false;
}
const bool result =
local_logs_manager_.EventLogWrite(render_process_id, lid, output);
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(reply), result));
}
}
void WebRtcEventLogManager::OnWebRtcEventLogWriteInternal(
int render_process_id,
int lid,
bool remote_logging_allowed,
const std::string& message,
base::OnceCallback<void(std::pair<bool, bool>)> reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
const bool local_result =
local_logs_manager_.EventLogWrite(render_process_id, lid, message);
const bool remote_result =
remote_logging_allowed
? remote_logs_manager_.EventLogWrite(render_process_id, lid, message)
: false;
if (reply) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(std::move(reply),
std::make_pair(local_result, remote_result)));
}
}
void WebRtcEventLogManager::SetLocalLogsObserverInternal(
WebRtcLocalEventLogsObserver* observer,
base::OnceClosure reply) {
......@@ -460,32 +267,28 @@ void WebRtcEventLogManager::SetLocalLogsObserverInternal(
}
}
void WebRtcEventLogManager::SetRemoteLogsObserverInternal(
WebRtcRemoteEventLogsObserver* observer,
base::OnceClosure reply) {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
remote_logs_observer_ = observer;
if (reply) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(reply));
void WebRtcEventLogManager::UpdateWebRtcEventLoggingState(
PeerConnectionKey peer_connection,
bool enabled) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (enabled) {
pc_tracker_proxy_->StartEventLogOutput(peer_connection);
} else {
pc_tracker_proxy_->StopEventLogOutput(peer_connection);
}
}
void WebRtcEventLogManager::SetClockForTesting(base::Clock* clock) {
// Testing function only - threading left for the caller's discretion.
// Testing only; no need for threading guarantees (called before anything
// could be put on the TQ).
local_logs_manager_.SetClockForTesting(clock);
}
void WebRtcEventLogManager::SetPeerConnectionTrackerProxyForTesting(
std::unique_ptr<PeerConnectionTrackerProxy> pc_tracker_proxy) {
// Testing function only - threading left for the caller's discretion.
// Testing only; no need for threading guarantees (called before anything
// could be put on the TQ).
pc_tracker_proxy_ = std::move(pc_tracker_proxy);
}
void WebRtcEventLogManager::SetWebRtcEventLogUploaderFactoryForTesting(
std::unique_ptr<WebRtcEventLogUploader::Factory> uploader_factory) {
// Testing function only - threading left for the caller's discretion.
remote_logs_manager_.SetWebRtcEventLogUploaderFactoryForTesting(
std::move(uploader_factory));
}
} // namespace content
......@@ -8,35 +8,29 @@
#include <map>
#include <memory>
#include <type_traits>
#include <utility>
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/clock.h"
#include "content/browser/webrtc/webrtc_event_log_manager_common.h"
#include "content/browser/webrtc/webrtc_local_event_log_manager.h"
#include "content/browser/webrtc/webrtc_remote_event_log_manager.h"
#include "content/common/content_export.h"
namespace content {
class BrowserContext;
// This is a singleton class running in the browser UI thread (ownership of
// the only instance lies in BrowserContext). It is in charge of writing WebRTC
// event logs to temporary files, then uploading those files to remote servers,
// as well as of writing the logs to files which were manually indicated by the
// user from the WebRTCIntenals. (A log may simulatenously be written to both,
// either, or none.)
// This is a singleton class running in the browser UI thread.
// It is in charge of writing RTC event logs to temporary files, then uploading
// those files to remote servers, as well as of writing the logs to files which
// were manually indicated by the user from the WebRTCIntenals. (A log may
// simulatenously be written to both, either, or none.)
// TODO(eladalon): This currently only supports the old use-case - locally
// stored log files. An upcoming CL will add remote-support.
// https://crbug.com/775415
class CONTENT_EXPORT WebRtcEventLogManager
: public WebRtcLocalEventLogsObserver,
public WebRtcRemoteEventLogsObserver {
: protected WebRtcLocalEventLogsObserver {
public:
using BrowserContextId = WebRtcRemoteEventLogManager::BrowserContextId;
// To turn WebRTC on and off, we go through PeerConnectionTrackerProxy. In
// order to make this toggling easily testable, PeerConnectionTrackerProxyImpl
// will send real messages to PeerConnectionTracker, whereas
......@@ -45,16 +39,10 @@ class CONTENT_EXPORT WebRtcEventLogManager
class PeerConnectionTrackerProxy {
public:
virtual ~PeerConnectionTrackerProxy() = default;
virtual void SetWebRtcEventLoggingState(WebRtcEventLogPeerConnectionKey key,
bool event_logging_enabled) = 0;
virtual void StartEventLogOutput(WebRtcEventLogPeerConnectionKey key) = 0;
virtual void StopEventLogOutput(WebRtcEventLogPeerConnectionKey key) = 0;
};
// Translate a BrowserContext into an ID, allowing associating PeerConnections
// with it while making sure that its methods would never be called outside
// of the UI thread.
static BrowserContextId GetBrowserContextId(
const BrowserContext* browser_context);
// Ensures that no previous instantiation of the class was performed, then
// instantiates the class and returns the object. Subsequent calls to
// GetInstance() will return this object.
......@@ -66,25 +54,10 @@ class CONTENT_EXPORT WebRtcEventLogManager
~WebRtcEventLogManager() override;
// Enables WebRTC event logging for a given BrowserContext:
// * Pending logs from previous sessions become eligible to be uploaded.
// * New logs for active peer connections *may* be recorded. (This does *not*
// start logging; it just makes it possible.)
// This function would typically be called during a BrowserContext's
// initialization.
// This function must not be called for an off-the-records BrowserContext.
// Local-logging is not associated with BrowserContexts, and is allowed even
// if EnableForBrowserContext is not called. That is, even for incognito mode.
void EnableForBrowserContext(const BrowserContext* browser_context,
base::OnceClosure reply = base::OnceClosure());
// Disables WebRTC event logging for a given BrowserContext. New remote-bound
// WebRTC event logs will no longer be created for this BrowserContext.
// This would typically be called when a BrowserContext is destroyed, so it
// receives the ID instead of a pointer to the BrowserContext itself, to
// ensure that it would not call any virtual functions during destruction.
void DisableForBrowserContext(BrowserContextId browser_context_id,
base::OnceClosure reply = base::OnceClosure());
// Currently, we only support manual logs initiated by the user
// through WebRTCInternals, which are stored locally.
// TODO(eladalon): Allow starting/stopping an RTC event log
// that will be uploaded to the server. https://crbug.com/775415
// Call this to let the manager know when a PeerConnection was created.
// If a reply callback is given, it will be posted back to BrowserThread::UI,
......@@ -124,7 +97,7 @@ class CONTENT_EXPORT WebRtcEventLogManager
// will get a local log file associated (specifically, we do *not* guarantee
// it would be either the oldest or the newest).
void EnableLocalLogging(
const base::FilePath& base_path,
base::FilePath base_path,
size_t max_file_size_bytes = kDefaultMaxLocalLogFileSizeBytes,
base::OnceCallback<void(bool)> reply = base::OnceCallback<void(bool)>());
......@@ -134,33 +107,18 @@ class CONTENT_EXPORT WebRtcEventLogManager
void DisableLocalLogging(
base::OnceCallback<void(bool)> reply = base::OnceCallback<void(bool)>());
// Start logging the peer connection's WebRTC events to a file, which will
// later be uploaded to a remote server. If a reply is provided, it will be
// posted back to BrowserThread::UI with the return value provided by
// WebRtcRemoteEventLogManager::StartRemoteLogging - see the comment there
// for more details.
// TODO(eladalon): Add support for injecting metadata through this call.
// https://crbug.com/775415
void StartRemoteLogging(
int render_process_id,
int lid, // Renderer-local PeerConnection ID.
size_t max_file_size_bytes,
base::OnceCallback<void(bool)> reply = base::OnceCallback<void(bool)>());
// Called when a new log fragment is sent from the renderer. This will
// potentially be written to a local WebRTC event log, a log destined for
// upload, or both.
// If a reply callback is given, it will be posted back to BrowserThread::UI
// with a pair of bools, the first bool associated with local logging and the
// second bool associated with remote-bound logging. Each bool assumes the
// value true if and only if the message was written in its entirety into
// a local/remote-bound log file.
// If a reply callback is given, it will be posted back to BrowserThread::UI,
// with true if and only if |output| was written in its entirety to both the
// local log (if any) as well as the remote log (if any). In the edge case
// that neither log file exists, false will be returned.
void OnWebRtcEventLogWrite(
int render_process_id,
int lid, // Renderer-local PeerConnection ID.
const std::string& message,
base::OnceCallback<void(std::pair<bool, bool>)> reply =
base::OnceCallback<void(std::pair<bool, bool>)>());
const std::string& output,
base::OnceCallback<void(bool)> reply = base::OnceCallback<void(bool)>());
// Set (or unset) an observer that will be informed whenever a local log file
// is started/stopped. The observer needs to be able to either run from
......@@ -171,30 +129,14 @@ class CONTENT_EXPORT WebRtcEventLogManager
void SetLocalLogsObserver(WebRtcLocalEventLogsObserver* observer,
base::OnceClosure reply = base::OnceClosure());
// Set (or unset) an observer that will be informed whenever a remote log file
// is started/stopped. Note that this refers to writing these files to disk,
// not for uploading them to the server.
// The observer needs to be able to either run from anywhere. If you need the
// code to run on specific runners or queues, have the observer post
// them there.
// If a reply callback is given, it will be posted back to BrowserThread::UI
// after the observer has been set.
void SetRemoteLogsObserver(WebRtcRemoteEventLogsObserver* observer,
base::OnceClosure reply = base::OnceClosure());
protected:
friend class WebRtcEventLogManagerTest; // Unit tests inject a frozen clock.
WebRtcEventLogManager();
// This can be used by unit tests to ensure that they would run synchronously.
void SetTaskRunnerForTesting(
const scoped_refptr<base::SequencedTaskRunner>& task_runner);
// This allows unit tests that do not wish to change the task runner to still
// check when certain operations are finished.
scoped_refptr<base::SequencedTaskRunner>& GetTaskRunnerForTesting();
private:
using PeerConnectionKey = WebRtcEventLogPeerConnectionKey;
......@@ -202,8 +144,8 @@ class CONTENT_EXPORT WebRtcEventLogManager
// we have turned WebRTC event logging on for a given peer connection, so that
// we may turn it off only when the last client no longer needs it.
enum LoggingTarget : unsigned int {
kLocalLogging = 1 << 0,
kRemoteLogging = 1 << 1
kLocalLogging = 0x01
// TODO(eladalon): Add kRemoteLogging as 0x02. https://crbug.com/775415
};
using LoggingTargetBitmap = std::underlying_type<LoggingTarget>::type;
......@@ -211,84 +153,49 @@ class CONTENT_EXPORT WebRtcEventLogManager
// WebRtcLocalEventLogsObserver implementation:
void OnLocalLogStarted(PeerConnectionKey peer_connection,
const base::FilePath& file_path) override;
base::FilePath file_path) override;
void OnLocalLogStopped(PeerConnectionKey peer_connection) override;
// WebRtcRemoteEventLogsObserver implementation:
void OnRemoteLogStarted(PeerConnectionKey key,
const base::FilePath& file_path) override;
void OnRemoteLogStopped(PeerConnectionKey key) override;
void OnLoggingTargetStarted(LoggingTarget target, PeerConnectionKey key);
void OnLoggingTargetStopped(LoggingTarget target, PeerConnectionKey key);
void EnableForBrowserContextInternal(
BrowserContextId browser_context_id,
const base::FilePath& browser_context_dir,
base::OnceClosure reply);
void DisableForBrowserContextInternal(BrowserContextId browser_context_id,
base::OnceClosure reply);
void PeerConnectionAddedInternal(int render_process_id,
int lid,
base::OnceCallback<void(bool)> reply);
void PeerConnectionRemovedInternal(int render_process_id,
int lid,
BrowserContextId browser_context_id,
base::OnceCallback<void(bool)> reply);
void EnableLocalLoggingInternal(const base::FilePath& base_path,
void EnableLocalLoggingInternal(base::FilePath base_path,
size_t max_file_size_bytes,
base::OnceCallback<void(bool)> reply);
void DisableLocalLoggingInternal(base::OnceCallback<void(bool)> reply);
void StartRemoteLoggingInternal(
int render_process_id,
int lid, // Renderer-local PeerConnection ID.
base::Optional<BrowserContextId> browser_context_id,
const base::FilePath& browser_context_dir,
size_t max_file_size_bytes,
base::OnceCallback<void(bool)> reply);
void OnWebRtcEventLogWriteInternal(
int render_process_id,
int lid, // Renderer-local PeerConnection ID.
bool remote_logging_allowed,
const std::string& message,
base::OnceCallback<void(std::pair<bool, bool>)> reply);
const std::string& output,
base::OnceCallback<void(bool)> reply);
void SetLocalLogsObserverInternal(WebRtcLocalEventLogsObserver* observer,
base::OnceClosure reply);
void SetRemoteLogsObserverInternal(WebRtcRemoteEventLogsObserver* observer,
base::OnceClosure reply);
// Send a message to WebRTC telling it to start/stop sending event-log
// notifications for a given peer connection.
void UpdateWebRtcEventLoggingState(PeerConnectionKey peer_connection,
bool enabled);
// Methods for injecting testing utilities in place of actual implementations.
// Because these are only intended for testing, we perform these changes
// asynchronously, trusting the unit tests to do so carefully enough.
void SetClockForTesting(base::Clock* clock);
void SetPeerConnectionTrackerProxyForTesting(
std::unique_ptr<PeerConnectionTrackerProxy> pc_tracker_proxy);
void SetWebRtcEventLogUploaderFactoryForTesting(
std::unique_ptr<WebRtcEventLogUploader::Factory> uploader_factory);
// Observer which will be informed whenever a local log file is started or
// stopped. Its callbacks are called synchronously from |task_runner_|,
// so the observer needs to be able to either run from any (sequenced) runner.
WebRtcLocalEventLogsObserver* local_logs_observer_;
// Observer which will be informed whenever a remote log file is started or
// stopped. Its callbacks are called synchronously from |task_runner_|,
// so the observer needs to be able to either run from any (sequenced) runner.
WebRtcRemoteEventLogsObserver* remote_logs_observer_;
// Manages local-bound logs - logs stored on the local filesystem when
// logging has been explicitly enabled by the user.
WebRtcLocalEventLogManager local_logs_manager_;
// Manages remote-bound logs - logs which will be sent to a remote server.
WebRtcRemoteEventLogManager remote_logs_manager_;
// This keeps track of which peer connections have event logging turned on
// in WebRTC, and for which client(s).
std::map<PeerConnectionKey, LoggingTargetBitmap>
......
// Copyright (c) 2018 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 "content/browser/webrtc/webrtc_event_log_manager_common.h"
#include <limits>
namespace content {
bool LogFileWriter::WriteToLogFile(LogFilesMap::iterator it,
const std::string& message) {
DCHECK_LE(message.length(),
static_cast<size_t>(std::numeric_limits<int>::max()));
// Observe the file size limit, if any. Note that base::File's interface does
// not allow writing more than numeric_limits<int>::max() bytes at a time.
int message_len = static_cast<int>(message.length()); // DCHECKed above.
LogFile& log_file = it->second;
if (log_file.max_file_size_bytes != kWebRtcEventLogManagerUnlimitedFileSize) {
DCHECK_LT(log_file.file_size_bytes, log_file.max_file_size_bytes);
const bool size_will_wrap_around =
log_file.file_size_bytes + message.length() < log_file.file_size_bytes;
const bool size_limit_will_be_exceeded =
log_file.file_size_bytes + message.length() >
log_file.max_file_size_bytes;
if (size_will_wrap_around || size_limit_will_be_exceeded) {
message_len = log_file.max_file_size_bytes - log_file.file_size_bytes;
}
}
int written = log_file.file.WriteAtCurrentPos(message.c_str(), message_len);
if (written != message_len) {
LOG(WARNING) << "WebRTC event log message couldn't be written to the "
"locally stored file in its entirety.";
CloseLogFile(it);
return false;
}
log_file.file_size_bytes += static_cast<size_t>(written);
if (log_file.max_file_size_bytes != kWebRtcEventLogManagerUnlimitedFileSize) {
DCHECK_LE(log_file.file_size_bytes, log_file.max_file_size_bytes);
if (log_file.file_size_bytes >= log_file.max_file_size_bytes) {
CloseLogFile(it);
}
}
// Truncated message due to exceeding the maximum is reported as an error -
// the caller is interested to know that not all of its message was written,
// regardless of the reason.
return (static_cast<size_t>(written) == message.length());
}
} // namespace content
......@@ -5,22 +5,12 @@
#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_COMMON_H_
#define CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_COMMON_H_
#include <map>
#include <string>
#include <tuple>
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
// This file is intended for:
// 1. Code shared between WebRtcEventLogManager, WebRtcLocalEventLogManager
// and WebRtcRemoteEventLogManager.
// 2. Code specific to either of the above classes, but which also needs
// to be seen by unit tests (such as constants).
namespace content {
CONTENT_EXPORT extern const size_t kWebRtcEventLogManagerUnlimitedFileSize;
......@@ -28,29 +18,6 @@ CONTENT_EXPORT extern const size_t kWebRtcEventLogManagerUnlimitedFileSize;
CONTENT_EXPORT extern const size_t kDefaultMaxLocalLogFileSizeBytes;
CONTENT_EXPORT extern const size_t kMaxNumberLocalWebRtcEventLogFiles;
// Limit over the number of concurrently active (currently being written to
// disk) remote-bound log files. This limits IO operations, and so it is
// applied globally (all browser contexts are limited together).
CONTENT_EXPORT extern const size_t kMaxActiveRemoteBoundWebRtcEventLogs;
// Limit over the number of pending logs (logs stored on disk and awaiting to
// be uploaded to a remote server). This limit avoids excessive storage. If a
// user chooses to have multiple profiles (and hence browser contexts) on a
// system, it is assumed that the user has enough storage to accommodate
// the increased storage consumption that comes with it. Therefore, this
// limit is applied per browser context.
CONTENT_EXPORT extern const size_t kMaxPendingRemoteBoundWebRtcEventLogs;
// The file extension to be associated with remote-bound logs while they are
// kept on local disk.
CONTENT_EXPORT extern const base::FilePath::CharType kRemoteBoundLogExtension[];
// Remote-bound event logs will not be uploaded if the time since their last
// modification (meaning the time when they were completed) exceeds this value.
// Such expired files will be purged from disk when examined.
CONTENT_EXPORT extern const base::TimeDelta
kRemoteBoundWebRtcEventLogsMaxRetention;
// For a given Chrome session, this is a unique key for PeerConnections.
// It's not, however, unique between sessions (after Chrome is restarted).
struct WebRtcEventLogPeerConnectionKey {
......@@ -75,70 +42,10 @@ struct WebRtcEventLogPeerConnectionKey {
// the paths which will be used for these logs.
class WebRtcLocalEventLogsObserver {
public:
virtual ~WebRtcLocalEventLogsObserver() = default;
virtual void OnLocalLogStarted(WebRtcEventLogPeerConnectionKey key,
const base::FilePath& file_path) = 0;
base::FilePath file_path) = 0;
virtual void OnLocalLogStopped(WebRtcEventLogPeerConnectionKey key) = 0;
protected:
virtual ~WebRtcLocalEventLogsObserver() = default;
};
// An observer for notifications of remote-bound log files being
// started/stopped. The start event would likely only interest unit tests
// (because it exposes the randomized filename to them). The stop event is of
// general interest, because it would often mean that WebRTC can stop sending
// us event logs for this peer connection.
// Some cases where OnRemoteLogStopped would be called include:
// 1. The PeerConnection has become inactive.
// 2. The file's maximum size has been reached.
// 3. Any type of error while writing to the file.
class WebRtcRemoteEventLogsObserver {
public:
virtual void OnRemoteLogStarted(WebRtcEventLogPeerConnectionKey key,
const base::FilePath& file_path) = 0;
virtual void OnRemoteLogStopped(WebRtcEventLogPeerConnectionKey key) = 0;
protected:
virtual ~WebRtcRemoteEventLogsObserver() = default;
};
struct LogFile {
LogFile(const base::FilePath& path,
base::File file,
size_t max_file_size_bytes)
: path(path),
file(std::move(file)),
max_file_size_bytes(max_file_size_bytes),
file_size_bytes(0) {}
const base::FilePath path;
base::File file;
const size_t max_file_size_bytes;
size_t file_size_bytes;
};
// WebRtcLocalEventLogManager and WebRtcRemoteEventLogManager share some logic
// when it comes to handling of files on disk.
class LogFileWriter {
protected:
using PeerConnectionKey = WebRtcEventLogPeerConnectionKey;
using LogFilesMap = std::map<PeerConnectionKey, LogFile>;
virtual ~LogFileWriter() = default;
// Given a peer connection and its associated log file, and given a log
// fragment that should be written to the log file, attempt to write to
// the log file (return value indicates success/failure).
// If an error occurs, or if the file reaches its capacity, CloseLogFile()
// will be called, closing the file.
bool WriteToLogFile(LogFilesMap::iterator it, const std::string& message);
// Called when WriteToLogFile() either encounters an error, or if the file's
// intended capacity is reached. It indicates to the inheriting class that
// the file should also be purged from its set of active log files.
// The function should return an iterator to the next element in the set
// of active logs. This makes the function more useful, allowing it to be
// used when iterating and closing several log files.
virtual LogFilesMap::iterator CloseLogFile(LogFilesMap::iterator it) = 0;
};
} // namespace content
......
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright (c) 2018 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 "content/browser/webrtc/webrtc_event_log_uploader.h"
#include "base/files/file_util.h"
#include "base/logging.h"
namespace content {
WebRtcEventLogUploaderImpl::WebRtcEventLogUploaderImpl(
const base::FilePath& path,
WebRtcEventLogUploaderObserver* observer) {
DCHECK(observer);
// TODO(eladalon): Provide an actual implementation; really upload the file.
// https://crbug.com/775415
// If the upload was successful, the file is no longer needed.
// If the upload failed, we don't want to retry, because we run the risk of
// uploading significant amounts of data once again, only for the upload to
// fail again after (as an example) wasting 50MBs of upload bandwidth.
const bool deletion_successful = base::DeleteFile(path, /*recursive=*/false);
if (!deletion_successful) {
// This is a somewhat serious (though unlikely) error, because now we'll try
// to upload this file again next time Chrome launches.
LOG(ERROR) << "Could not delete pending log file.";
}
// TODO(eladalon): Provide actual success/failure of upload.
// https://crbug.com/775415
observer->OnWebRtcEventLogUploadComplete(path, true);
}
std::unique_ptr<WebRtcEventLogUploader>
WebRtcEventLogUploaderImpl::Factory::Create(
const base::FilePath& log_file,
WebRtcEventLogUploaderObserver* observer) {
return std::make_unique<WebRtcEventLogUploaderImpl>(log_file, observer);
}
} // namespace content
// Copyright (c) 2018 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.
#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_EVENT_LOG_UPLOADER_H_
#define CONTENT_BROWSER_WEBRTC_WEBRTC_EVENT_LOG_UPLOADER_H_
#include <memory>
#include "base/files/file_path.h"
namespace content {
// A class implementing this interace can register for notification of an
// upload's eventual result (success/failure).
class WebRtcEventLogUploaderObserver {
public:
virtual void OnWebRtcEventLogUploadComplete(const base::FilePath& file_path,
bool upload_successful) = 0;
protected:
virtual ~WebRtcEventLogUploaderObserver() = default;
};
// A sublcass of this interface would take ownership of a file, and either
// upload it to a remote server (actual implementation), or pretend to do
// so (in unit tests). It will typically take on an observer of type
// WebRtcEventLogUploaderObserver, and inform it of the success or failure
// of the upload.
class WebRtcEventLogUploader {
public:
virtual ~WebRtcEventLogUploader() = default;
// Since we'll need more than one instance of the abstract
// WebRtcEventLogUploader, we'll need an abstract factory for it.
class Factory {
public:
virtual ~Factory() = default;
// Creates uploaders. The observer is passed to each call of Create,
// rather than be memorized by the factory's constructor, because factories
// created by unit tests have no visibility into the real implementation's
// observer (WebRtcRemoteEventLogManager).
virtual std::unique_ptr<WebRtcEventLogUploader> Create(
const base::FilePath& log_file,
WebRtcEventLogUploaderObserver* observer) = 0;
};
};
class WebRtcEventLogUploaderImpl : public WebRtcEventLogUploader {
public:
WebRtcEventLogUploaderImpl(const base::FilePath& path,
WebRtcEventLogUploaderObserver* observer);
~WebRtcEventLogUploaderImpl() override = default;
class Factory : public WebRtcEventLogUploader::Factory {
public:
~Factory() override = default;
std::unique_ptr<WebRtcEventLogUploader> Create(
const base::FilePath& log_file,
WebRtcEventLogUploaderObserver* observer) override;
};
};
} // namespace content
#endif // CONTENT_BROWSER_WEBRTC_WEBRTC_EVENT_LOG_UPLOADER_H_
......@@ -4,6 +4,8 @@
#include "content/browser/webrtc/webrtc_local_event_log_manager.h"
#include <limits>
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
......@@ -31,9 +33,7 @@ WebRtcLocalEventLogManager::WebRtcLocalEventLogManager(
clock_for_testing_(nullptr),
max_log_file_size_bytes_(kDefaultMaxLocalLogFileSizeBytes) {}
WebRtcLocalEventLogManager::~WebRtcLocalEventLogManager() {
// This should never actually run, except in unit tests.
}
WebRtcLocalEventLogManager::~WebRtcLocalEventLogManager() {}
bool WebRtcLocalEventLogManager::PeerConnectionAdded(int render_process_id,
int lid) {
......@@ -67,7 +67,7 @@ bool WebRtcLocalEventLogManager::PeerConnectionRemoved(int render_process_id,
if (local_log != log_files_.end()) {
// Note that success/failure of stopping the local log file is unrelated
// to the success/failure of PeerConnectionRemoved().
CloseLogFile(local_log);
StopLogFile(render_process_id, lid);
}
active_peer_connections_.erase(peer_connection);
......@@ -75,7 +75,7 @@ bool WebRtcLocalEventLogManager::PeerConnectionRemoved(int render_process_id,
return true;
}
bool WebRtcLocalEventLogManager::EnableLogging(const base::FilePath& base_path,
bool WebRtcLocalEventLogManager::EnableLogging(base::FilePath base_path,
size_t max_file_size_bytes) {
if (!base_path_.empty()) {
return false;
......@@ -113,12 +113,48 @@ bool WebRtcLocalEventLogManager::DisableLogging() {
bool WebRtcLocalEventLogManager::EventLogWrite(int render_process_id,
int lid,
const std::string& message) {
const std::string& output) {
DCHECK_LE(output.length(),
static_cast<size_t>(std::numeric_limits<int>::max()));
auto it = log_files_.find(PeerConnectionKey(render_process_id, lid));
if (it == log_files_.end()) {
return false;
}
return WriteToLogFile(it, message);
// Observe the file size limit, if any. Note that base::File's interface does
// not allow writing more than numeric_limits<int>::max() bytes at a time.
int output_len = static_cast<int>(output.length()); // DCHECKed above.
LogFile& log_file = it->second;
if (log_file.max_file_size_bytes != kWebRtcEventLogManagerUnlimitedFileSize) {
DCHECK_LT(log_file.file_size_bytes, log_file.max_file_size_bytes);
if (log_file.file_size_bytes + output.length() < log_file.file_size_bytes ||
log_file.file_size_bytes + output.length() >
log_file.max_file_size_bytes) {
output_len = log_file.max_file_size_bytes - log_file.file_size_bytes;
}
}
int written = log_file.file.WriteAtCurrentPos(output.c_str(), output_len);
if (written < 0 || written != output_len) { // Error
LOG(WARNING) << "WebRTC event log output couldn't be written to local "
"file in its entirety.";
CloseLogFile(it);
return false;
}
log_file.file_size_bytes += static_cast<size_t>(written);
if (log_file.max_file_size_bytes != kWebRtcEventLogManagerUnlimitedFileSize) {
DCHECK_LE(log_file.file_size_bytes, log_file.max_file_size_bytes);
if (log_file.file_size_bytes >= log_file.max_file_size_bytes) {
CloseLogFile(it);
}
}
// Truncated output due to exceeding the maximum is reported as an error - the
// caller is interested to know that not all of its output was written,
// regardless of the reason.
return (static_cast<size_t>(written) == output.length());
}
void WebRtcLocalEventLogManager::SetClockForTesting(base::Clock* clock) {
......@@ -158,8 +194,7 @@ void WebRtcLocalEventLogManager::StartLogFile(int render_process_id, int lid) {
// If the file was successfully created, it's now ready to be written to.
DCHECK(log_files_.find({render_process_id, lid}) == log_files_.end());
log_files_.emplace(
key, LogFile(file_path, std::move(file), max_log_file_size_bytes_));
log_files_.emplace(key, LogFile(std::move(file), max_log_file_size_bytes_));
// The observer needs to be able to run on any TaskQueue.
if (observer_) {
......@@ -167,6 +202,14 @@ void WebRtcLocalEventLogManager::StartLogFile(int render_process_id, int lid) {
}
}
void WebRtcLocalEventLogManager::StopLogFile(int render_process_id, int lid) {
auto it = log_files_.find(PeerConnectionKey(render_process_id, lid));
if (it == log_files_.end()) {
return;
}
CloseLogFile(it);
}
WebRtcLocalEventLogManager::LogFilesMap::iterator
WebRtcLocalEventLogManager::CloseLogFile(LogFilesMap::iterator it) {
const PeerConnectionKey peer_connection = it->first;
......
......@@ -16,21 +16,18 @@
namespace content {
class WebRtcLocalEventLogManager final : public LogFileWriter {
class WebRtcLocalEventLogManager {
public:
explicit WebRtcLocalEventLogManager(WebRtcLocalEventLogsObserver* observer);
~WebRtcLocalEventLogManager() override;
~WebRtcLocalEventLogManager();
bool PeerConnectionAdded(int render_process_id, int lid);
bool PeerConnectionRemoved(int render_process_id, int lid);
bool EnableLogging(const base::FilePath& base_path,
size_t max_file_size_bytes);
bool EnableLogging(base::FilePath base_path, size_t max_file_size_bytes);
bool DisableLogging();
bool EventLogWrite(int render_process_id,
int lid,
const std::string& message);
bool EventLogWrite(int render_process_id, int lid, const std::string& output);
// This function is public, but this entire class is a protected
// implementation detail of WebRtcEventLogManager, which hides this
......@@ -38,12 +35,24 @@ class WebRtcLocalEventLogManager final : public LogFileWriter {
void SetClockForTesting(base::Clock* clock);
private:
// Create a local log file.
void StartLogFile(int render_process_id, int lid);
using PeerConnectionKey = WebRtcEventLogPeerConnectionKey;
struct LogFile {
LogFile(base::File file, size_t max_file_size_bytes)
: file(std::move(file)),
max_file_size_bytes(max_file_size_bytes),
file_size_bytes(0) {}
base::File file;
const size_t max_file_size_bytes;
size_t file_size_bytes;
};
// LogFileWriter implementation. Closes a log file, flushing it to disk
// and relinquishing its handle.
LogFilesMap::iterator CloseLogFile(LogFilesMap::iterator it) override;
typedef std::map<PeerConnectionKey, LogFile> LogFilesMap;
// File handling.
void StartLogFile(int render_process_id, int lid);
void StopLogFile(int render_process_id, int lid);
LogFilesMap::iterator CloseLogFile(LogFilesMap::iterator it);
// Derives the name of a local log file. The format is:
// [user_defined]_[date]_[time]_[pid]_[lid].log
......
// Copyright (c) 2018 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 "content/browser/webrtc/webrtc_remote_event_log_manager.h"
#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
namespace content {
// TODO(eladalon): Block remote-bound logging on mobile devices.
// https://crbug.com/775415
namespace {
const base::FilePath::CharType kRemoteBoundLogSubDirectory[] =
FILE_PATH_LITERAL("webrtc_event_logs");
} // namespace
const size_t kMaxActiveRemoteBoundWebRtcEventLogs = 3;
const size_t kMaxPendingRemoteBoundWebRtcEventLogs = 5;
static_assert(kMaxActiveRemoteBoundWebRtcEventLogs <=
kMaxPendingRemoteBoundWebRtcEventLogs,
"This assumption affects unit test coverage.");
const base::TimeDelta kRemoteBoundWebRtcEventLogsMaxRetention =
base::TimeDelta::FromDays(3);
const base::FilePath::CharType kRemoteBoundLogExtension[] =
FILE_PATH_LITERAL("log");
WebRtcRemoteEventLogManager::WebRtcRemoteEventLogManager(
WebRtcRemoteEventLogsObserver* observer)
: observer_(observer),
uploader_factory_(new WebRtcEventLogUploaderImpl::Factory) {}
WebRtcRemoteEventLogManager::~WebRtcRemoteEventLogManager() {
// TODO(eladalon): Purge from disk files which were being uploaded while
// destruction took place, thereby avoiding endless attempts to upload
// the same file. https://crbug.com/775415
}
void WebRtcRemoteEventLogManager::EnableForBrowserContext(
BrowserContextId browser_context,
const base::FilePath& browser_context_dir) {
const base::FilePath remote_bound_logs_dir =
GetLogsDirectoryPath(browser_context_dir);
if (!MaybeCreateLogsDirectory(remote_bound_logs_dir)) {
LOG(WARNING)
<< "WebRtcRemoteEventLogManager couldn't create logs directory.";
return;
}
AddPendingLogs(browser_context, remote_bound_logs_dir);
}
void WebRtcRemoteEventLogManager::DisableForBrowserContext(
BrowserContextId browser_context) {
auto active_it = active_logs_counts_.find(browser_context);
if (active_it != active_logs_counts_.end()) {
active_logs_counts_.erase(active_it);
}
auto pending_it = pending_logs_counts_.find(browser_context);
if (pending_it != pending_logs_counts_.end()) {
pending_logs_counts_.erase(pending_it);
}
}
bool WebRtcRemoteEventLogManager::PeerConnectionAdded(int render_process_id,
int lid) {
PrunePendingLogs(); // Infrequent event - good opportunity to prune.
const auto result = active_peer_connections_.emplace(render_process_id, lid);
return result.second;
}
bool WebRtcRemoteEventLogManager::PeerConnectionRemoved(
int render_process_id,
int lid,
BrowserContextId browser_context) {
PrunePendingLogs(); // Infrequent event - good opportunity to prune.
const PeerConnectionKey key = PeerConnectionKey(render_process_id, lid);
auto peer_connection = active_peer_connections_.find(key);
if (peer_connection == active_peer_connections_.end()) {
return false;
}
MaybeStopRemoteLogging(render_process_id, lid, browser_context);
active_peer_connections_.erase(peer_connection);
MaybeStartUploading();
return true;
}
bool WebRtcRemoteEventLogManager::StartRemoteLogging(
int render_process_id,
int lid,
BrowserContextId browser_context,
const base::FilePath& browser_context_dir,
size_t max_file_size_bytes) {
// TODO(eladalon): Set a tighter limit (following discussion with rschriebman
// and manj). https://crbug.com/775415
if (max_file_size_bytes == kWebRtcEventLogManagerUnlimitedFileSize) {
return false;
}
const PeerConnectionKey key(render_process_id, lid);
// May not start logging inactive peer connections.
if (active_peer_connections_.find(key) == active_peer_connections_.end()) {
return false;
}
// May not restart active remote logs.
auto it = active_logs_.find(key);
if (it != active_logs_.end()) {
LOG(ERROR) << "Remote logging already underway for (" << render_process_id
<< ", " << lid << ").";
return false;
}
// This is a good opportunity to prune the list of pending logs, potentially
// making room for this file.
PrunePendingLogs();
// Limit over concurrently active logs (across BrowserContext-s).
if (active_logs_.size() >= kMaxActiveRemoteBoundWebRtcEventLogs) {
return false;
}
// Limit over the number of pending logs (per BrowserContext). We count active
// logs too, since they become pending logs once completed.
if (active_logs_counts_[browser_context] +
pending_logs_counts_[browser_context] >=
kMaxPendingRemoteBoundWebRtcEventLogs) {
return false;
}
return StartWritingLog(render_process_id, lid, browser_context,
browser_context_dir, max_file_size_bytes);
}
bool WebRtcRemoteEventLogManager::EventLogWrite(int render_process_id,
int lid,
const std::string& message) {
auto it = active_logs_.find(PeerConnectionKey(render_process_id, lid));
if (it == active_logs_.end()) {
return false;
}
return WriteToLogFile(it, message);
}
void WebRtcRemoteEventLogManager::OnWebRtcEventLogUploadComplete(
const base::FilePath& file_path,
bool upload_successful) {
// Post a task to deallocate the uploader (can't do this directly,
// because this function is a callback from the uploader), potentially
// starting a new upload for the next file.
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
&WebRtcRemoteEventLogManager::OnWebRtcEventLogUploadCompleteInternal,
base::Unretained(this)));
// TODO(eladalon): Send indication of success/failure back to JS.
// https://crbug.com/775415
}
void WebRtcRemoteEventLogManager::SetWebRtcEventLogUploaderFactoryForTesting(
std::unique_ptr<WebRtcEventLogUploader::Factory> uploader_factory) {
uploader_factory_ = std::move(uploader_factory);
// Unit tests would initially set a null uploader factory, so that files would
// be kept around. Some tests would later change to a different factory
// (e.g. one that always simulates upload failure); inthat case, we should
// get rid of the null uploader, since it never terminates.
uploader_.reset();
MaybeStartUploading();
}
base::FilePath WebRtcRemoteEventLogManager::GetLogsDirectoryPath(
const base::FilePath& browser_context_dir) {
return browser_context_dir.Append(kRemoteBoundLogSubDirectory);
}
WebRtcRemoteEventLogManager::LogFilesMap::iterator
WebRtcRemoteEventLogManager::CloseLogFile(LogFilesMap::iterator it) {
const PeerConnectionKey peer_connection = it->first;
it->second.file.Flush();
it = active_logs_.erase(it); // file.Close() called by destructor.
if (observer_) {
observer_->OnRemoteLogStopped(peer_connection);
}
MaybeStartUploading();
return it;
}
bool WebRtcRemoteEventLogManager::MaybeCreateLogsDirectory(
const base::FilePath& remote_bound_logs_dir) {
if (base::PathExists(remote_bound_logs_dir)) {
if (!base::DirectoryExists(remote_bound_logs_dir)) {
LOG(ERROR) << "Path for remote-bound logs is taken by a non-directory.";
return false;
}
} else if (!base::CreateDirectory(remote_bound_logs_dir)) {
LOG(ERROR) << "Failed to create the local directory for remote-bound logs.";
return false;
}
// TODO(eladalon): Test for appropriate permissions. https://crbug.com/775415
return true;
}
void WebRtcRemoteEventLogManager::AddPendingLogs(
BrowserContextId browser_context,
const base::FilePath& remote_bound_logs_dir) {
DCHECK(active_logs_counts_.find(browser_context) ==
active_logs_counts_.end());
DCHECK(pending_logs_counts_.find(browser_context) ==
pending_logs_counts_.end());
active_logs_counts_.emplace(browser_context, 0);
pending_logs_counts_.emplace(browser_context, 0);
base::FilePath::StringType pattern =
base::FilePath::StringType(FILE_PATH_LITERAL("*")) +
kRemoteBoundLogExtension;
base::FileEnumerator enumerator(remote_bound_logs_dir,
/*recursive=*/false,
base::FileEnumerator::FILES, pattern);
for (auto path = enumerator.Next(); !path.empty(); path = enumerator.Next()) {
const auto last_modified = enumerator.GetInfo().GetLastModifiedTime();
pending_logs_.emplace(browser_context, path, last_modified);
pending_logs_counts_[browser_context] += 1;
}
MaybeStartUploading();
}
bool WebRtcRemoteEventLogManager::StartWritingLog(
int render_process_id,
int lid,
BrowserContextId browser_context,
const base::FilePath& browser_context_dir,
size_t max_file_size_bytes) {
// Randomize a new filename. In the highly unlikely event that this filename
// is already taken, it will be treated the same way as any other failure
// to start the log file.
// TODO(eladalon): Add a unit test for above comment. https://crbug.com/775415
const std::string unique_filename =
"event_log_" + std::to_string(base::RandUint64());
const base::FilePath base_path = GetLogsDirectoryPath(browser_context_dir);
const base::FilePath file_path = base_path.AppendASCII(unique_filename)
.AddExtension(kRemoteBoundLogExtension);
// Attempt to create the file.
constexpr int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE |
base::File::FLAG_EXCLUSIVE_WRITE;
base::File file(file_path, file_flags);
if (!file.IsValid() || !file.created()) {
LOG(WARNING) << "Couldn't create and/or open remote WebRTC event log file.";
return false;
}
// Record that we're now writing this remote-bound log to this file.
const PeerConnectionKey key(render_process_id, lid);
const auto it = active_logs_.emplace(
key, LogFile(file_path, std::move(file), max_file_size_bytes));
DCHECK(it.second);
active_logs_counts_[browser_context] += 1;
observer_->OnRemoteLogStarted(PeerConnectionKey(render_process_id, lid),
file_path);
return true;
}
void WebRtcRemoteEventLogManager::MaybeStopRemoteLogging(
int render_process_id,
int lid,
BrowserContextId browser_context) {
const PeerConnectionKey key(render_process_id, lid);
const auto it = active_logs_.find(key);
if (it == active_logs_.end()) {
return;
}
it->second.file.Flush();
it->second.file.Close();
// The current time is a good enough approximation of the file's last
// modification time.
base::Time last_modified = base::Time::Now();
pending_logs_.emplace(browser_context, it->second.path, last_modified);
pending_logs_counts_[browser_context] += 1;
active_logs_.erase(it);
active_logs_counts_[browser_context] -= 1;
observer_->OnRemoteLogStopped(PeerConnectionKey(render_process_id, lid));
MaybeStartUploading();
}
void WebRtcRemoteEventLogManager::PrunePendingLogs() {
const base::Time oldest_non_expired_timestamp =
base::Time::Now() - kRemoteBoundWebRtcEventLogsMaxRetention;
for (auto it = pending_logs_.begin(); it != pending_logs_.end();) {
if (it->last_modified < oldest_non_expired_timestamp) {
if (!base::DeleteFile(it->path, /*recursive=*/false)) {
LOG(ERROR) << "Failed to delete " << it->path << ".";
}
pending_logs_counts_[it->browser_context] -= 1;
it = pending_logs_.erase(it);
} else {
++it;
}
}
}
bool WebRtcRemoteEventLogManager::UploadingAllowed() const {
return active_peer_connections_.empty();
}
void WebRtcRemoteEventLogManager::MaybeStartUploading() {
PrunePendingLogs(); // Avoid uploading freshly expired files.
if (uploader_) {
return; // Upload already underway.
}
if (pending_logs_.empty()) {
return; // Nothing to upload.
}
if (!UploadingAllowed()) {
return;
}
// The uploader takes ownership of the file; it's no longer considered to be
// pending. (If the upload fails, the log will be deleted.)
// TODO(eladalon): Add more refined retry behavior, so that we would not
// delete the log permanently if the network is just down, on the one hand,
// but also would not be uploading unlimited data on endless retries on the
// other hand. https://crbug.com/775415
uploader_ = uploader_factory_->Create(pending_logs_.begin()->path, this);
pending_logs_.erase(pending_logs_.begin());
}
void WebRtcRemoteEventLogManager::OnWebRtcEventLogUploadCompleteInternal() {
uploader_.reset();
MaybeStartUploading();
}
} // namespace content
// Copyright (c) 2018 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.
#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_REMOTE_EVENT_LOG_MANAGER_H_
#define CONTENT_BROWSER_WEBRTC_WEBRTC_REMOTE_EVENT_LOG_MANAGER_H_
#include <map>
#include <set>
#include <vector>
#include "base/time/time.h"
#include "content/browser/webrtc/webrtc_event_log_manager_common.h"
#include "content/browser/webrtc/webrtc_event_log_uploader.h"
#include "content/common/content_export.h"
namespace content {
// TODO(eladalon): Prevent uploading of logs when Chrome shutdown imminent.
// https://crbug.com/775415
class CONTENT_EXPORT WebRtcRemoteEventLogManager final
: public LogFileWriter,
public WebRtcEventLogUploaderObserver {
public:
using BrowserContextId = uintptr_t;
explicit WebRtcRemoteEventLogManager(WebRtcRemoteEventLogsObserver* observer);
~WebRtcRemoteEventLogManager() override;
// Enables remote-bound logging for a given BrowserContext. Logs stored during
// previous sessions become eligible for upload, and recording of new logs for
// peer connections associated with this BrowserContext, in the
// BrowserContext's user-data directory, becomes possible.
// This method would typically be called when a BrowserContext is initialized.
void EnableForBrowserContext(BrowserContextId browser_context,
const base::FilePath& browser_context_dir);
// Enables remote-bound logging for a given BrowserContext. Pending logs from
// earlier (while it was enabled) may still be uploaded, but no additional
// logs will be created.
void DisableForBrowserContext(BrowserContextId browser_context);
// Called to inform |this| of peer connections being added/removed.
// This information is used to:
// 1. Make decisions about when to upload previously finished logs.
// 2. When a peer connection is removed, if it was being logged, its log
// changes from ACTIVE to PENDING.
// The return value of both methods indicates only the consistency of the
// information with previously received information (e.g. can't remove a
// peer connection that was never added, etc.).
bool PeerConnectionAdded(int render_process_id, int lid);
bool PeerConnectionRemoved(int render_process_id,
int lid,
BrowserContextId browser_context);
// Attempt to start logging the WebRTC events of an active peer connection.
// Logging is subject to several restrictions:
// 1. May not log more than kMaxNumberActiveRemoteWebRtcEventLogFiles logs
// at the same time.
// 2. Each browser context may have only kMaxPendingLogFilesPerBrowserContext
// pending logs. Since active logs later become pending logs, it is also
// forbidden to start a remote-bound log that would, once completed, become
// a pending log that would exceed that limit.
// 3. The maximum file size must be sensible.
// The return value is true if all of the restrictions were observed, and if
// a file was successfully created for this log.
bool StartRemoteLogging(int render_process_id,
int lid,
BrowserContextId browser_context,
const base::FilePath& browser_context_dir,
size_t max_file_size_bytes);
// If an active remote-bound log exists for the given peer connection, this
// will append |message| to that log. If writing |message| to the log would
// exceed its maximum allowed size, |message| is first truncated.
// If the log file's capacity is exhausted as a result of this function call,
// or if a write error occurs, the file is closed, and the remote-bound log
// changes from ACTIVE to PENDING.
// True is returned if and only if |message| was written in its entirety to
// an active log.
bool EventLogWrite(int render_process_id,
int lid,
const std::string& message);
// WebRtcEventLogUploaderObserver implementation.
void OnWebRtcEventLogUploadComplete(const base::FilePath& file_path,
bool upload_successful) override;
// Unit tests may use this to inject null uploaders, or ones which are
// directly controlled by the unit test (succeed or fail according to the
// test's needs).
// Note that for simplicity's sake, this may be called from outside the
// task queue on which this object lives (WebRtcEventLogManager::task_queue_).
// Therefore, if a test calls this, it should call it before it initializes
// any BrowserContext with pending log files in its directory.
void SetWebRtcEventLogUploaderFactoryForTesting(
std::unique_ptr<WebRtcEventLogUploader::Factory> uploader_factory);
protected:
friend class WebRtcEventLogManagerTest;
// Given a BrowserContext's directory, return the path to the directory where
// we store the pending remote-bound logs associated with this BrowserContext.
static base::FilePath GetLogsDirectoryPath(
const base::FilePath& browser_context_dir);
private:
using PeerConnectionKey = WebRtcEventLogPeerConnectionKey;
struct PendingLog {
PendingLog(BrowserContextId browser_context,
const base::FilePath& path,
base::Time last_modified)
: browser_context(browser_context),
path(path),
last_modified(last_modified) {}
bool operator<(const PendingLog& other) const {
if (last_modified != other.last_modified) {
return last_modified < other.last_modified;
}
return path < other.path; // Break ties arbitrarily, but consistently.
}
const BrowserContextId browser_context; // This file's owner.
const base::FilePath path;
// |last_modified| recorded at BrowserContext initialization. Chrome will
// not modify it afterwards, and neither should the user.
const base::Time last_modified;
};
// LogFileWriter implementation. Closes an active log file, changing its
// state from ACTIVE to PENDING.
LogFilesMap::iterator CloseLogFile(LogFilesMap::iterator it) override;
// Attempts to create the directory where we'll write the logs, if it does
// not already exist. Returns true if the directory exists (either it already
// existed, or it was successfully created).
bool MaybeCreateLogsDirectory(const base::FilePath& remote_bound_logs_dir);
// Scans the user data directory associated with this BrowserContext for
// remote-bound logs that were created during previous Chrome sessions.
// This function does *not* protect against manipulation by the user,
// who might seed the directory with more files than were permissible.
void AddPendingLogs(BrowserContextId browser_context,
const base::FilePath& remote_bound_logs_dir);
// Attempts the creation of a locally stored file into which a remote-bound
// log may be written. True is returned if and only if such a file was
// successfully created.
bool StartWritingLog(int render_process_id,
int lid,
BrowserContextId browser_context,
const base::FilePath& browser_context_dir,
size_t max_file_size_bytes);
// Checks if the referenced peer connection has an associated active
// remote-bound log. If it does, the log is changed from ACTIVE to PENDING.
void MaybeStopRemoteLogging(int render_process_id,
int lid,
BrowserContextId browser_context);
// Get rid of pending logs whose age exceeds our retention policy.
// On the one hand, we want to remove expired files as soon as possible, but
// on the other hand, we don't want to waste CPU by checking this too often.
// Therefore, we prune pending files:
// 1. When a new BrowserContext is initalized, thereby also pruning the
// pending logs contributed by that BrowserContext.
// 2. Before initiating a new upload, thereby avoiding uploading a file that
// has just now expired.
// 3. On infrequent events - peer connection addition/removal, but NOT
// on something that could potentially be frequent, such as EventLogWrite.
// Note that the last modification date of a file, which is the value measured
// against for retention, is only read from disk once per file, meaning
// this check is not too expensive.
void PrunePendingLogs();
// Initiating a new upload is only allowed when there are no active peer
// connection which might be adversely affected by the bandwidth consumption
// of the upload.
// TODO(eladalon): Add support for pausing/resuming an upload when peer
// connections are added/removed after an upload was already initiated.
// https://crbug.com/775415
bool UploadingAllowed() const;
// If no upload is in progress, and if uploading is currently permissible,
// start a new upload.
void MaybeStartUploading();
// When an upload is complete, it might be time to upload the next file.
void OnWebRtcEventLogUploadCompleteInternal();
// This is used to inform WebRtcEventLogManager when remote-bound logging
// of a peer connection starts/stops, which allows WebRtcEventLogManager to
// decide when to ask WebRTC to start/stop sending event logs.
WebRtcRemoteEventLogsObserver* const observer_;
// Currently active peer connections. PeerConnections which have been closed
// are not considered active, regardless of whether they have been torn down.
std::set<PeerConnectionKey> active_peer_connections_;
// Remote-bound logs which we're currently in the process of writing to disk.
std::map<PeerConnectionKey, LogFile> active_logs_;
// Remote-bound logs which have been written to disk before (either during
// this Chrome session or during an earlier one), and which are no waiting to
// be uploaded.
std::set<PendingLog> pending_logs_;
// Null if no ongoing upload, or an uploader which owns a file, and is
// currently busy uploading it to a remote server.
std::unique_ptr<WebRtcEventLogUploader> uploader_;
// Producer of uploader objects. (In unit tests, this would create
// null-implementation uploaders, or uploaders whose behavior is controlled
// by the unit test.)
std::unique_ptr<WebRtcEventLogUploader::Factory> uploader_factory_;
// Active logs are subject to a global limit (no more than X active logs,
// regardless of which context they belong to). This makes sense, because
// performance is the limiting factor. However, pending logs are subject
// to a per-browser-context limit, because a user that chooses to run multiple
// profiles is resigning himself to increased disk utilization. We only keep
// track of active_logs_counts_ - the per-browser-context active log count -
// because active logs become pending logs once completed.
std::map<BrowserContextId, size_t> active_logs_counts_;
std::map<BrowserContextId, size_t> pending_logs_counts_;
DISALLOW_COPY_AND_ASSIGN(WebRtcRemoteEventLogManager);
};
} // namespace content
#endif // CONTENT_BROWSER_WEBRTC_WEBRTC_REMOTE_EVENT_LOG_MANAGER_H_
......@@ -7,7 +7,6 @@
#include <utility>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/test/null_task_runner.h"
#include "content/public/browser/permission_manager.h"
......@@ -46,13 +45,8 @@ class TestContextURLRequestContextGetter : public net::URLRequestContextGetter {
namespace content {
TestBrowserContext::TestBrowserContext(
base::FilePath browser_context_dir_path) {
if (browser_context_dir_path.empty()) {
EXPECT_TRUE(browser_context_dir_.CreateUniqueTempDir());
} else {
EXPECT_TRUE(browser_context_dir_.Set(browser_context_dir_path));
}
TestBrowserContext::TestBrowserContext() {
EXPECT_TRUE(browser_context_dir_.CreateUniqueTempDir());
BrowserContext::Initialize(this, browser_context_dir_.GetPath());
}
......
......@@ -25,8 +25,7 @@ class ZoomLevelDelegate;
class TestBrowserContext : public BrowserContext {
public:
explicit TestBrowserContext(
base::FilePath browser_context_dir_path = base::FilePath());
TestBrowserContext();
~TestBrowserContext() override;
// Takes ownership of the temporary directory so that it's not deleted when
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment