зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1188545 - Cancel network interceptions when the service worker is being terminated with unresolved respondWith promises. r=nsm
This commit is contained in:
Родитель
e3772b283b
Коммит
d2e449fa0d
|
@ -195,6 +195,7 @@ class RespondWithHandler final : public PromiseNativeHandler
|
|||
const DebugOnly<bool> mIsClientRequest;
|
||||
const bool mIsNavigationRequest;
|
||||
const nsCString mScriptSpec;
|
||||
bool mRequestWasHandled;
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
@ -207,6 +208,7 @@ public:
|
|||
, mIsClientRequest(aIsClientRequest)
|
||||
, mIsNavigationRequest(aIsNavigationRequest)
|
||||
, mScriptSpec(aScriptSpec)
|
||||
, mRequestWasHandled(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -216,7 +218,12 @@ public:
|
|||
|
||||
void CancelRequest(nsresult aStatus);
|
||||
private:
|
||||
~RespondWithHandler() {}
|
||||
~RespondWithHandler()
|
||||
{
|
||||
if (!mRequestWasHandled) {
|
||||
CancelRequest(NS_ERROR_INTERCEPTION_FAILED);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct RespondWithClosure
|
||||
|
@ -382,6 +389,7 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
|
|||
|
||||
MOZ_ASSERT(!closure);
|
||||
autoCancel.Reset();
|
||||
mRequestWasHandled = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -396,6 +404,7 @@ RespondWithHandler::CancelRequest(nsresult aStatus)
|
|||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new CancelChannelRunnable(mInterceptedChannel, aStatus);
|
||||
NS_DispatchToMainThread(runnable);
|
||||
mRequestWasHandled = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -164,6 +164,7 @@ support-files =
|
|||
redirect_post.sjs
|
||||
xslt_worker.js
|
||||
xslt/*
|
||||
unresolved_fetch_worker.js
|
||||
|
||||
[test_app_protocol.html]
|
||||
skip-if = release_build
|
||||
|
@ -257,3 +258,4 @@ skip-if = toolkit == "android" || toolkit == "gonk"
|
|||
[test_eventsource_intercept.html]
|
||||
[test_not_intercept_plugin.html]
|
||||
[test_file_blob_upload.html]
|
||||
[test_unresolved_fetch_interception.html]
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that an unresolved respondWith promise will reset the channel when
|
||||
the service worker is terminated due to idling.
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1188545</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
||||
</head>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1188545">Mozilla Bug 118845</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function start() {
|
||||
return navigator.serviceWorker.register("unresolved_fetch_worker.js", {scope: "./"})
|
||||
.then((swr) => ({registration: swr}));
|
||||
}
|
||||
|
||||
function waitControlled(ctx) {
|
||||
var p = new Promise(function(res, rej) {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
res(ctx);
|
||||
} else {
|
||||
navigator.serviceWorker.oncontrollerchange = function() {
|
||||
res(ctx);
|
||||
navigator.serviceWorker.oncontrollerchange = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function unregister(ctx) {
|
||||
return ctx.registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
}, function(e) {
|
||||
dump("Unregistering the SW failed with " + e + "\n");
|
||||
});
|
||||
}
|
||||
|
||||
function testFetch(ctx) {
|
||||
ok(navigator.serviceWorker.controller, "Controlled");
|
||||
|
||||
var p = fetch("something_that_doesnt_exist_abcd.html")
|
||||
.catch(function() {
|
||||
ok(true, "channel was reset");
|
||||
}).then(function() { return ctx; });
|
||||
|
||||
navigator.serviceWorker.onmessage = function(event) {
|
||||
ok(event.data == "continue", "Got continue message from worker.");
|
||||
// close worker
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.idle_extended_timeout", 0]
|
||||
]}, function() {
|
||||
navigator.serviceWorker.controller.postMessage("shutdown");
|
||||
});
|
||||
|
||||
navigator.serviceWorker.onmessage = null;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
start()
|
||||
.then(waitControlled)
|
||||
.then(testFetch)
|
||||
.then(unregister)
|
||||
.catch(function(e) {
|
||||
ok(false, "Some test failed with error " + e)
|
||||
}).then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.idle_timeout", 0],
|
||||
["dom.serviceWorkers.idle_extended_timeout", 299999],
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["dom.serviceWorkers.interception.enabled", true]
|
||||
]}, runTest);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
onfetch = function(event) {
|
||||
if (!event.client) {
|
||||
dump("ERROR: event doesnt have a client");
|
||||
}
|
||||
|
||||
event.client.postMessage("continue");
|
||||
|
||||
// never resolve
|
||||
event.respondWith(new Promise(function(res, rej) {}));
|
||||
}
|
||||
|
||||
onactivate = function(event) {
|
||||
event.waitUntil(clients.claim());
|
||||
}
|
Загрузка…
Ссылка в новой задаче