Commit 1fa1df4b authored by Maks Orlovich's avatar Maks Orlovich Committed by Commit Bot

Reland: S13n: Add APIs for implementing net-export in Network Service

Change for reland:
The debug bot failure was because tests passed an invalid base::File
to a method with a mojo_base.mojom.File --- as opposed to
mojo_base.mojom.File? --- parameter type.

This commits to not accepting those files, by adding an additional
DCHECK on it and adjusting tests to not do that.

Rationale: passing in a broken file is ultimately doing an RPC to
do a lot of work that accomplishes nothing, so it's silly to support it,
even if a 1-character fix CL would be easier.

Original CL:
https://chromium-review.googlesource.com/c/chromium/src/+/1030033

Original description:
S13n: Add APIs for implementing net-export in Network Service

(But don't use them yet).
This takes care of managing the FileNetLogObserver with a passed-in
destination file, and also of all aspects of pulling state from
URLRequestContexts, which browser-end NetExportFileExporter presently
does but won't be able to with network service.

There is one behavior difference in that respect: the in-progress
entries for things that are in flight when the export is started
now included all URLRequestContexts known, rather than just the
main + media + system for whever the export UI is running. Given
that events collected when export is active included everything
already, this seemed rational as consistent, and avoiding complexity
of finding the particular contexts, including the going-away media one.

Bug: 767450
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_mojo
Change-Id: Ifd7f8fbcd60ec2dadf7a8b31c6b0ec67d27b9b7b
Reviewed-on: https://chromium-review.googlesource.com/1037243
Commit-Queue: Maks Orlovich <morlovich@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarHelen Li <xunjieli@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555870}
parent 8f49bff3
......@@ -7,8 +7,16 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "base/values.h"
#include "net/log/file_net_log_observer.h"
#include "net/log/net_log_util.h"
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/network_switches.h"
namespace network {
......@@ -37,4 +45,207 @@ void MojoNetLog::ProcessCommandLine(const base::CommandLine& command_line) {
file_net_log_observer_->StartObserving(this, capture_mode);
}
NetLogExporter::NetLogExporter(NetworkContext* network_context)
: network_context_(network_context), state_(STATE_IDLE) {}
NetLogExporter::~NetLogExporter() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// In case scratch directory creation didn't finish by the time |this| is
// destroyed, |destination_| is still owned here (rather than handed over to
// FileNetLogObserver); ask the scheduler to close it someplace suitable.
if (destination_.IsValid())
CloseFileOffThread(std::move(destination_));
// ~FileNetLogObserver will take care of unregistering from NetLog even
// if StopObserving isn't invoked.
}
void NetLogExporter::Start(base::File destination,
base::Value extra_constants,
NetLogExporter::CaptureMode capture_mode,
uint64_t max_file_size,
StartCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(destination.IsValid());
if (state_ != STATE_IDLE) {
CloseFileOffThread(std::move(destination));
std::move(callback).Run(net::ERR_UNEXPECTED);
return;
}
// Store the file explicitly since destroying it involves disk I/O, so must
// be carefully controlled.
destination_ = std::move(destination);
net::NetLogCaptureMode net_capture_mode;
switch (capture_mode) {
case NetLogExporter::CaptureMode::DEFAULT:
net_capture_mode = net::NetLogCaptureMode::Default();
break;
case NetLogExporter::CaptureMode::INCLUDE_COOKIES_AND_CREDENTIALS:
net_capture_mode = net::NetLogCaptureMode::IncludeCookiesAndCredentials();
break;
case NetLogExporter::CaptureMode::INCLUDE_SOCKET_BYTES:
net_capture_mode = net::NetLogCaptureMode::IncludeSocketBytes();
break;
}
state_ = STATE_WAITING_DIR;
static_assert(kUnlimitedFileSize == net::FileNetLogObserver::kNoLimit,
"Inconsistent unbounded size constants");
if (max_file_size != kUnlimitedFileSize) {
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&NetLogExporter::CreateScratchDir,
scratch_dir_create_handler_for_tests_),
// Note: this a static method which takes a weak pointer as an argument,
// so it will run if |this| is deleted.
base::BindOnce(&NetLogExporter::StartWithScratchDirOrCleanup,
AsWeakPtr(), std::move(extra_constants),
net_capture_mode, max_file_size, std::move(callback)));
} else {
StartWithScratchDir(std::move(extra_constants), net_capture_mode,
max_file_size, std::move(callback), base::FilePath());
}
}
void NetLogExporter::Stop(base::Value polled_data_value,
StopCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::DictionaryValue* polled_data = nullptr;
bool ok = polled_data_value.GetAsDictionary(&polled_data);
DCHECK(ok); // mojo is supposed to enforce that.
if (state_ != STATE_RUNNING) {
std::move(callback).Run(net::ERR_UNEXPECTED);
return;
}
std::unique_ptr<base::DictionaryValue> net_info = net::GetNetInfo(
network_context_->url_request_context(), net::NET_INFO_ALL_SOURCES);
if (polled_data)
net_info->MergeDictionary(polled_data);
file_net_observer_->StopObserving(
std::move(net_info),
base::BindOnce([](StopCallback sc) { std::move(sc).Run(net::OK); },
std::move(callback)));
file_net_observer_ = nullptr;
state_ = STATE_IDLE;
}
void NetLogExporter::SetCreateScratchDirHandlerForTesting(
const base::RepeatingCallback<base::FilePath()>& handler) {
scratch_dir_create_handler_for_tests_ = handler;
}
void NetLogExporter::CloseFileOffThread(base::File file) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (file.IsValid()) {
base::PostTaskWithTraits(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce([](base::File f) { f.Close(); }, std::move(file)));
}
}
base::FilePath NetLogExporter::CreateScratchDir(
base::RepeatingCallback<base::FilePath()>
scratch_dir_create_handler_for_tests) {
if (scratch_dir_create_handler_for_tests)
return scratch_dir_create_handler_for_tests.Run();
base::ScopedTempDir scratch_dir;
if (scratch_dir.CreateUniqueTempDir())
return scratch_dir.Take();
else
return base::FilePath();
}
void NetLogExporter::StartWithScratchDirOrCleanup(
base::WeakPtr<NetLogExporter> object,
base::Value extra_constants,
net::NetLogCaptureMode capture_mode,
uint64_t max_file_size,
StartCallback callback,
const base::FilePath& scratch_dir_path) {
NetLogExporter* instance = object.get();
if (instance) {
instance->StartWithScratchDir(std::move(extra_constants), capture_mode,
max_file_size, std::move(callback),
scratch_dir_path);
} else if (!scratch_dir_path.empty()) {
// An NetLogExporter got destroyed while it was trying to create a scratch
// dir.
base::PostTaskWithTraits(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(
[](const base::FilePath& dir) {
// The delete is non-recursive (2nd argument false) since the
// only time this is invoked the directory is expected to be
// empty.
base::DeleteFile(dir, false);
},
scratch_dir_path));
}
}
void NetLogExporter::StartWithScratchDir(
base::Value extra_constants_value,
net::NetLogCaptureMode capture_mode,
uint64_t max_file_size,
StartCallback callback,
const base::FilePath& scratch_dir_path) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::DictionaryValue* extra_constants = nullptr;
bool ok = extra_constants_value.GetAsDictionary(&extra_constants);
DCHECK(ok); // mojo is supposed to enforce that before Start() is invoked.
if (scratch_dir_path.empty() && max_file_size != kUnlimitedFileSize) {
state_ = STATE_IDLE;
CloseFileOffThread(std::move(destination_));
std::move(callback).Run(net::ERR_INSUFFICIENT_RESOURCES);
return;
}
state_ = STATE_RUNNING;
std::unique_ptr<base::DictionaryValue> constants = net::GetNetConstants();
if (extra_constants)
constants->MergeDictionary(extra_constants);
if (max_file_size != kUnlimitedFileSize) {
file_net_observer_ = net::FileNetLogObserver::CreateBoundedPreExisting(
scratch_dir_path, std::move(destination_), max_file_size,
std::move(constants));
} else {
DCHECK(scratch_dir_path.empty());
file_net_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting(
std::move(destination_), std::move(constants));
}
// There might not be a NetworkService object e.g. on iOS; in that case
// assume this present NetworkContext is all there is.
if (network_context_->network_service()) {
network_context_->network_service()->CreateNetLogEntriesForActiveObjects(
file_net_observer_.get());
} else {
std::set<net::URLRequestContext*> contexts;
contexts.insert(network_context_->url_request_context());
net::CreateNetLogEntriesForActiveObjects(contexts,
file_net_observer_.get());
}
file_net_observer_->StartObserving(
network_context_->url_request_context()->net_log(), capture_mode);
std::move(callback).Run(net::OK);
}
} // namespace network
......@@ -8,7 +8,9 @@
#include <memory>
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "net/log/net_log.h"
#include "services/network/public/mojom/network_service.mojom.h"
namespace base {
class CommandLine;
......@@ -20,6 +22,8 @@ class FileNetLogObserver;
namespace network {
class NetworkContext;
// NetLog used by NetworkService when it owns the NetLog, rather than when a
// pre-existing one is passed in to its constructor.
//
......@@ -39,6 +43,67 @@ class MojoNetLog : public net::NetLog {
DISALLOW_COPY_AND_ASSIGN(MojoNetLog);
};
// API implementation for exporting ongoing netlogs.
class COMPONENT_EXPORT(NETWORK_SERVICE) NetLogExporter
: public mojom::NetLogExporter,
public base::SupportsWeakPtr<NetLogExporter> {
public:
// This expects to live on the same thread as NetworkContext, e.g.
// IO thread or NetworkService main thread.
explicit NetLogExporter(NetworkContext* network_context);
~NetLogExporter() override;
void Start(base::File destination,
base::Value extra_constants,
NetLogExporter::CaptureMode capture_mode,
uint64_t max_file_size,
StartCallback callback) override;
void Stop(base::Value polled_data, StopCallback callback) override;
// Sets a callback that will be used to create a scratch directory instead
// of the normal codepath. For test use only.
void SetCreateScratchDirHandlerForTesting(
const base::RepeatingCallback<base::FilePath()>& handler);
private:
void CloseFileOffThread(base::File file);
// Run off-thread by task scheduler, as does disk I/O.
static base::FilePath CreateScratchDir(
base::RepeatingCallback<base::FilePath()>
scratch_dir_create_handler_for_tests);
static void StartWithScratchDirOrCleanup(
base::WeakPtr<NetLogExporter> object,
base::Value extra_constants,
net::NetLogCaptureMode capture_mode,
uint64_t max_file_size,
StartCallback callback,
const base::FilePath& scratch_dir_path);
void StartWithScratchDir(base::Value extra_constants,
net::NetLogCaptureMode capture_mode,
uint64_t max_file_size,
StartCallback callback,
const base::FilePath& scratch_dir_path);
// NetworkContext owns |this| via StrongBindingSet, so this object can't
// outlive it.
NetworkContext* network_context_;
enum State { STATE_IDLE, STATE_WAITING_DIR, STATE_RUNNING } state_;
std::unique_ptr<net::FileNetLogObserver> file_net_observer_;
base::File destination_;
// Test-only injectable replacement for CreateScratchDir.
base::RepeatingCallback<base::FilePath()>
scratch_dir_create_handler_for_tests_;
THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(NetLogExporter);
};
} // namespace network
#endif // SERVICES_NETWORK_MOJO_NET_LOG_H_
......@@ -48,6 +48,7 @@
#include "net/url_request/url_request_context_builder.h"
#include "services/network/http_server_properties_pref_delegate.h"
#include "services/network/ignore_errors_cert_verifier.h"
#include "services/network/mojo_net_log.h"
#include "services/network/network_service.h"
#include "services/network/proxy_config_service_mojo.h"
#include "services/network/public/cpp/features.h"
......@@ -670,6 +671,12 @@ void NetworkContext::CreateWebSocket(mojom::WebSocketRequest request,
#endif // !defined(OS_IOS)
}
void NetworkContext::CreateNetLogExporter(
mojom::NetLogExporterRequest request) {
net_log_exporter_bindings_.AddBinding(std::make_unique<NetLogExporter>(this),
std::move(request));
}
void NetworkContext::AddHSTSForTesting(const std::string& host,
base::Time expiry,
bool include_subdomains,
......
......@@ -15,6 +15,7 @@
#include "base/callback.h"
#include "base/component_export.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/files/file.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "build/build_config.h"
......@@ -152,6 +153,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
int32_t process_id,
int32_t render_frame_id,
const url::Origin& origin) override;
void CreateNetLogExporter(mojom::NetLogExporterRequest request) override;
void AddHSTSForTesting(const std::string& host,
base::Time expiry,
bool include_subdomains,
......@@ -229,6 +231,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::set<std::unique_ptr<URLLoaderFactory>, base::UniquePtrComparator>
url_loader_factories_;
mojo::StrongBindingSet<mojom::NetLogExporter> net_log_exporter_bindings_;
int current_resource_scheduler_client_id_ = 0;
// Owned by the URLRequestContext
......
......@@ -11,6 +11,7 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
......@@ -19,11 +20,13 @@
#include "base/run_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/gtest_util.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/network_session_configurator/browser/network_session_configurator.h"
......@@ -56,6 +59,7 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "net/url_request/url_request_job_factory.h"
#include "services/network/mojo_net_log.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
......@@ -1349,6 +1353,179 @@ TEST_F(NetworkContextTest, GssapiLibraryName) {
}
#endif
TEST_F(NetworkContextTest, CreateNetLogExporter) {
// Basic flow around start/stop.
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateContextParams());
mojom::NetLogExporterPtr net_log_exporter;
network_context->CreateNetLogExporter(mojo::MakeRequest(&net_log_exporter));
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath out_path(temp_dir.GetPath().AppendASCII("out.json"));
base::File out_file(out_path,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(out_file.IsValid());
base::Value dict_start(base::Value::Type::DICTIONARY);
const char kKeyEarly[] = "early";
const char kValEarly[] = "morning";
dict_start.SetKey(kKeyEarly, base::Value(kValEarly));
net::TestCompletionCallback cb;
net_log_exporter->Start(std::move(out_file), std::move(dict_start),
mojom::NetLogExporter_CaptureMode::DEFAULT,
100 * 1024, cb.callback());
EXPECT_EQ(net::OK, cb.WaitForResult());
base::Value dict_late(base::Value::Type::DICTIONARY);
const char kKeyLate[] = "late";
const char kValLate[] = "snowval";
dict_late.SetKey(kKeyLate, base::Value(kValLate));
net_log_exporter->Stop(std::move(dict_late), cb.callback());
EXPECT_EQ(net::OK, cb.WaitForResult());
// Check that file got written.
std::string contents;
ASSERT_TRUE(base::ReadFileToString(out_path, &contents));
// Contents should have net constants, without the client needing any
// net:: methods.
EXPECT_NE(std::string::npos, contents.find("ERR_IO_PENDING")) << contents;
// The additional stuff inject should also occur someplace.
EXPECT_NE(std::string::npos, contents.find(kKeyEarly)) << contents;
EXPECT_NE(std::string::npos, contents.find(kValEarly)) << contents;
EXPECT_NE(std::string::npos, contents.find(kKeyLate)) << contents;
EXPECT_NE(std::string::npos, contents.find(kValLate)) << contents;
}
TEST_F(NetworkContextTest, CreateNetLogExporterUnbounded) {
// Make sure that exporting without size limit works.
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateContextParams());
mojom::NetLogExporterPtr net_log_exporter;
network_context->CreateNetLogExporter(mojo::MakeRequest(&net_log_exporter));
base::FilePath temp_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
base::File out_file(temp_path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
ASSERT_TRUE(out_file.IsValid());
net::TestCompletionCallback cb;
net_log_exporter->Start(
std::move(out_file), base::Value(base::Value::Type::DICTIONARY),
network::mojom::NetLogExporter::CaptureMode::DEFAULT,
network::mojom::NetLogExporter::kUnlimitedFileSize, cb.callback());
EXPECT_EQ(net::OK, cb.WaitForResult());
net_log_exporter->Stop(base::Value(base::Value::Type::DICTIONARY),
cb.callback());
EXPECT_EQ(net::OK, cb.WaitForResult());
// Check that file got written.
std::string contents;
ASSERT_TRUE(base::ReadFileToString(temp_path, &contents));
// Contents should have net constants, without the client needing any
// net:: methods.
EXPECT_NE(std::string::npos, contents.find("ERR_IO_PENDING")) << contents;
base::DeleteFile(temp_path, false);
}
TEST_F(NetworkContextTest, CreateNetLogExporterErrors) {
// Some basic state machine misuses.
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateContextParams());
mojom::NetLogExporterPtr net_log_exporter;
network_context->CreateNetLogExporter(mojo::MakeRequest(&net_log_exporter));
net::TestCompletionCallback cb;
net_log_exporter->Stop(base::Value(base::Value::Type::DICTIONARY),
cb.callback());
EXPECT_EQ(net::ERR_UNEXPECTED, cb.WaitForResult());
base::FilePath temp_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
base::File temp_file(temp_path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
ASSERT_TRUE(temp_file.IsValid());
net_log_exporter->Start(
std::move(temp_file), base::Value(base::Value::Type::DICTIONARY),
mojom::NetLogExporter_CaptureMode::DEFAULT, 100 * 1024, cb.callback());
EXPECT_EQ(net::OK, cb.WaitForResult());
// Can't start twice.
base::FilePath temp_path2;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_path2));
base::File temp_file2(
temp_path2, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
ASSERT_TRUE(temp_file2.IsValid());
net_log_exporter->Start(
std::move(temp_file2), base::Value(base::Value::Type::DICTIONARY),
mojom::NetLogExporter_CaptureMode::DEFAULT, 100 * 1024, cb.callback());
EXPECT_EQ(net::ERR_UNEXPECTED, cb.WaitForResult());
base::DeleteFile(temp_path, false);
base::DeleteFile(temp_path2, false);
// Forgetting to stop is recovered from.
}
TEST_F(NetworkContextTest, DestroyNetLogExporterWhileCreatingScratchDir) {
// Make sure that things behave OK if NetLogExporter is destroyed during the
// brief window it owns the scratch directory.
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateContextParams());
std::unique_ptr<NetLogExporter> net_log_exporter =
std::make_unique<NetLogExporter>(network_context.get());
base::WaitableEvent block_mktemp(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
base::ScopedTempDir dir;
ASSERT_TRUE(dir.CreateUniqueTempDir());
base::FilePath path = dir.Take();
EXPECT_TRUE(base::PathExists(path));
net_log_exporter->SetCreateScratchDirHandlerForTesting(base::BindRepeating(
[](base::WaitableEvent* block_on,
const base::FilePath& path) -> base::FilePath {
base::ScopedAllowBaseSyncPrimitivesForTesting need_to_block;
block_on->Wait();
return path;
},
&block_mktemp, path));
base::FilePath temp_path;
ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
base::File temp_file(temp_path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
ASSERT_TRUE(temp_file.IsValid());
net_log_exporter->Start(std::move(temp_file),
base::Value(base::Value::Type::DICTIONARY),
mojom::NetLogExporter_CaptureMode::DEFAULT, 100,
base::BindOnce([](int) {}));
net_log_exporter = nullptr;
block_mktemp.Signal();
scoped_task_environment_.RunUntilIdle();
EXPECT_FALSE(base::PathExists(path));
base::DeleteFile(temp_path, false);
}
} // namespace
} // namespace network
......@@ -19,6 +19,7 @@
#include "net/dns/host_resolver.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/log/net_log.h"
#include "net/log/net_log_util.h"
#include "net/nqe/network_quality_estimator.h"
#include "net/nqe/network_quality_estimator_params.h"
#include "net/url_request/url_request_context_builder.h"
......@@ -198,6 +199,14 @@ void NetworkService::DeregisterNetworkContext(NetworkContext* network_context) {
network_contexts_.erase(network_context);
}
void NetworkService::CreateNetLogEntriesForActiveObjects(
net::NetLog::ThreadSafeObserver* observer) {
std::set<net::URLRequestContext*> contexts;
for (NetworkContext* nc : network_contexts_)
contexts.insert(nc->url_request_context());
return net::CreateNetLogEntriesForActiveObjects(contexts, observer);
}
void NetworkService::SetClient(mojom::NetworkServiceClientPtr client) {
client_ = std::move(client);
}
......
......@@ -12,6 +12,7 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "net/log/net_log.h"
#include "services/network/keepalive_statistics_recorder.h"
#include "services/network/network_change_manager.h"
#include "services/network/network_service.h"
......@@ -23,7 +24,6 @@
namespace net {
class HostResolver;
class LoggingNetworkChangeObserver;
class NetLog;
class NetworkQualityEstimator;
class URLRequestContext;
} // namespace net
......@@ -87,6 +87,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
void RegisterNetworkContext(NetworkContext* network_context);
void DeregisterNetworkContext(NetworkContext* network_context);
// Invokes net::CreateNetLogEntriesForActiveObjects(observer) on all
// URLRequestContext's known to |this|.
void CreateNetLogEntriesForActiveObjects(
net::NetLog::ThreadSafeObserver* observer);
// mojom::NetworkService implementation:
void SetClient(mojom::NetworkServiceClientPtr client) override;
void CreateNetworkContext(mojom::NetworkContextRequest request,
......
......@@ -4,7 +4,9 @@
module network.mojom;
import "mojo/public/mojom/base/file.mojom";
import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/values.mojom";
import "mojo/public/mojom/base/time.mojom";
import "net/interfaces/address_list.mojom";
import "net/interfaces/ip_endpoint.mojom";
......@@ -179,6 +181,52 @@ struct NetworkUsage {
int64 total_bytes_sent;
};
// Manages export of ongoing NetLog events to a file.
// Both Start and Stop must succeed, in that order, for the export to
// be complete and have a well-formed file. You may call Start again after
// Stop's callback has been invoked, but doing things like calling Start twice
// without intervening successful stops will result in an error.
interface NetLogExporter {
enum CaptureMode {
// Log all events, but do not include the actual transferred bytes, and
// remove cookies and HTTP credentials and HTTP/2 GOAWAY frame debug data.
DEFAULT,
// Log all events, but do not include the actual transferred bytes as
// parameters for bytes sent/received events.
INCLUDE_COOKIES_AND_CREDENTIALS,
// Log everything possible, even if it is slow and memory expensive.
// Includes logging of transferred bytes.
INCLUDE_SOCKET_BYTES
};
const uint64 kUnlimitedFileSize = 0xFFFFFFFFFFFFFFFF;
// Starts logging to |destination|, including definitions of |extra_constants|
// in the log in addition to the standard constants required by the log.
// Contents in |destination| might not be complete until Stop() is called
// successfully.
//
// If |max_file_size| is kUnlimitedFileSize log size will not be limited.
//
// Returns network error code.
Start(
mojo_base.mojom.File destination,
mojo_base.mojom.DictionaryValue extra_constants,
CaptureMode capture_mode,
uint64 max_file_size) => (int32 net_error);
// Finalizes the log file. If |polled_values| is provided, it will be
// included alongside net configuration info inside the 'polledData' field
// of the log object.
//
// Returns network error code; if successful this will occur only after
// the file has been fully written.
Stop(mojo_base.mojom.DictionaryValue polled_values) => (int32 net_error);
};
// Represents a distinct context for making network requests, with its own
// storage (e.g. cookies and cache).
interface NetworkContext {
......@@ -297,6 +345,13 @@ interface NetworkContext {
int32 render_frame_id,
url.mojom.Origin origin);
// Create a NetLogExporter, which helps export NetLog to an existing file.
// Note that the log is generally global, including all NetworkContexts
// managed by the same NetworkService. The particular NetworkContext this is
// called on will determine which NetworkContext gets its information and
// configuration summary written out at the end of the log.
CreateNetLogExporter(NetLogExporter& exporter);
[Sync]
// Adds explicitly-specified data as if it was processed from an
// HSTS header.
......
......@@ -80,6 +80,7 @@ class TestNetworkContext : public mojom::NetworkContext {
int32_t process_id,
int32_t render_frame_id,
const url::Origin& origin) override {}
void CreateNetLogExporter(mojom::NetLogExporterRequest exporter) override {}
void AddHSTSForTesting(const std::string& host,
base::Time expiry,
bool include_subdomains,
......
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