Worker: Add credentials tests for dedicated workers

This CL adds web-platform-tests for the "credentials" option of WorkerOptions:
https://html.spec.whatwg.org/multipage/workers.html#workeroptions

The current spec defines that the default value of this option is "omit", but
there is an ongoing spec discussion to change it to "same-origin":
https://github.com/whatwg/html/pull/3656

This CL adds the tests based on the current spec, and a subsequent CL will
update them based on the decision.

Bug: 843875
Change-Id: I50eb0c7971587b9d84865498d67abef8ed2d8fc6
Reviewed-on: https://chromium-review.googlesource.com/1063524
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559888}
diff --git a/workers/modules/dedicated-worker-options-credentials.html b/workers/modules/dedicated-worker-options-credentials.html
new file mode 100644
index 0000000..316b01d
--- /dev/null
+++ b/workers/modules/dedicated-worker-options-credentials.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<title>DedicatedWorker: WorkerOptions 'credentials'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Determines the expected cookie value to be reported by a dedicated worker
+// based on the given option. The worker reports an empty string as the actual
+// cookie value if the cookie wasn't sent to the server. Otherwise, it's the
+// value set by the headers file:
+// "dedicated-worker-options-credentials.html.headers"
+function DetermineExpectedCookieValue(options) {
+  // Classic script loading should always send credentials regardless of the
+  // 'credentials' option because the spec says the option takes effect only
+  // for module script loading.
+  if (options.type == 'classic')
+    return 'COOKIE_VALUE';
+  assert_equals(options.type, 'module');
+
+  if (!options.credentials || options.credentials == 'omit')
+    return '';
+  if (options.credentials == 'same-origin' || options.credentials == 'include')
+    return 'COOKIE_VALUE';
+  assert_unreached('Invalid credentials option was specified: ' +
+                   options.credentials);
+}
+
+// Runs a credentials test with the given WorkerOptions.
+async function runCredentialsTest(options) {
+  const worker = new Worker('resources/credentials.py', options);
+
+  // Wait until the worker sends the actual cookie value.
+  const msg_event = await new Promise(resolve => worker.onmessage = resolve);
+
+  const expectedCookieValue = DetermineExpectedCookieValue(options);
+  assert_equals(msg_event.data, expectedCookieValue);
+}
+
+// Tests for module scripts.
+
+promise_test(() => runCredentialsTest({ type: 'module'}),
+    'new Worker() with the default credentials option should not send ' +
+    'the credentials');
+
+promise_test(() => runCredentialsTest({ credentials: 'omit',
+                                        type: 'module' }),
+    'new Worker() with credentials=omit should not send the credentials');
+
+promise_test(() => runCredentialsTest({ credentials: 'same-origin',
+                                        type: 'module' }),
+    'new Worker() with credentials=same-origin should send the credentials');
+
+promise_test(() => runCredentialsTest({ credentials: 'include',
+                                        type: 'module' }),
+    'new Worker() with credentials=include should send the credentials');
+
+// Tests for classic scripts.
+
+promise_test(() => runCredentialsTest({ type: 'classic' }),
+    'new Worker() with type=classic should always send the credentials ' +
+    'regardless of the credentials option (default).');
+
+promise_test(() => runCredentialsTest({ credentials: 'omit',
+                                        type: 'classic' }),
+    'new Worker() with type=classic should always send the credentials ' +
+    'regardless of the credentials option (omit).');
+
+promise_test(() => runCredentialsTest({ credentials: 'same-origin',
+                                        type: 'classic' }),
+    'new Worker() with type=classic should always send the credentials ' +
+    'regardless of the credentials option (same-origin).');
+
+promise_test(() => runCredentialsTest({ credentials: 'include',
+                                        type: 'classic' }),
+    'new Worker() with type=classic should always send the credentials ' +
+    'regardless of the credentials option (include).');
+
+</script>
diff --git a/workers/modules/dedicated-worker-options-credentials.html.headers b/workers/modules/dedicated-worker-options-credentials.html.headers
new file mode 100644
index 0000000..6f53744
--- /dev/null
+++ b/workers/modules/dedicated-worker-options-credentials.html.headers
@@ -0,0 +1,2 @@
+Set-Cookie: COOKIE_NAME=COOKIE_VALUE
+Access-Control-Allow-Credentials: true
diff --git a/workers/modules/resources/credentials.py b/workers/modules/resources/credentials.py
new file mode 100644
index 0000000..8f79563
--- /dev/null
+++ b/workers/modules/resources/credentials.py
@@ -0,0 +1,10 @@
+def main(request, response):
+    cookie = request.cookies.first("COOKIE_NAME", None)
+
+    response_headers = [("Content-Type", "text/javascript"),
+                        ("Access-Control-Allow-Credentials", "true")]
+
+    cookie_value = '';
+    if cookie:
+        cookie_value = cookie.value;
+    return (200, response_headers, "postMessage('"+cookie_value+"');")