diff --git a/shell/common/gin_converters/net_converter.cc b/shell/common/gin_converters/net_converter.cc index bc925622263c..d25c0a2614e5 100644 --- a/shell/common/gin_converters/net_converter.cc +++ b/shell/common/gin_converters/net_converter.cc @@ -256,14 +256,22 @@ v8::Local Converter::ToV8( gin::Dictionary upload_data(isolate, v8::Object::New(isolate)); switch (element.type()) { case network::mojom::DataElementType::kFile: + upload_data.Set("type", "file"); upload_data.Set("file", element.path().value()); + upload_data.Set("filePath", base::Value(element.path().AsUTF8Unsafe())); + upload_data.Set("offset", static_cast(element.offset())); + upload_data.Set("length", static_cast(element.length())); + upload_data.Set("modificationTime", + element.expected_modification_time().ToDoubleT()); break; case network::mojom::DataElementType::kBytes: + upload_data.Set("type", "rawData"); upload_data.Set("bytes", node::Buffer::Copy(isolate, element.bytes(), element.length()) .ToLocalChecked()); break; case network::mojom::DataElementType::kDataPipe: { + upload_data.Set("type", "blob"); // TODO(zcbenz): After the NetworkService refactor, the old blobUUID API // becomes unecessarily complex, we should deprecate the getBlobData API // and return the DataPipeHolder wrapper directly. diff --git a/spec-main/chromium-spec.ts b/spec-main/chromium-spec.ts index b85e0c2a5fc8..d46cb0c489d3 100644 --- a/spec-main/chromium-spec.ts +++ b/spec-main/chromium-spec.ts @@ -423,6 +423,85 @@ describe('chromium features', () => { }) }) + describe('form submit', () => { + let server: http.Server + let serverUrl: string + + before(async () => { + server = http.createServer((req, res) => { + let body = '' + req.on('data', (chunk) => { + body += chunk + }) + res.setHeader('Content-Type', 'application/json') + req.on('end', () => { + res.end(`body:${body}`) + }) + }) + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)) + serverUrl = `http://localhost:${(server.address() as any).port}` + }) + after(async () => { + server.close() + await closeAllWindows() + }); + + [true, false].forEach((isSandboxEnabled) => + describe(`sandbox=${isSandboxEnabled}`, () => { + it('posts data in the same window', () => { + const w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: isSandboxEnabled + } + }) + + return new Promise(async (resolve) => { + await w.loadFile(path.join(fixturesPath, 'pages', 'form-with-data.html')) + + w.webContents.once('did-finish-load', async () => { + const res = await w.webContents.executeJavaScript('document.body.innerText') + expect(res).to.equal('body:greeting=hello') + resolve() + }) + + w.webContents.executeJavaScript(` + const form = document.querySelector('form') + form.action = '${serverUrl}'; + form.submit(); + `) + }) + }) + + it('posts data to a new window with target=_blank', () => { + const w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: isSandboxEnabled + } + }) + + return new Promise(async (resolve) => { + await w.loadFile(path.join(fixturesPath, 'pages', 'form-with-data.html')) + + app.once('browser-window-created', async (event, newWin) => { + const res = await newWin.webContents.executeJavaScript('document.body.innerText') + expect(res).to.equal('body:greeting=hello') + resolve() + }) + + w.webContents.executeJavaScript(` + const form = document.querySelector('form') + form.action = '${serverUrl}'; + form.target = '_blank'; + form.submit(); + `) + }) + }) + }) + ) + }) + describe('window.open', () => { for (const show of [true, false]) { it(`inherits parent visibility over parent {show=${show}} option`, (done) => { diff --git a/spec/fixtures/pages/form-with-data.html b/spec/fixtures/pages/form-with-data.html new file mode 100644 index 000000000000..711f6196d525 --- /dev/null +++ b/spec/fixtures/pages/form-with-data.html @@ -0,0 +1,8 @@ + + +
+ + +
+ +