Commit 9cbeba16 authored by nhiroki's avatar nhiroki Committed by Commit bot

ServiceWorker: Fix messed registration attributes on ServiceWorkerGlobalScope

This is the fix for regression introduced by
https://codereview.chromium.org/1344783002

After the CL, SWProviderContext::ControllerDelegate::AssociateRegistration()
wrongly set its |installing_| field to the active worker and |active_| field
to nullptr. These messed fields eventually show up as
ServiceWorkerGlobalScope.registration's version attributes.

This CL fixes the wrong field assignment and adds layout tests.

BUG=532098, 557551

Review URL: https://codereview.chromium.org/1460653002

Cr-Commit-Position: refs/heads/master@{#360557}
parent 66656ced
......@@ -92,7 +92,7 @@ class ServiceWorkerProviderContext::ControllerDelegate
scoped_ptr<ServiceWorkerHandleReference> active) override {
DCHECK(!registration_);
registration_ = registration.Pass();
installing_ = active.Pass();
installing_ = installing.Pass();
waiting_ = waiting.Pass();
active_ = active.Pass();
}
......
......@@ -11,6 +11,7 @@ promise_test(function(t) {
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
add_completion_callback(function() { registration.unregister(); });
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
......@@ -30,8 +31,71 @@ promise_test(function(t) {
expected_events_seen.toString(),
'Service Worker should respond to fetch');
frame.remove();
return service_worker_unregister_and_done(t, scope);
});
}, 'Verify registration attribute on ServiceWorkerGlobalScope');
}, 'Verify registration attributes on ServiceWorkerGlobalScope');
promise_test(function(t) {
var script = 'resources/registration-attribute-worker.js';
var newer_script = 'resources/registration-attribute-newer-worker.js';
var scope = 'resources/scope/registration-attribute';
var newer_worker;
return service_worker_unregister_and_register(t, script, scope)
.then(function(registration) {
add_completion_callback(function() { registration.unregister(); });
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
return navigator.serviceWorker.register(newer_script, {scope: scope});
})
.then(function(registration) {
newer_worker = registration.installing;
return wait_for_state(t, registration.installing, 'activated');
})
.then(function() {
var channel = new MessageChannel;
var saw_message = new Promise(function(resolve) {
channel.port1.onmessage = function(e) { resolve(e.data); };
});
newer_worker.postMessage({port: channel.port2}, [channel.port2]);
return saw_message;
})
.then(function(results) {
var script_url = normalizeURL(script);
var newer_script_url = normalizeURL(newer_script);
var expectations = [
'evaluate',
' installing: empty',
' waiting: empty',
' active: ' + script_url,
'updatefound',
' installing: ' + newer_script_url,
' waiting: empty',
' active: ' + script_url,
'install',
' installing: ' + newer_script_url,
' waiting: empty',
' active: ' + script_url,
'statechange(installed)',
' installing: empty',
' waiting: ' + newer_script_url,
' active: ' + script_url,
'statechange(activating)',
' installing: empty',
' waiting: empty',
' active: ' + newer_script_url,
'activate',
' installing: empty',
' waiting: empty',
' active: ' + newer_script_url,
'statechange(activated)',
' installing: empty',
' waiting: empty',
' active: ' + newer_script_url,
];
assert_array_equals(results, expectations);
});
}, 'Verify registration attributes on ServiceWorkerGlobalScope of the ' +
'newer worker');
</script>
// TODO(nhiroki): stop using global states because service workers can be killed
// at any point. Instead, we could post a message to the page on each event via
// Client object (http://crbug.com/558244).
var results = [];
function stringify(worker) {
return worker ? worker.scriptURL : 'empty';
}
function record(event_name) {
results.push(event_name);
results.push(' installing: ' + stringify(self.registration.installing));
results.push(' waiting: ' + stringify(self.registration.waiting));
results.push(' active: ' + stringify(self.registration.active));
}
record('evaluate');
self.registration.addEventListener('updatefound', function() {
record('updatefound');
var worker = self.registration.installing;
self.registration.installing.addEventListener('statechange', function() {
record('statechange(' + worker.state + ')');
});
});
self.addEventListener('install', function(e) { record('install'); });
self.addEventListener('activate', function(e) { record('activate'); });
self.addEventListener('message', function(e) {
e.data.port.postMessage(results);
});
importScripts('../../resources/test-helpers.js');
importScripts('../../resources/worker-testharness.js');
// TODO(nhiroki): stop using global states because service workers can be killed
// at any point. Instead, we could post a message to the page on each event via
// Client object (http://crbug.com/558244).
var events_seen = [];
// TODO(nhiroki): Move these assertions to registration-attribute.html because
// an assertion failure on the worker is not shown on the result page and
// handled as timeout. See registration-attribute-newer-worker.js for example.
assert_equals(
self.registration.scope,
normalizeURL('scope/registration-attribute'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment