Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: content/browser/resources/service_worker/serviceworker_internals.js

Issue 304543002: Show the unregistered workers in chrome://serviceworker-internals and chrome://inspect (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: incorporated falken's comment Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 cr.define('serviceworker', function() { 5 cr.define('serviceworker', function() {
6 'use strict'; 6 'use strict';
7 7
8 function initialize() { 8 function initialize() {
9 if (window.location.hash == "#iframe") { 9 if (window.location.hash == "#iframe") {
10 // This page is loaded from chrome://inspect. 10 // This page is loaded from chrome://inspect.
11 window.addEventListener('message', onMessage.bind(this), false); 11 window.addEventListener('message', onMessage.bind(this), false);
12 }
13 update();
14 }
15
16 function onMessage(event) {
17 if (event.origin != 'chrome://inspect') {
18 return;
19 }
20 sendCommand(event.data.action, event.data.worker);
21 }
22
23 function update() {
24 chrome.send('getAllRegistrations');
25 }
26
27 function progressNodeFor(link) {
28 return link.parentNode.querySelector('.operation-status');
29 }
30
31 // All commands are sent with the partition_path and scope, and are all
32 // completed with 'onOperationComplete'.
33 var COMMANDS = ['stop', 'sync', 'inspect', 'unregister', 'start'];
34 function commandHandler(command) {
35 return function(event) {
36 var link = event.target;
37 progressNodeFor(link).style.display = 'inline';
38 sendCommand(command, link.cmdArgs, (function(status) {
39 progressNodeFor(link).style.display = 'none';
40 }).bind(null, link));
41 return false;
42 };
43 };
44
45 var commandCallbacks = [];
46 function sendCommand(command, args, callback) {
47 var callbackId = 0;
48 while (callbackId in commandCallbacks) {
49 callbackId++;
50 }
51 commandCallbacks[callbackId] = callback;
52 chrome.send(command, [callbackId, args]);
53 }
54
55 // Fired from the backend after the command call has completed.
56 function onOperationComplete(status, callbackId) {
57 var callback = commandCallbacks[callbackId];
58 delete commandCallbacks[callbackId];
59 if (callback) {
60 callback(status);
61 }
62 update();
63 }
64
65 // Send the active ServiceWorker information to chrome://inspect.
66 function sendToInspectPage(live_registrations,
67 partition_id) {
68 var workers = [];
69 live_registrations.forEach(function(registration) {
70 [registration.active, registration.pending].forEach(function(version) {
71 if (!version || version.running_status != 'RUNNING') {
72 return;
12 } 73 }
13 update(); 74 workers.push({
14 } 75 'scope': registration.scope,
15 76 'url': registration.script_url,
16 function onMessage(event) { 77 'partition_id': partition_id,
17 if (event.origin != 'chrome://inspect') { 78 'version_id': version.version_id,
18 return; 79 'process_id': version.process_id,
80 'devtools_agent_route_id':
81 version.devtools_agent_route_id
82 });
83 });
84 });
85 window.parent.postMessage(
86 {'partition_id': partition_id, 'workers': workers},
87 'chrome://inspect');
88 }
89
90 var allLogMessages = {};
91 // Set log for a worker version.
92 function fillLogForVersion(partition_id, version) {
93 if (!version) {
94 return;
95 }
96 if (!(partition_id in allLogMessages)) {
97 allLogMessages[partition_id] = {};
98 }
99 var logMessages = allLogMessages[partition_id];
100 if (version.version_id in logMessages) {
101 version.log = logMessages[version.version_id];
102 } else {
103 version.log = '';
104 }
105 }
106
107 // Get the unregistered workers.
108 // |unregistered_registrations| will be filled with the registrations which
109 // are in |live_registrations| but not in |stored_registrations|.
110 // |unregistered_versions| will be filled with the versions which
111 // are in |live_versions| but not in |stored_registrations| nor in
112 // |live_registrations|.
113 function getUnregisteredWorkers(stored_registrations,
114 live_registrations,
115 live_versions,
116 unregistered_registrations,
117 unregistered_versions) {
118 var registration_id_set = {};
119 var version_id_set = {};
120 stored_registrations.forEach(function(registration) {
121 registration_id_set[registration.registration_id] = true;
122 });
123 [stored_registrations, live_registrations].forEach(function(registrations) {
124 registrations.forEach(function(registration) {
125 [registration.active, registration.pending].forEach(function(version) {
126 if (version) {
127 version_id_set[version.version_id] = true;
128 }
129 });
130 });
131 });
132 live_registrations.forEach(function(registration) {
133 if (!registration_id_set[registration.registration_id]) {
134 registration.unregistered = true;
135 unregistered_registrations.push(registration);
136 }
137 });
138 live_versions.forEach(function(version) {
139 if (!version_id_set[version.version_id]) {
140 unregistered_versions.push(version);
141 }
142 });
143 }
144
145 // Fired once per partition from the backend.
146 function onPartitionData(live_registrations,
147 live_versions,
148 stored_registrations,
149 partition_id,
150 partition_path) {
151 if (window.location.hash == "#iframe") {
152 // This page is loaded from chrome://inspect.
153 sendToInspectPage(live_registrations, partition_id);
154 return;
155 }
156 var unregistered_registrations = [];
157 var unregistered_versions = [];
158 getUnregisteredWorkers(stored_registrations,
159 live_registrations,
160 live_versions,
161 unregistered_registrations,
162 unregistered_versions);
163 var template;
164 var container = $('serviceworker-list');
165 // Existing templates are keyed by partition_path. This allows
166 // the UI to be updated in-place rather than refreshing the
167 // whole page.
168 for (var i = 0; i < container.childNodes.length; ++i) {
169 if (container.childNodes[i].partition_path == partition_path) {
170 template = container.childNodes[i];
171 }
172 }
173 // This is probably the first time we're loading.
174 if (!template) {
175 template = jstGetTemplate('serviceworker-list-template');
176 container.appendChild(template);
177 }
178 var fillLogFunc = fillLogForVersion.bind(this, partition_id);
179 stored_registrations.forEach(function(registration) {
180 [registration.active, registration.pending].forEach(fillLogFunc);
181 });
182 unregistered_registrations.forEach(function(registration) {
183 [registration.active, registration.pending].forEach(fillLogFunc);
184 });
185 unregistered_versions.forEach(fillLogFunc);
186 jstProcess(new JsEvalContext({
187 stored_registrations: stored_registrations,
188 unregistered_registrations: unregistered_registrations,
189 unregistered_versions: unregistered_versions,
190 partition_id: partition_id,
191 partition_path: partition_path}),
192 template);
193 for (var i = 0; i < COMMANDS.length; ++i) {
194 var handler = commandHandler(COMMANDS[i]);
195 var links = container.querySelectorAll('button.' + COMMANDS[i]);
196 for (var j = 0; j < links.length; ++j) {
197 if (!links[j].hasClickEvent) {
198 links[j].addEventListener('click', handler, false);
199 links[j].hasClickEvent = true;
19 } 200 }
20 chrome.send(event.data.action, 201 }
21 [event.data.partition_path, event.data.scope]); 202 }
22 } 203 }
23 204
24 function update() { 205 function onWorkerStarted(partition_id, version_id, process_id, thread_id) {
25 chrome.send('getAllRegistrations'); 206 update();
26 } 207 }
27 208
28 function progressNodeFor(link) { 209 function onWorkerStopped(partition_id, version_id, process_id, thread_id) {
29 return link.parentNode.querySelector('.operation-status'); 210 update();
30 } 211 }
31 212
32 // All commands are sent with the partition_path and scope, and 213 function onErrorReported(partition_id,
33 // are all completed with 'onOperationComplete'. 214 version_id,
34 var COMMANDS = ['unregister', 'start', 'stop', 'sync', 'inspect']; 215 process_id,
35 function commandHandler(command) { 216 thread_id,
36 return function(event) { 217 error_info) {
37 var link = event.target; 218 outputLogMessage(partition_id,
38 progressNodeFor(link).style.display = 'inline'; 219 version_id,
39 chrome.send(command, [link.partition_path, 220 'Error: ' + JSON.stringify(error_info) + '\n');
40 link.scope]); 221 }
41 return false; 222
42 }; 223 function onConsoleMessageReported(partition_id,
43 }; 224 version_id,
44 225 process_id,
45 function withNode(selector, partition_path, scope, callback) { 226 thread_id,
46 var links = document.querySelectorAll(selector); 227 message) {
47 for (var i = 0; i < links.length; ++i) { 228 outputLogMessage(partition_id,
48 var link = links[i]; 229 version_id,
49 if (partition_path == link.partition_path && 230 'Console: ' + JSON.stringify(message) + '\n');
50 scope == link.scope) { 231 }
51 callback(link); 232
52 } 233 function onVersionStateChanged(partition_id, version_id) {
53 } 234 update();
54 } 235 }
55 236
56 // Fired from the backend after the start call has completed 237 function onRegistrationStored(scope) {
57 function onOperationComplete(status, path, scope) { 238 update();
58 // refreshes the ui, displaying any relevant buttons 239 }
59 withNode('button', path, scope, function(link) { 240
60 progressNodeFor(link).style.display = 'none'; 241 function onRegistrationDeleted(scope) {
61 }); 242 update();
62 update(); 243 }
63 } 244
64 245 function outputLogMessage(partition_id, version_id, message) {
65 var allLogMessages = {}; 246 if (!(partition_id in allLogMessages)) {
66 247 allLogMessages[partition_id] = {};
67 // Send the active ServiceWorker information to chrome://inspect. 248 }
68 function sendToInspectPage(registrations, partition_id, partition_path) { 249 var logMessages = allLogMessages[partition_id];
69 var workers = []; 250 if (version_id in logMessages) {
70 for (var i = 0; i < registrations.length; i++) { 251 logMessages[version_id] += message;
71 var registration = registrations[i]; 252 } else {
72 if (!registration.active || 253 logMessages[version_id] = message;
73 registration.active.running_status != 'RUNNING') { 254 }
74 continue; 255
75 } 256 var logAreas = document.querySelectorAll('textarea.serviceworker-log');
76 workers.push({ 257 for (var i = 0; i < logAreas.length; ++i) {
77 'partition_path': partition_path, 258 var logArea = logAreas[i];
78 'scope': registration.scope, 259 if (logArea.partition_id == partition_id &&
79 'url': registration.script_url 260 logArea.version_id == version_id) {
80 }) 261 logArea.value += message;
81 } 262 }
82 window.parent.postMessage({ 263 }
83 'partition_id': partition_id, 264 }
84 'workers': workers, 265
85 }, 'chrome://inspect') 266 return {
86 } 267 initialize: initialize,
87 268 onOperationComplete: onOperationComplete,
88 // Fired once per partition from the backend. 269 onPartitionData: onPartitionData,
89 function onPartitionData(registrations, partition_id, partition_path) { 270 onWorkerStarted: onWorkerStarted,
90 if (window.location.hash == "#iframe") { 271 onWorkerStopped: onWorkerStopped,
91 // This page is loaded from chrome://inspect. 272 onErrorReported: onErrorReported,
92 sendToInspectPage(registrations, partition_id, partition_path); 273 onConsoleMessageReported: onConsoleMessageReported,
93 return; 274 onVersionStateChanged: onVersionStateChanged,
94 } 275 onRegistrationStored: onRegistrationStored,
95 var template; 276 onRegistrationDeleted: onRegistrationDeleted,
96 var container = $('serviceworker-list'); 277 };
97
98 // Existing templates are keyed by partition_path. This allows
99 // the UI to be updated in-place rather than refreshing the
100 // whole page.
101 for (var i = 0; i < container.childNodes.length; ++i) {
102 if (container.childNodes[i].partition_path == partition_path) {
103 template = container.childNodes[i];
104 }
105 }
106
107 // This is probably the first time we're loading.
108 if (!template) {
109 template = jstGetTemplate('serviceworker-list-template');
110 container.appendChild(template);
111 }
112
113 // Set log for each worker versions.
114 if (!(partition_id in allLogMessages)) {
115 allLogMessages[partition_id] = {};
116 }
117 var logMessages = allLogMessages[partition_id];
118 registrations.forEach(function (worker) {
119 [worker.active, worker.pending].forEach(function (version) {
120 if (version) {
121 if (version.version_id in logMessages) {
122 version.log = logMessages[version.version_id];
123 } else {
124 version.log = '';
125 }
126 }
127 });
128 });
129
130 jstProcess(new JsEvalContext({ registrations: registrations,
131 partition_id: partition_id,
132 partition_path: partition_path}),
133 template);
134 for (var i = 0; i < COMMANDS.length; ++i) {
135 var handler = commandHandler(COMMANDS[i]);
136 var links = container.querySelectorAll('button.' + COMMANDS[i]);
137 for (var j = 0; j < links.length; ++j) {
138 if (!links[j].hasClickEvent) {
139 links[j].addEventListener('click', handler, false);
140 links[j].hasClickEvent = true;
141 }
142 }
143 }
144 }
145
146 function onWorkerStarted(partition_id, version_id, process_id, thread_id) {
147 update();
148 }
149
150 function onWorkerStopped(partition_id, version_id, process_id, thread_id) {
151 update();
152 }
153
154 function onErrorReported(partition_id,
155 version_id,
156 process_id,
157 thread_id,
158 error_info) {
159 outputLogMessage(partition_id,
160 version_id,
161 'Error: ' + JSON.stringify(error_info) + '\n');
162 }
163
164 function onConsoleMessageReported(partition_id,
165 version_id,
166 process_id,
167 thread_id,
168 message) {
169 outputLogMessage(partition_id,
170 version_id,
171 'Console: ' + JSON.stringify(message) + '\n');
172 }
173
174 function onVersionStateChanged(partition_id, version_id) {
175 update();
176 }
177
178 function onRegistrationStored(scope) {
179 update();
180 }
181
182 function onRegistrationDeleted(scope) {
183 update();
184 }
185
186 function outputLogMessage(partition_id, version_id, message) {
187 if (!(partition_id in allLogMessages)) {
188 allLogMessages[partition_id] = {};
189 }
190 var logMessages = allLogMessages[partition_id];
191 if (version_id in logMessages) {
192 logMessages[version_id] += message;
193 } else {
194 logMessages[version_id] = message;
195 }
196
197 var logAreas =
198 document.querySelectorAll('textarea.serviceworker-log');
199 for (var i = 0; i < logAreas.length; ++i) {
200 var logArea = logAreas[i];
201 if (logArea.partition_id == partition_id &&
202 logArea.version_id == version_id) {
203 logArea.value += message;
204 }
205 }
206 }
207
208 return {
209 initialize: initialize,
210 update: update,
211 onOperationComplete: onOperationComplete,
212 onPartitionData: onPartitionData,
213 onWorkerStarted: onWorkerStarted,
214 onWorkerStopped: onWorkerStopped,
215 onErrorReported: onErrorReported,
216 onConsoleMessageReported: onConsoleMessageReported,
217 onVersionStateChanged: onVersionStateChanged,
218 onRegistrationStored: onRegistrationStored,
219 onRegistrationDeleted: onRegistrationDeleted,
220 };
221 }); 278 });
222 279
223 document.addEventListener('DOMContentLoaded', serviceworker.initialize); 280 document.addEventListener('DOMContentLoaded', serviceworker.initialize);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698