service worker: WPT: Add generated response tests for XHR response URL.

respondWith(new Response()) is a little tricky for response URL so it's
good to have a test for it.

Bug: 915126
Change-Id: I21fbc654687d467baf14f02c23f4e41d18ac79ab
Reviewed-on: https://chromium-review.googlesource.com/c/1415613
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#623577}
diff --git a/service-workers/service-worker/resources/xhr-response-url-worker.js b/service-workers/service-worker/resources/xhr-response-url-worker.js
new file mode 100644
index 0000000..906ad50
--- /dev/null
+++ b/service-workers/service-worker/resources/xhr-response-url-worker.js
@@ -0,0 +1,32 @@
+// Service worker for the xhr-response-url test.
+
+self.addEventListener('fetch', event => {
+  const url = new URL(event.request.url);
+  const respondWith = url.searchParams.get('respondWith');
+  if (!respondWith)
+    return;
+
+  if (respondWith == 'fetch') {
+    const target = url.searchParams.get('url');
+    event.respondWith(fetch(target));
+    return;
+  }
+
+  if (respondWith == 'string') {
+    const headers = {'content-type': 'text/plain'};
+    event.respondWith(new Response('hello', {headers}));
+    return;
+  }
+
+  if (respondWith == 'document') {
+    const doc = `
+        <!DOCTYPE html>
+        <html>
+        <title>hi</title>
+        <body>hello</body>
+        </html>`;
+    const headers = {'content-type': 'text/html'};
+    event.respondWith(new Response(doc, {headers}));
+    return;
+  }
+});
diff --git a/service-workers/service-worker/xhr-response-url.https.html b/service-workers/service-worker/xhr-response-url.https.html
index 6c2cf67..1ad2ce3 100644
--- a/service-workers/service-worker/xhr-response-url.https.html
+++ b/service-workers/service-worker/xhr-response-url.https.html
@@ -6,9 +6,19 @@
 <script src="resources/test-helpers.sub.js"></script>
 <script>
 const scope = 'resources/xhr-iframe.html';
-const script = 'resources/fetch-rewrite-worker.js';
+const script = 'resources/xhr-response-url-worker.js';
 let iframe;
 
+function build_url(options) {
+  const url = new URL('test', window.location);
+  const opts = options ? options : {};
+  if (opts.respondWith)
+    url.searchParams.set('respondWith', opts.respondWith);
+  if (opts.url)
+    url.searchParams.set('url', opts.url.href);
+  return url.href;
+}
+
 promise_test(async (t) => {
   const registration =
       await service_worker_unregister_and_register(t, script, scope);
@@ -19,23 +29,37 @@
 // Test that XMLHttpRequest.responseURL uses the response URL from the service
 // worker.
 promise_test(async (t) => {
-  // Build the XHR URL. Set the |url| param to tell the service worker
-  // to respondWith(fetch(|url|)).
+  // Build a URL that tells the service worker to respondWith(fetch(|target|)).
   const target = new URL('resources/dummy.txt', window.location);
-  const url = `test?url=${encodeURIComponent(target)}`;
+  const url = build_url({
+    respondWith: 'fetch',
+    url: target
+  });
 
   // Perform the XHR.
   const xhr = await iframe.contentWindow.xhr(url);
   assert_equals(xhr.responseURL, target.href, 'responseURL');
 }, 'XHR responseURL should be the response URL');
 
+// Same as above with a generated response.
+promise_test(async (t) => {
+  // Build a URL that tells the service worker to respondWith(new Response()).
+  const url = build_url({respondWith: 'string'});
+
+  // Perform the XHR.
+  const xhr = await iframe.contentWindow.xhr(url);
+  assert_equals(xhr.responseURL, url, 'responseURL');
+}, 'XHR responseURL should be the response URL (generated response)');
+
 // Test that XMLHttpRequest.responseXML is a Document whose URL is the
 // response URL from the service worker.
 promise_test(async (t) => {
-  // Build the XHR URL. Set the |url| param to tell the service worker
-  // to respondWith(fetch(|url|)).
+  // Build a URL that tells the service worker to respondWith(fetch(|target|)).
   const target = new URL('resources/blank.html', window.location);
-  const url = `test?url=${encodeURIComponent(target)}`;
+  const url = build_url({
+    respondWith: 'fetch',
+    url: target
+  });
 
   // Perform the XHR.
   const xhr = await iframe.contentWindow.xhr(url, {responseType: 'document'});
@@ -51,6 +75,26 @@
   assert_equals(xhr.responseXML.baseURI, target.href, 'responseXML.baseURI');
 }, 'XHR Document should use the response URL');
 
+// Same as above with a generated response from the service worker.
+promise_test(async (t) => {
+  // Build a URL that tells the service worker to
+  // respondWith(new Response()) with a document response.
+  const url = build_url({respondWith: 'document'});
+
+  // Perform the XHR.
+  const xhr = await iframe.contentWindow.xhr(url, {responseType: 'document'});
+  assert_equals(xhr.responseURL, url, 'responseURL');
+
+  // The document's URL uses the response URL, which is the request URL:
+  // "Set |document|’s URL to |response|’s url."
+  // https://xhr.spec.whatwg.org/#document-response
+  assert_equals(xhr.responseXML.URL, url, 'responseXML.URL');
+
+  // The document's base URL falls back to the document URL:
+  // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#document-base-url
+  assert_equals(xhr.responseXML.baseURI, url, 'responseXML.baseURI');
+}, 'XHR Document should use the response URL (generated response)');
+
 promise_test(async (t) => {
   if (iframe)
     iframe.remove();