Bug 1233798 - report to console when service worker register fails due to mime-type issues. r=bkelly
authorAndrew Sutherland <asutherland@asutherland.org>
Tue, 05 Jul 2016 22:24:23 -0400
changeset 344442 b8ca65757e7c645d759afe80d0fb8fd3f15d80d6
parent 344441 ad2cbcabbc571104bb0656668bdef187d0a1b122
child 344443 f3a1648af4e852c60f879ca8c7f83e8342e214ab
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1233798
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1233798 - report to console when service worker register fails due to mime-type issues. r=bkelly Log a message to the console when there is no Content-Type received for a service worker or it's not a JS type. With test. Looks like: Failed to register/update a ServiceWorker: Non-JS Content-Type of ‘text/plain’ received for script ‘http://mochi.test:8888/tests/dom/workers/test/serviceworkers/sw_bad_mime_type.js’.
dom/locales/en-US/chrome/dom/dom.properties
dom/workers/ServiceWorkerScriptCache.cpp
dom/workers/test/serviceworkers/mochitest.ini
dom/workers/test/serviceworkers/sw_bad_mime_type.js
dom/workers/test/serviceworkers/sw_bad_mime_type.js^headers^
dom/workers/test/serviceworkers/test_error_reporting.html
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -205,16 +205,18 @@ InterceptionCanceledWithURL=Failed to load ‘%S’. A ServiceWorker canceled the load by calling FetchEvent.preventDefault().
 # LOCALIZATION NOTE: Do not translate "ServiceWorker", "promise", or "FetchEvent.respondWith()". %1$S is a URL. %2$S is an error string.
 InterceptionRejectedResponseWithURL=Failed to load ‘%1$S’. A ServiceWorker passed a promise to FetchEvent.respondWith() that rejected with ‘%2$S’.
 # LOCALIZATION NOTE: Do not translate "ServiceWorker", "promise", "FetchEvent.respondWith()", or "Response". %1$S is a URL. %2$S is an error string.
 InterceptedNonResponseWithURL=Failed to load ‘%1$S’. A ServiceWorker passed a promise to FetchEvent.respondWith() that resolved with non-Response value ‘%2$S’.
 # LOCALIZATION NOTE: Do not translate "ServiceWorker", "Service-Worker-Allowed" or "HTTP". %1$S and %2$S are URLs.
 ServiceWorkerScopePathMismatch=Failed to register a ServiceWorker: The path of the provided scope ‘%1$S’ is not under the max scope allowed ‘%2$S’. Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.
 # LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is a URL representing the scope of the ServiceWorker, %2$S is a stringified numeric HTTP status code like "404" and %3$S is a URL.
 ServiceWorkerRegisterNetworkError=Failed to register/update a ServiceWorker for scope ‘%1$S’: Load failed with status %2$S for script ‘%3$S’.
+# LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is a URL representing the scope of the ServiceWorker, %2$S is a MIME Media Type like "text/plain" and %3$S is a URL.
+ServiceWorkerRegisterMimeTypeError=Failed to register/update a ServiceWorker for scope ‘%1$S’: Bad Content-Type of ‘%2$S’ received for script ‘%3$S’.  Must be ‘text/javascript’, ‘application/x-javascript’, or ‘application/javascript’.
 ExecCommandCutCopyDeniedNotInputDriven=document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler.
 ManifestShouldBeObject=Manifest should be an object.
 ManifestScopeURLInvalid=The scope URL is invalid.
 ManifestScopeNotSameOrigin=The scope URL must be same origin as document.
 ManifestStartURLOutsideScope=The start URL is outside the scope, so the scope is invalid.
 ManifestStartURLInvalid=The start URL is invalid.
 ManifestStartURLShouldBeSameOrigin=The start URL must be same origin as document.
 # LOCALIZATION NOTE: %1$S is the name of the object whose property is invalid. %2$S is the name of the invalid property. %3$S is the expected type of the property value. E.g. "Expected the manifest's start_url member to be a string."
--- a/dom/workers/ServiceWorkerScriptCache.cpp
+++ b/dom/workers/ServiceWorkerScriptCache.cpp
@@ -774,23 +774,32 @@ CompareNetwork::OnStreamComplete(nsIStre
     RefPtr<ServiceWorkerRegistrationInfo> registration =
       mManager->GetRegistration();
     registration->RefreshLastUpdateCheckTime();
   }
 
   nsAutoCString mimeType;
   rv = httpChannel->GetContentType(mimeType);
   if (NS_WARN_IF(NS_FAILED(rv))) {
+    // We should only end up here if !mResponseHead in the channel.  If headers
+    // were received but no content type was specified, we'll be given
+    // UNKNOWN_CONTENT_TYPE "application/x-unknown-content-type" and so fall
+    // into the next case with its better error message.
     mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
     return rv;
   }
 
   if (!mimeType.LowerCaseEqualsLiteral("text/javascript") &&
       !mimeType.LowerCaseEqualsLiteral("application/x-javascript") &&
       !mimeType.LowerCaseEqualsLiteral("application/javascript")) {
+    RefPtr<ServiceWorkerRegistrationInfo> registration = mManager->GetRegistration();
+    ServiceWorkerManager::LocalizeAndReportToAllClients(
+      registration->mScope, "ServiceWorkerRegisterMimeTypeError",
+      nsTArray<nsString> { NS_ConvertUTF8toUTF16(registration->mScope),
+        NS_ConvertUTF8toUTF16(mimeType), mManager->URL() });
     mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
     return rv;
   }
 
   char16_t* buffer = nullptr;
   size_t len = 0;
 
   rv = nsScriptLoader::ConvertToUTF16(httpChannel, aString, aLen,
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -201,16 +201,18 @@ support-files =
   redirect.sjs
   open_window/client.html
   lorem_script.js
   file_blob_response_worker.js
   !/dom/security/test/cors/file_CrossSiteXHR_server.sjs
   !/dom/tests/mochitest/notification/MockServices.js
   !/dom/tests/mochitest/notification/NotificationTest.js
   blocking_install_event_worker.js
+  sw_bad_mime_type.js
+  sw_bad_mime_type.js^headers^
 
 [test_bug1151916.html]
 [test_bug1240436.html]
 [test_claim.html]
 [test_claim_fetch.html]
 [test_claim_oninstall.html]
 [test_close.html]
 [test_controller.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/sw_bad_mime_type.js
@@ -0,0 +1,1 @@
+// I need some contents.
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/serviceworkers/sw_bad_mime_type.js^headers^
@@ -0,0 +1,1 @@
+Content-Type: text/plain
--- a/dom/workers/test/serviceworkers/test_error_reporting.html
+++ b/dom/workers/test/serviceworkers/test_error_reporting.html
@@ -93,12 +93,31 @@ add_task(function* register_404() {
   // which we need to consume so it doesn't get thrown at our generator.
   yield navigator.serviceWorker.register("404.js", { scope: "network_error/" })
     .then(
       () => { ok(false, "should have rejected"); },
       (e) => { ok(e.name === "TypeError", "404 failed as expected"); });
 
   yield wait_for_expected_message(expectedMessage);
 });
+
+/**
+ * Ensure an error is logged when the service worker is being served with a
+ * MIME type of text/plain rather than a JS type.
+ */
+add_task(function* register_bad_mime_type() {
+  let expectedMessage = expect_console_message(
+    "ServiceWorkerRegisterMimeTypeError",
+    [make_absolute_url("bad_mime_type/"), "text/plain",
+     make_absolute_url("sw_bad_mime_type.js")]);
+
+  // consume the expected rejection so it doesn't get thrown at us.
+  yield navigator.serviceWorker.register("sw_bad_mime_type.js", { scope: "bad_mime_type/" })
+    .then(
+      () => { ok(false, "should have rejected"); },
+      (e) => { ok(e.name === "SecurityError", "bad MIME type failed as expected"); });
+
+  yield wait_for_expected_message(expectedMessage);
+});
 </script>
 
 </body>
 </html>