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

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

Powered by Google App Engine
This is Rietveld 408576698