fix: restore POST forms that open a new window with target=_blank (#21469)
* fix: restore parts of original ResourceRequestBody V8 conversion Restore some of the original conversion logic in order to fix target=_blank post form submissions. * test: add test for POST form submission
This commit is contained in:
parent
49b47ee4ed
commit
5cecc230fb
3 changed files with 95 additions and 0 deletions
|
@ -256,14 +256,22 @@ v8::Local<v8::Value> Converter<network::ResourceRequestBody>::ToV8(
|
||||||
gin::Dictionary upload_data(isolate, v8::Object::New(isolate));
|
gin::Dictionary upload_data(isolate, v8::Object::New(isolate));
|
||||||
switch (element.type()) {
|
switch (element.type()) {
|
||||||
case network::mojom::DataElementType::kFile:
|
case network::mojom::DataElementType::kFile:
|
||||||
|
upload_data.Set("type", "file");
|
||||||
upload_data.Set("file", element.path().value());
|
upload_data.Set("file", element.path().value());
|
||||||
|
upload_data.Set("filePath", base::Value(element.path().AsUTF8Unsafe()));
|
||||||
|
upload_data.Set("offset", static_cast<int>(element.offset()));
|
||||||
|
upload_data.Set("length", static_cast<int>(element.length()));
|
||||||
|
upload_data.Set("modificationTime",
|
||||||
|
element.expected_modification_time().ToDoubleT());
|
||||||
break;
|
break;
|
||||||
case network::mojom::DataElementType::kBytes:
|
case network::mojom::DataElementType::kBytes:
|
||||||
|
upload_data.Set("type", "rawData");
|
||||||
upload_data.Set("bytes", node::Buffer::Copy(isolate, element.bytes(),
|
upload_data.Set("bytes", node::Buffer::Copy(isolate, element.bytes(),
|
||||||
element.length())
|
element.length())
|
||||||
.ToLocalChecked());
|
.ToLocalChecked());
|
||||||
break;
|
break;
|
||||||
case network::mojom::DataElementType::kDataPipe: {
|
case network::mojom::DataElementType::kDataPipe: {
|
||||||
|
upload_data.Set("type", "blob");
|
||||||
// TODO(zcbenz): After the NetworkService refactor, the old blobUUID API
|
// TODO(zcbenz): After the NetworkService refactor, the old blobUUID API
|
||||||
// becomes unecessarily complex, we should deprecate the getBlobData API
|
// becomes unecessarily complex, we should deprecate the getBlobData API
|
||||||
// and return the DataPipeHolder wrapper directly.
|
// and return the DataPipeHolder wrapper directly.
|
||||||
|
|
|
@ -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', () => {
|
describe('window.open', () => {
|
||||||
for (const show of [true, false]) {
|
for (const show of [true, false]) {
|
||||||
it(`inherits parent visibility over parent {show=${show}} option`, (done) => {
|
it(`inherits parent visibility over parent {show=${show}} option`, (done) => {
|
||||||
|
|
8
spec/fixtures/pages/form-with-data.html
vendored
Normal file
8
spec/fixtures/pages/form-with-data.html
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<form id="form" method="post">
|
||||||
|
<input name="greeting" value="hello">
|
||||||
|
<input type="submit" value="submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Reference in a new issue