Skip to content

Commit

Permalink
RemoteContextHelper: expose all request headers
Browse files Browse the repository at this point in the history
Previously, we would manually update executor.sub.html to output request
headers into the HTML body. The result would be stored as a global
variable, window.requestHeaders, with absent headers having the string
value "absent".

This improves the situation in several ways:

* Adds a first-class API, getRequestHeaders(), to RemoteContextHelper,
  instead of relying on the implicit knowledge that if you use
  executeScript(), you can retrieve a global window.requestHeaders.

* The returned object is a Headers object, instead of an object literal.
  Absent headers are simply not in the object, instead of being the
  string "absent".

* The returned object has all request headers, not a manually-curated
  list.

* Because all headers are sent across the boundary at once, in the
  single getRequestHeaders() call, we no longer have to call into the
  remote context using executeScript() once per header of interest.

Bug: 1456579
Change-Id: I2c88fde4ed3007e712496f6ab807851e89ac6c6f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4778110
Reviewed-by: Fergal Daly <fergal@chromium.org>
Commit-Queue: Domenic Denicola <domenic@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1185025}
  • Loading branch information
domenic authored and Chromium LUCI CQ committed Aug 18, 2023
1 parent 405818a commit 5701e7c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,14 @@
// now-same-origin document initiating this navigation via history.
await A.historyForward();

const secFetchSite = await B.executeScript(() => window.requestHeaders['sec-fetch-site']);
const referrer = await B.executeScript(() => window.requestHeaders['referer']);
const requestHeaders = await B.getRequestHeaders();
const documentReferrer = await B.executeScript(() => document.referrer);

assert_equals(secFetchSite, 'cross-site',
assert_equals(requestHeaders.get('sec-fetch-site'), 'cross-site',
'Same-origin forward history navigation to a document whose original ' +
'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' +
'header');
assert_equals(referrer, originA + '/',
assert_equals(requestHeaders.get('referer'), originA + '/',
'Same-origin forward history navigation to a document whose original ' +
'initiator was cross-site ends up with the Referer header that is the ' +
'original cross-site initiator');
Expand Down Expand Up @@ -113,15 +112,14 @@
location.reload();
}, []);

const secFetchSite = await B.executeScript(() => window.requestHeaders['sec-fetch-site']);
const referrer = await B.executeScript(() => window.requestHeaders['referer']);
const requestHeaders = await B.getRequestHeaders();
const documentReferrer = await B.executeScript(() => document.referrer);

assert_equals(secFetchSite, 'cross-site',
assert_equals(requestHeaders.get('sec-fetch-site'), 'cross-site',
'Same-origin forward history navigation to a document whose original ' +
'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' +
'header');
assert_equals(referrer, originA + '/',
assert_equals(requestHeaders.get('referer'), originA + '/',
'Same-origin forward history navigation to a document whose original ' +
'initiator was cross-site ends up with the Referer header that is the ' +
'original cross-site initiator');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// META: title=RemoteContextHelper with defaults
// META: script=/common/dispatcher/dispatcher.js
// META: script=/common/get-host-info.sub.js
// META: script=/common/utils.js
// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
// META: script=./resources/test-helper.js

'use strict';

promise_test(async t => {
const rcHelper = new RemoteContextHelper();
const main = await rcHelper.addWindow();

const headers = await main.getRequestHeaders();

assert_equals(headers.constructor, Headers);
assert_true(headers.has("user-agent"), "user-agent is present");
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import json

def main(request, response):
initRequestHeaders = ""
for header_name in request.headers.keys():
for header_value in request.headers.get_list(header_name):
js_name = json.dumps(header_name.lower().decode("utf-8"))
js_value = json.dumps(header_value.decode("utf-8"))
initRequestHeaders += f"window.__requestHeaders.append({js_name}, {js_value});\n"

return (200, [("Content-Type", "text/html")], f"""
<!DOCTYPE HTML>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="./executor-common.js"></script>
<script src="./executor-window.js"></script>
<body>
<script>
window.__requestHeaders = new Headers();
{initRequestHeaders}
requestExecutor();
</script>
""")

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
{
const RESOURCES_PATH =
'/html/browsers/browsing-the-web/remote-context-helper/resources';
const WINDOW_EXECUTOR_PATH = `${RESOURCES_PATH}/executor.sub.html`;
const WINDOW_EXECUTOR_PATH = `${RESOURCES_PATH}/executor-window.py`;
const WORKER_EXECUTOR_PATH = `${RESOURCES_PATH}/executor-worker.js`;

/**
Expand Down Expand Up @@ -383,6 +383,26 @@
});
}

/**
* Gets a `Headers` object containing the request headers that were used
* when the browser requested this document.
*
* Currently, this only works for `RemoteContextHelper`s representing
* windows, not workers.
* @returns {Promise<Headers>}
*/
async getRequestHeaders() {
// This only works in window environments for now. We could make it work
// for workers too; if you have a need, just share or duplicate the code
// that's in executor-window.py. Anyway, we explicitly use `window` in
// the script so that we get a clear error if you try using it on a
// worker.

// We need to serialize and deserialize the `Headers` object manually.
const asNestedArrays = await this.executeScript(() => [...window.__requestHeaders]);
return new Headers(asNestedArrays);
}

/**
* Executes a script in the remote context that will perform a navigation.
* To do this safely, we must suspend the executor and wait for that to
Expand Down

0 comments on commit 5701e7c

Please sign in to comment.