feat: allow setting capture mode and max file size in netLog API (#19215)
This commit is contained in:
parent
8028c57b42
commit
477661d0e4
5 changed files with 102 additions and 13 deletions
|
@ -22,9 +22,17 @@ of the `app` module gets emitted.
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
### `netLog.startLogging(path)`
|
### `netLog.startLogging(path[, options])`
|
||||||
|
|
||||||
* `path` String - File path to record network logs.
|
* `path` String - File path to record network logs.
|
||||||
|
* `options` Object (optional)
|
||||||
|
* `captureMode` String (optional) - What kinds of data should be captured. By
|
||||||
|
default, only metadata about requests will be captured. Setting this to
|
||||||
|
`includeSensitive` will include cookies and authentication data. Setting
|
||||||
|
it to `everything` will include all bytes transferred on sockets. Can be
|
||||||
|
`default`, `includeSensitive` or `everything`.
|
||||||
|
* `maxFileSize` Number (optional) - When the log grows beyond this size,
|
||||||
|
logging will automatically stop. Defaults to unlimited.
|
||||||
|
|
||||||
Returns `Promise<void>` - resolves when the net log has begun recording.
|
Returns `Promise<void>` - resolves when the net log has begun recording.
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ Session.prototype._init = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
const _originalStartLogging = NetLog.prototype.startLogging
|
const _originalStartLogging = NetLog.prototype.startLogging
|
||||||
NetLog.prototype.startLogging = function (path) {
|
NetLog.prototype.startLogging = function (path, ...args) {
|
||||||
this._currentlyLoggingPath = path
|
this._currentlyLoggingPath = path
|
||||||
try {
|
try {
|
||||||
return _originalStartLogging.call(this, path)
|
return _originalStartLogging.call(this, path, ...args)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this._currentlyLoggingPath = null
|
this._currentlyLoggingPath = null
|
||||||
throw e
|
throw e
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "components/net_log/chrome_net_log.h"
|
#include "components/net_log/chrome_net_log.h"
|
||||||
#include "content/public/browser/storage_partition.h"
|
#include "content/public/browser/storage_partition.h"
|
||||||
#include "electron/electron_version.h"
|
#include "electron/electron_version.h"
|
||||||
|
#include "native_mate/converter.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "native_mate/handle.h"
|
#include "native_mate/handle.h"
|
||||||
#include "net/url_request/url_request_context_getter.h"
|
#include "net/url_request/url_request_context_getter.h"
|
||||||
|
@ -20,6 +21,30 @@
|
||||||
#include "shell/common/native_mate_converters/file_path_converter.h"
|
#include "shell/common/native_mate_converters/file_path_converter.h"
|
||||||
#include "shell/common/node_includes.h"
|
#include "shell/common/node_includes.h"
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct Converter<net::NetLogCaptureMode> {
|
||||||
|
static bool FromV8(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::Value> val,
|
||||||
|
net::NetLogCaptureMode* out) {
|
||||||
|
std::string type;
|
||||||
|
if (!ConvertFromV8(isolate, val, &type))
|
||||||
|
return false;
|
||||||
|
if (type == "default")
|
||||||
|
*out = net::NetLogCaptureMode::kDefault;
|
||||||
|
else if (type == "includeSensitive")
|
||||||
|
*out = net::NetLogCaptureMode::kIncludeSensitive;
|
||||||
|
else if (type == "everything")
|
||||||
|
*out = net::NetLogCaptureMode::kEverything;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mate
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -60,13 +85,36 @@ NetLog::NetLog(v8::Isolate* isolate, AtomBrowserContext* browser_context)
|
||||||
|
|
||||||
NetLog::~NetLog() = default;
|
NetLog::~NetLog() = default;
|
||||||
|
|
||||||
v8::Local<v8::Promise> NetLog::StartLogging(mate::Arguments* args) {
|
v8::Local<v8::Promise> NetLog::StartLogging(base::FilePath log_path,
|
||||||
base::FilePath log_path;
|
mate::Arguments* args) {
|
||||||
if (!args->GetNext(&log_path) || log_path.empty()) {
|
if (log_path.empty()) {
|
||||||
args->ThrowError("The first parameter must be a valid string");
|
args->ThrowError("The first parameter must be a valid string");
|
||||||
return v8::Local<v8::Promise>();
|
return v8::Local<v8::Promise>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
net::NetLogCaptureMode capture_mode = net::NetLogCaptureMode::kDefault;
|
||||||
|
uint64_t max_file_size = network::mojom::NetLogExporter::kUnlimitedFileSize;
|
||||||
|
|
||||||
|
mate::Dictionary dict;
|
||||||
|
if (args->GetNext(&dict)) {
|
||||||
|
v8::Local<v8::Value> capture_mode_v8;
|
||||||
|
if (dict.Get("captureMode", &capture_mode_v8)) {
|
||||||
|
if (!mate::ConvertFromV8(args->isolate(), capture_mode_v8,
|
||||||
|
&capture_mode)) {
|
||||||
|
args->ThrowError("Invalid value for captureMode");
|
||||||
|
return v8::Local<v8::Promise>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v8::Local<v8::Value> max_file_size_v8;
|
||||||
|
if (dict.Get("maxFileSize", &max_file_size_v8)) {
|
||||||
|
if (!mate::ConvertFromV8(args->isolate(), max_file_size_v8,
|
||||||
|
&max_file_size)) {
|
||||||
|
args->ThrowError("Invalid value for maxFileSize");
|
||||||
|
return v8::Local<v8::Promise>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (net_log_exporter_) {
|
if (net_log_exporter_) {
|
||||||
args->ThrowError("There is already a net log running");
|
args->ThrowError("There is already a net log running");
|
||||||
return v8::Local<v8::Promise>();
|
return v8::Local<v8::Promise>();
|
||||||
|
@ -90,11 +138,6 @@ v8::Local<v8::Promise> NetLog::StartLogging(mate::Arguments* args) {
|
||||||
net_log_exporter_.set_connection_error_handler(
|
net_log_exporter_.set_connection_error_handler(
|
||||||
base::BindOnce(&NetLog::OnConnectionError, base::Unretained(this)));
|
base::BindOnce(&NetLog::OnConnectionError, base::Unretained(this)));
|
||||||
|
|
||||||
// TODO(deepak1556): Provide more flexibility to this module
|
|
||||||
// by allowing customizations on the capturing options.
|
|
||||||
auto capture_mode = net::NetLogCaptureMode::kDefault;
|
|
||||||
auto max_file_size = network::mojom::NetLogExporter::kUnlimitedFileSize;
|
|
||||||
|
|
||||||
base::PostTaskAndReplyWithResult(
|
base::PostTaskAndReplyWithResult(
|
||||||
file_task_runner_.get(), FROM_HERE,
|
file_task_runner_.get(), FROM_HERE,
|
||||||
base::BindOnce(OpenFileForWriting, log_path),
|
base::BindOnce(OpenFileForWriting, log_path),
|
||||||
|
|
|
@ -31,7 +31,8 @@ class NetLog : public mate::TrackableObject<NetLog> {
|
||||||
static void BuildPrototype(v8::Isolate* isolate,
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
v8::Local<v8::FunctionTemplate> prototype);
|
v8::Local<v8::FunctionTemplate> prototype);
|
||||||
|
|
||||||
v8::Local<v8::Promise> StartLogging(mate::Arguments* args);
|
v8::Local<v8::Promise> StartLogging(base::FilePath log_path,
|
||||||
|
mate::Arguments* args);
|
||||||
v8::Local<v8::Promise> StopLogging(mate::Arguments* args);
|
v8::Local<v8::Promise> StopLogging(mate::Arguments* args);
|
||||||
bool IsCurrentlyLogging() const;
|
bool IsCurrentlyLogging() const;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ const fs = require('fs')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const ChildProcess = require('child_process')
|
const ChildProcess = require('child_process')
|
||||||
const {session} = require('electron')
|
const {session, net} = require('electron')
|
||||||
const appPath = path.join(__dirname, 'fixtures', 'api', 'net-log')
|
const appPath = path.join(__dirname, 'fixtures', 'api', 'net-log')
|
||||||
const dumpFile = path.join(os.tmpdir(), 'net_log.json')
|
const dumpFile = path.join(os.tmpdir(), 'net_log.json')
|
||||||
const dumpFileDynamic = path.join(os.tmpdir(), 'net_log_dynamic.json')
|
const dumpFileDynamic = path.join(os.tmpdir(), 'net_log_dynamic.json')
|
||||||
|
@ -83,6 +83,43 @@ describe('netLog module', () => {
|
||||||
expect(() => testNetLog().startLogging('')).to.throw()
|
expect(() => testNetLog().startLogging('')).to.throw()
|
||||||
expect(() => testNetLog().startLogging(null)).to.throw()
|
expect(() => testNetLog().startLogging(null)).to.throw()
|
||||||
expect(() => testNetLog().startLogging([])).to.throw()
|
expect(() => testNetLog().startLogging([])).to.throw()
|
||||||
|
expect(() => testNetLog().startLogging('aoeu', {captureMode: 'aoeu'})).to.throw()
|
||||||
|
expect(() => testNetLog().startLogging('aoeu', {maxFileSize: null})).to.throw()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should include cookies when requested', async () => {
|
||||||
|
await testNetLog().startLogging(dumpFileDynamic, {captureMode: "includeSensitive"})
|
||||||
|
const unique = require('uuid').v4()
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
const req = net.request(server.url)
|
||||||
|
req.setHeader('Cookie', `foo=${unique}`)
|
||||||
|
req.on('response', (response) => {
|
||||||
|
response.on('data', () => {}) // https://github.com/electron/electron/issues/19214
|
||||||
|
response.on('end', () => resolve())
|
||||||
|
})
|
||||||
|
req.end()
|
||||||
|
})
|
||||||
|
await testNetLog().stopLogging()
|
||||||
|
expect(fs.existsSync(dumpFileDynamic)).to.be.true('dump file exists')
|
||||||
|
const dump = fs.readFileSync(dumpFileDynamic, 'utf8')
|
||||||
|
expect(dump).to.contain(`foo=${unique}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should include socket bytes when requested', async () => {
|
||||||
|
await testNetLog().startLogging(dumpFileDynamic, {captureMode: "everything"})
|
||||||
|
const unique = require('uuid').v4()
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
const req = net.request({method: 'POST', url: server.url})
|
||||||
|
req.on('response', (response) => {
|
||||||
|
response.on('data', () => {}) // https://github.com/electron/electron/issues/19214
|
||||||
|
response.on('end', () => resolve())
|
||||||
|
})
|
||||||
|
req.end(Buffer.from(unique))
|
||||||
|
})
|
||||||
|
await testNetLog().stopLogging()
|
||||||
|
expect(fs.existsSync(dumpFileDynamic)).to.be.true('dump file exists')
|
||||||
|
const dump = fs.readFileSync(dumpFileDynamic, 'utf8')
|
||||||
|
expect(JSON.parse(dump).events.some(x => x.params && x.params.bytes && Buffer.from(x.params.bytes, 'base64').includes(unique))).to.be.true('uuid present in dump')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should begin and end logging automatically when --log-net-log is passed', done => {
|
it('should begin and end logging automatically when --log-net-log is passed', done => {
|
||||||
|
|
Loading…
Reference in a new issue