Record the Capture Mode (sensitivity level) in NetLog JSON
It is possible to infer the capture mode (which limits how much sensitive information is stored in a NetLog file) by scanning emitted events, but explicitly recording the capture mode in the file enables automated tooling to more easily classify logs. Bug: 1057773 Change-Id: Ia36fb2cbb091cf2b4a940fbe48fce87269438c33 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2087702 Reviewed-by: Matt Menke <mmenke@chromium.org> Reviewed-by: John Abd-El-Malek <jam@chromium.org> Reviewed-by: Eric Roman <eroman@chromium.org> Commit-Queue: Eric Lawrence [MSFT] <ericlaw@microsoft.com> Cr-Commit-Position: refs/heads/master@{#815833}
This commit is contained in:

committed by
Commit Bot

parent
2b39bbccf9
commit
0afff12340
components/cronet
fuchsia/engine/browser
google_apis/gcm/tools
net/log
services/network
@ -620,15 +620,15 @@ void CronetURLRequestContext::NetworkTasks::StartNetLog(
|
||||
// Do nothing if already logging to a file.
|
||||
if (net_log_file_observer_)
|
||||
return;
|
||||
net_log_file_observer_ = net::FileNetLogObserver::CreateUnbounded(
|
||||
file_path, /*constants=*/nullptr);
|
||||
CreateNetLogEntriesForActiveObjects({context_.get()},
|
||||
net_log_file_observer_.get());
|
||||
|
||||
net::NetLogCaptureMode capture_mode =
|
||||
include_socket_bytes ? net::NetLogCaptureMode::kEverything
|
||||
: net::NetLogCaptureMode::kDefault;
|
||||
net_log_file_observer_->StartObserving(g_net_log.Get().net_log(),
|
||||
capture_mode);
|
||||
net_log_file_observer_ = net::FileNetLogObserver::CreateUnbounded(
|
||||
file_path, capture_mode, /*constants=*/nullptr);
|
||||
CreateNetLogEntriesForActiveObjects({context_.get()},
|
||||
net_log_file_observer_.get());
|
||||
net_log_file_observer_->StartObserving(g_net_log.Get().net_log());
|
||||
}
|
||||
|
||||
void CronetURLRequestContext::NetworkTasks::StartNetLogToBoundedFile(
|
||||
@ -657,17 +657,16 @@ void CronetURLRequestContext::NetworkTasks::StartNetLogToBoundedFile(
|
||||
}
|
||||
}
|
||||
|
||||
net::NetLogCaptureMode capture_mode =
|
||||
include_socket_bytes ? net::NetLogCaptureMode::kEverything
|
||||
: net::NetLogCaptureMode::kDefault;
|
||||
net_log_file_observer_ = net::FileNetLogObserver::CreateBounded(
|
||||
file_path, size, /*constants=*/nullptr);
|
||||
file_path, size, capture_mode, /*constants=*/nullptr);
|
||||
|
||||
CreateNetLogEntriesForActiveObjects({context_.get()},
|
||||
net_log_file_observer_.get());
|
||||
|
||||
net::NetLogCaptureMode capture_mode =
|
||||
include_socket_bytes ? net::NetLogCaptureMode::kEverything
|
||||
: net::NetLogCaptureMode::kDefault;
|
||||
net_log_file_observer_->StartObserving(g_net_log.Get().net_log(),
|
||||
capture_mode);
|
||||
net_log_file_observer_->StartObserving(g_net_log.Get().net_log());
|
||||
}
|
||||
|
||||
void CronetURLRequestContext::NetworkTasks::StopNetLog() {
|
||||
|
@ -178,9 +178,8 @@ void CronetEnvironment::StartNetLogOnNetworkThread(const base::FilePath& path,
|
||||
: net::NetLogCaptureMode::kDefault;
|
||||
|
||||
file_net_log_observer_ =
|
||||
net::FileNetLogObserver::CreateUnbounded(path, nullptr);
|
||||
file_net_log_observer_->StartObserving(main_context_->net_log(),
|
||||
capture_mode);
|
||||
net::FileNetLogObserver::CreateUnbounded(path, capture_mode, nullptr);
|
||||
file_net_log_observer_->StartObserving(main_context_->net_log());
|
||||
LOG(WARNING) << "Started NetLog";
|
||||
}
|
||||
|
||||
|
@ -42,8 +42,8 @@ WebEngineNetLogObserver::WebEngineNetLogObserver(
|
||||
if (!log_path.empty()) {
|
||||
net::NetLogCaptureMode capture_mode = net::NetLogCaptureMode::kDefault;
|
||||
file_net_log_observer_ = net::FileNetLogObserver::CreateUnbounded(
|
||||
log_path, GetWebEngineConstants());
|
||||
file_net_log_observer_->StartObserving(net::NetLog::Get(), capture_mode);
|
||||
log_path, capture_mode, GetWebEngineConstants());
|
||||
file_net_log_observer_->StartObserving(net::NetLog::Get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,10 +338,11 @@ void MCSProbe::UpdateCallback(bool success) {
|
||||
void MCSProbe::InitializeNetworkState() {
|
||||
if (command_line_.HasSwitch(kLogFileSwitch)) {
|
||||
base::FilePath log_path = command_line_.GetSwitchValuePath(kLogFileSwitch);
|
||||
logger_ = net::FileNetLogObserver::CreateUnbounded(log_path, nullptr);
|
||||
net::NetLogCaptureMode capture_mode =
|
||||
net::NetLogCaptureMode::kIncludeSensitive;
|
||||
logger_->StartObserving(net_log_, capture_mode);
|
||||
logger_ = net::FileNetLogObserver::CreateUnbounded(log_path, capture_mode,
|
||||
nullptr);
|
||||
logger_->StartObserving(net_log_);
|
||||
}
|
||||
|
||||
net::URLRequestContextBuilder builder;
|
||||
|
@ -333,17 +333,19 @@ class FileNetLogObserver::FileWriter {
|
||||
std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateBounded(
|
||||
const base::FilePath& log_path,
|
||||
uint64_t max_total_size,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants) {
|
||||
return CreateInternal(log_path, SiblingInprogressDirectory(log_path),
|
||||
base::nullopt, max_total_size, kDefaultNumFiles,
|
||||
std::move(constants));
|
||||
capture_mode, std::move(constants));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateUnbounded(
|
||||
const base::FilePath& log_path,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants) {
|
||||
return CreateInternal(log_path, base::FilePath(), base::nullopt, kNoLimit,
|
||||
kDefaultNumFiles, std::move(constants));
|
||||
kDefaultNumFiles, capture_mode, std::move(constants));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileNetLogObserver>
|
||||
@ -351,19 +353,23 @@ FileNetLogObserver::CreateBoundedPreExisting(
|
||||
const base::FilePath& inprogress_dir_path,
|
||||
base::File output_file,
|
||||
uint64_t max_total_size,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants) {
|
||||
return CreateInternal(base::FilePath(), inprogress_dir_path,
|
||||
base::make_optional<base::File>(std::move(output_file)),
|
||||
max_total_size, kDefaultNumFiles, std::move(constants));
|
||||
max_total_size, kDefaultNumFiles, capture_mode,
|
||||
std::move(constants));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileNetLogObserver>
|
||||
FileNetLogObserver::CreateUnboundedPreExisting(
|
||||
base::File output_file,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants) {
|
||||
return CreateInternal(base::FilePath(), base::FilePath(),
|
||||
base::make_optional<base::File>(std::move(output_file)),
|
||||
kNoLimit, kDefaultNumFiles, std::move(constants));
|
||||
kNoLimit, kDefaultNumFiles, capture_mode,
|
||||
std::move(constants));
|
||||
}
|
||||
|
||||
FileNetLogObserver::~FileNetLogObserver() {
|
||||
@ -378,9 +384,8 @@ FileNetLogObserver::~FileNetLogObserver() {
|
||||
file_task_runner_->DeleteSoon(FROM_HERE, file_writer_.release());
|
||||
}
|
||||
|
||||
void FileNetLogObserver::StartObserving(NetLog* net_log,
|
||||
NetLogCaptureMode capture_mode) {
|
||||
net_log->AddObserver(this, capture_mode);
|
||||
void FileNetLogObserver::StartObserving(NetLog* net_log) {
|
||||
net_log->AddObserver(this, capture_mode_);
|
||||
}
|
||||
|
||||
void FileNetLogObserver::StopObserving(std::unique_ptr<base::Value> polled_data,
|
||||
@ -425,10 +430,11 @@ std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateBoundedForTests(
|
||||
const base::FilePath& log_path,
|
||||
uint64_t max_total_size,
|
||||
size_t total_num_event_files,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants) {
|
||||
return CreateInternal(log_path, SiblingInprogressDirectory(log_path),
|
||||
base::nullopt, max_total_size, total_num_event_files,
|
||||
std::move(constants));
|
||||
capture_mode, std::move(constants));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateInternal(
|
||||
@ -437,6 +443,7 @@ std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateInternal(
|
||||
base::Optional<base::File> pre_existing_log_file,
|
||||
uint64_t max_total_size,
|
||||
size_t total_num_event_files,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants) {
|
||||
DCHECK_GT(total_num_event_files, 0u);
|
||||
|
||||
@ -469,25 +476,43 @@ std::unique_ptr<FileNetLogObserver> FileNetLogObserver::CreateInternal(
|
||||
return base::WrapUnique(new FileNetLogObserver(
|
||||
file_task_runner, std::move(file_writer),
|
||||
base::WrapRefCounted(new WriteQueue(write_queue_memory_max)),
|
||||
std::move(constants)));
|
||||
capture_mode, std::move(constants)));
|
||||
}
|
||||
|
||||
FileNetLogObserver::FileNetLogObserver(
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
std::unique_ptr<FileWriter> file_writer,
|
||||
scoped_refptr<WriteQueue> write_queue,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants)
|
||||
: file_task_runner_(std::move(file_task_runner)),
|
||||
write_queue_(std::move(write_queue)),
|
||||
file_writer_(std::move(file_writer)) {
|
||||
file_writer_(std::move(file_writer)),
|
||||
capture_mode_(capture_mode) {
|
||||
if (!constants)
|
||||
constants = base::Value::ToUniquePtrValue(GetNetConstants());
|
||||
|
||||
DCHECK(!constants->FindKey("logCaptureMode"));
|
||||
constants->SetStringKey("logCaptureMode", CaptureModeToString(capture_mode));
|
||||
file_task_runner_->PostTask(
|
||||
FROM_HERE, base::BindOnce(&FileNetLogObserver::FileWriter::Initialize,
|
||||
base::Unretained(file_writer_.get()),
|
||||
std::move(constants)));
|
||||
}
|
||||
|
||||
std::string FileNetLogObserver::CaptureModeToString(NetLogCaptureMode mode) {
|
||||
switch (mode) {
|
||||
case NetLogCaptureMode::kDefault:
|
||||
return "Default";
|
||||
case NetLogCaptureMode::kIncludeSensitive:
|
||||
return "IncludeSensitive";
|
||||
case NetLogCaptureMode::kEverything:
|
||||
return "Everything";
|
||||
}
|
||||
NOTREACHED();
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
FileNetLogObserver::WriteQueue::WriteQueue(uint64_t memory_max)
|
||||
: memory_(0), memory_max_(memory_max) {}
|
||||
|
||||
|
@ -58,11 +58,13 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
|
||||
static std::unique_ptr<FileNetLogObserver> CreateBounded(
|
||||
const base::FilePath& log_path,
|
||||
uint64_t max_total_size,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
// Shortcut for calling CreateBounded() with kNoLimit.
|
||||
static std::unique_ptr<FileNetLogObserver> CreateUnbounded(
|
||||
const base::FilePath& log_path,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
// Creates a bounded log that writes to a pre-existing file (truncating
|
||||
@ -73,18 +75,20 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
|
||||
const base::FilePath& inprogress_dir_path,
|
||||
base::File output_file,
|
||||
uint64_t max_total_size,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
// Creates an unbounded log that writes to a pre-existing file (truncating
|
||||
// it to start with, and closing it upon completion).
|
||||
static std::unique_ptr<FileNetLogObserver> CreateUnboundedPreExisting(
|
||||
base::File output_file,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
~FileNetLogObserver() override;
|
||||
|
||||
// Attaches this observer to |net_log| and begins observing events.
|
||||
void StartObserving(NetLog* net_log, NetLogCaptureMode capture_mode);
|
||||
void StartObserving(NetLog* net_log);
|
||||
|
||||
// Stops observing net_log() and closes the output file(s). Must be called
|
||||
// after StartObserving. Should be called before destruction of the
|
||||
@ -112,6 +116,7 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
|
||||
const base::FilePath& log_path,
|
||||
uint64_t max_total_size,
|
||||
size_t total_num_event_files,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
private:
|
||||
@ -124,13 +129,17 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
|
||||
base::Optional<base::File> pre_existing_out_file,
|
||||
uint64_t max_total_size,
|
||||
size_t total_num_event_files,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
FileNetLogObserver(scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
std::unique_ptr<FileWriter> file_writer,
|
||||
scoped_refptr<WriteQueue> write_queue,
|
||||
NetLogCaptureMode capture_mode,
|
||||
std::unique_ptr<base::Value> constants);
|
||||
|
||||
static std::string CaptureModeToString(NetLogCaptureMode mode);
|
||||
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
|
||||
|
||||
// The |write_queue_| object is shared between the file task runner and the
|
||||
@ -147,6 +156,8 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver {
|
||||
// finished (since it is posted using base::Unretained()).
|
||||
std::unique_ptr<FileWriter> file_writer_;
|
||||
|
||||
const NetLogCaptureMode capture_mode_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(FileNetLogObserver);
|
||||
};
|
||||
|
||||
|
@ -234,16 +234,19 @@ class FileNetLogObserverTest : public ::testing::TestWithParam<bool>,
|
||||
|
||||
bool IsBounded() const { return GetParam(); }
|
||||
|
||||
void CreateAndStartObserving(std::unique_ptr<base::Value> constants) {
|
||||
void CreateAndStartObserving(
|
||||
std::unique_ptr<base::Value> constants,
|
||||
NetLogCaptureMode capture_mode = NetLogCaptureMode::kDefault) {
|
||||
if (IsBounded()) {
|
||||
logger_ = FileNetLogObserver::CreateBoundedForTests(
|
||||
log_path_, kLargeFileSize, kTotalNumFiles, std::move(constants));
|
||||
log_path_, kLargeFileSize, kTotalNumFiles, capture_mode,
|
||||
std::move(constants));
|
||||
} else {
|
||||
logger_ =
|
||||
FileNetLogObserver::CreateUnbounded(log_path_, std::move(constants));
|
||||
logger_ = FileNetLogObserver::CreateUnbounded(log_path_, capture_mode,
|
||||
std::move(constants));
|
||||
}
|
||||
|
||||
logger_->StartObserving(&net_log_, NetLogCaptureMode::kDefault);
|
||||
logger_->StartObserving(&net_log_);
|
||||
}
|
||||
|
||||
void CreateAndStartObservingPreExisting(
|
||||
@ -259,13 +262,13 @@ class FileNetLogObserverTest : public ::testing::TestWithParam<bool>,
|
||||
if (IsBounded()) {
|
||||
logger_ = FileNetLogObserver::CreateBoundedPreExisting(
|
||||
scratch_dir_.GetPath(), std::move(file), kLargeFileSize,
|
||||
std::move(constants));
|
||||
NetLogCaptureMode::kDefault, std::move(constants));
|
||||
} else {
|
||||
logger_ = FileNetLogObserver::CreateUnboundedPreExisting(
|
||||
std::move(file), std::move(constants));
|
||||
std::move(file), NetLogCaptureMode::kDefault, std::move(constants));
|
||||
}
|
||||
|
||||
logger_->StartObserving(&net_log_, NetLogCaptureMode::kDefault);
|
||||
logger_->StartObserving(&net_log_);
|
||||
}
|
||||
|
||||
bool LogFileExists() {
|
||||
@ -303,8 +306,9 @@ class FileNetLogObserverBoundedTest : public ::testing::Test,
|
||||
uint64_t total_file_size,
|
||||
int num_files) {
|
||||
logger_ = FileNetLogObserver::CreateBoundedForTests(
|
||||
log_path_, total_file_size, num_files, std::move(constants));
|
||||
logger_->StartObserving(&net_log_, NetLogCaptureMode::kDefault);
|
||||
log_path_, total_file_size, num_files, NetLogCaptureMode::kDefault,
|
||||
std::move(constants));
|
||||
logger_->StartObserving(&net_log_);
|
||||
}
|
||||
|
||||
// Returns the path for an internally directory created for bounded logs (this
|
||||
@ -486,11 +490,12 @@ TEST_P(FileNetLogObserverTest, PreExistingFileBroken) {
|
||||
EXPECT_FALSE(file.IsValid());
|
||||
if (IsBounded())
|
||||
logger_ = FileNetLogObserver::CreateBoundedPreExisting(
|
||||
scratch_dir_.GetPath(), std::move(file), kLargeFileSize, nullptr);
|
||||
scratch_dir_.GetPath(), std::move(file), kLargeFileSize,
|
||||
NetLogCaptureMode::kDefault, nullptr);
|
||||
else
|
||||
logger_ = FileNetLogObserver::CreateUnboundedPreExisting(std::move(file),
|
||||
nullptr);
|
||||
logger_->StartObserving(&net_log_, NetLogCaptureMode::kDefault);
|
||||
logger_ = FileNetLogObserver::CreateUnboundedPreExisting(
|
||||
std::move(file), NetLogCaptureMode::kDefault, nullptr);
|
||||
logger_->StartObserving(&net_log_);
|
||||
|
||||
// Send dummy event.
|
||||
AddEntries(logger_.get(), 1, kDummyEventSize);
|
||||
@ -551,6 +556,28 @@ TEST_P(FileNetLogObserverTest, GeneratesValidJSONWithPolledData) {
|
||||
kDummyPolledDataString);
|
||||
}
|
||||
|
||||
// Ensure that the Capture Mode is recorded as a constant in the NetLog.
|
||||
TEST_P(FileNetLogObserverTest, LogModeRecorded) {
|
||||
struct TestCase {
|
||||
NetLogCaptureMode capture_mode;
|
||||
const char* expected_value;
|
||||
} test_cases[] = {// Challenges that result in success results.
|
||||
{NetLogCaptureMode::kEverything, "Everything"},
|
||||
{NetLogCaptureMode::kIncludeSensitive, "IncludeSensitive"},
|
||||
{NetLogCaptureMode::kDefault, "Default"}};
|
||||
|
||||
TestClosure closure;
|
||||
for (const auto& test_case : test_cases) {
|
||||
CreateAndStartObserving(nullptr, test_case.capture_mode);
|
||||
logger_->StopObserving(nullptr, closure.closure());
|
||||
closure.WaitForResult();
|
||||
std::unique_ptr<ParsedNetLog> log = ReadNetLogFromDisk(log_path_);
|
||||
ASSERT_TRUE(log);
|
||||
ExpectDictionaryContainsProperty(log->constants, "logCaptureMode",
|
||||
test_case.expected_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds events concurrently from several different threads. The exact order of
|
||||
// events seen by this test is non-deterministic.
|
||||
TEST_P(FileNetLogObserverTest, AddEventsFromMultipleThreads) {
|
||||
@ -946,8 +973,9 @@ TEST_F(FileNetLogObserverBoundedTest, PreExistingUsesSpecifiedDir) {
|
||||
file.Write(0, "not json", 8);
|
||||
|
||||
logger_ = FileNetLogObserver::CreateBoundedPreExisting(
|
||||
scratch_dir.GetPath(), std::move(file), kLargeFileSize, nullptr);
|
||||
logger_->StartObserving(&net_log_, NetLogCaptureMode::kDefault);
|
||||
scratch_dir.GetPath(), std::move(file), kLargeFileSize,
|
||||
NetLogCaptureMode::kDefault, nullptr);
|
||||
logger_->StartObserving(&net_log_);
|
||||
|
||||
base::ThreadPoolInstance::Get()->FlushForTesting();
|
||||
EXPECT_TRUE(base::PathExists(log_path_));
|
||||
|
@ -185,12 +185,12 @@ void NetLogExporter::StartWithScratchDir(
|
||||
|
||||
if (max_file_size != kUnlimitedFileSize) {
|
||||
file_net_observer_ = net::FileNetLogObserver::CreateBoundedPreExisting(
|
||||
scratch_dir_path, std::move(destination_), max_file_size,
|
||||
scratch_dir_path, std::move(destination_), max_file_size, capture_mode,
|
||||
std::move(constants));
|
||||
} else {
|
||||
DCHECK(scratch_dir_path.empty());
|
||||
file_net_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting(
|
||||
std::move(destination_), std::move(constants));
|
||||
std::move(destination_), capture_mode, std::move(constants));
|
||||
}
|
||||
|
||||
// There might not be a NetworkService object e.g. on iOS; in that case
|
||||
@ -206,7 +206,7 @@ void NetLogExporter::StartWithScratchDir(
|
||||
}
|
||||
|
||||
file_net_observer_->StartObserving(
|
||||
network_context_->url_request_context()->net_log(), capture_mode);
|
||||
network_context_->url_request_context()->net_log());
|
||||
std::move(callback).Run(net::OK);
|
||||
}
|
||||
|
||||
|
@ -482,8 +482,8 @@ void NetworkService::StartNetLog(base::File file,
|
||||
constants->MergeDictionary(&client_constants);
|
||||
|
||||
file_net_log_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting(
|
||||
std::move(file), std::move(constants));
|
||||
file_net_log_observer_->StartObserving(net_log_, capture_mode);
|
||||
std::move(file), capture_mode, std::move(constants));
|
||||
file_net_log_observer_->StartObserving(net_log_);
|
||||
}
|
||||
|
||||
void NetworkService::AttachNetLogProxy(
|
||||
|
Reference in New Issue
Block a user