OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @constructor | |
7 * @implements {WebInspector.OutputStream} | |
8 * @param {!WebInspector.TimelineModel} model | |
9 * @param {!WebInspector.Progress} progress | |
10 * @param {function()=} canceledCallback | |
11 */ | |
12 WebInspector.TimelineLoader = function(model, progress, canceledCallback) | |
13 { | |
14 this._model = model; | |
15 | |
16 this._canceledCallback = canceledCallback; | |
17 this._progress = progress; | |
18 this._progress.setTitle(WebInspector.UIString("Loading")); | |
19 this._progress.setTotalWork(WebInspector.TimelineLoader._totalProgress); //
Unknown, will loop the values. | |
20 | |
21 this._state = WebInspector.TimelineLoader.State.Initial; | |
22 this._buffer = ""; | |
23 this._firstChunk = true; | |
24 this._wasCanceledOnce = false; | |
25 | |
26 this._loadedBytes = 0; | |
27 this._jsonTokenizer = new WebInspector.TextUtils.BalancedJSONTokenizer(this.
_writeBalancedJSON.bind(this), true); | |
28 } | |
29 | |
30 /** | |
31 * @param {!WebInspector.TimelineModel} model | |
32 * @param {!File} file | |
33 * @param {!WebInspector.Progress} progress | |
34 */ | |
35 WebInspector.TimelineLoader.loadFromFile = function(model, file, progress) | |
36 { | |
37 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(model, pro
gress); | |
38 var fileReader = WebInspector.TimelineLoader._createFileReader(file, delegat
e); | |
39 var loader = new WebInspector.TimelineLoader(model, new WebInspector.Progres
sProxy(null), fileReader.cancel.bind(fileReader)); | |
40 fileReader.start(loader); | |
41 } | |
42 | |
43 /** | |
44 * @param {!WebInspector.TimelineModel} model | |
45 * @param {string} url | |
46 * @param {!WebInspector.Progress} progress | |
47 */ | |
48 WebInspector.TimelineLoader.loadFromURL = function(model, url, progress) | |
49 { | |
50 var stream = new WebInspector.TimelineLoader(model, progress); | |
51 WebInspector.ResourceLoader.loadAsStream(url, null, stream); | |
52 } | |
53 | |
54 /** | |
55 * @param {!File} file | |
56 * @param {!WebInspector.OutputStreamDelegate} delegate | |
57 * @return {!WebInspector.ChunkedReader} | |
58 */ | |
59 WebInspector.TimelineLoader._createFileReader = function(file, delegate) | |
60 { | |
61 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineModel.T
ransferChunkLengthBytes, delegate); | |
62 } | |
63 | |
64 | |
65 WebInspector.TimelineLoader._totalProgress = 100000; | |
66 | |
67 WebInspector.TimelineLoader.State = { | |
68 Initial: "Initial", | |
69 LookingForEvents: "LookingForEvents", | |
70 ReadingEvents: "ReadingEvents" | |
71 } | |
72 | |
73 WebInspector.TimelineLoader.prototype = { | |
74 /** | |
75 * @override | |
76 * @param {string} chunk | |
77 */ | |
78 write: function(chunk) | |
79 { | |
80 this._loadedBytes += chunk.length; | |
81 if (this._progress.isCanceled() && !this._wasCanceledOnce) { | |
82 this._wasCanceled = true; | |
83 this._reportErrorAndCancelLoading(); | |
84 return; | |
85 } | |
86 this._progress.setWorked(this._loadedBytes % WebInspector.TimelineLoader
._totalProgress, | |
87 WebInspector.UIString("Loaded %s", Number.bytes
ToString(this._loadedBytes))); | |
88 if (this._state === WebInspector.TimelineLoader.State.Initial) { | |
89 if (chunk[0] === "{") | |
90 this._state = WebInspector.TimelineLoader.State.LookingForEvents
; | |
91 else if (chunk[0] === "[") | |
92 this._state = WebInspector.TimelineLoader.State.ReadingEvents; | |
93 else { | |
94 this._reportErrorAndCancelLoading(WebInspector.UIString("Malform
ed timeline data: Unknown JSON format")); | |
95 return; | |
96 } | |
97 } | |
98 | |
99 if (this._state === WebInspector.TimelineLoader.State.LookingForEvents)
{ | |
100 var objectName = "\"traceEvents\":"; | |
101 var startPos = this._buffer.length - objectName.length; | |
102 this._buffer += chunk; | |
103 var pos = this._buffer.indexOf(objectName, startPos); | |
104 if (pos === -1) | |
105 return; | |
106 chunk = this._buffer.slice(pos + objectName.length) | |
107 this._state = WebInspector.TimelineLoader.State.ReadingEvents; | |
108 } | |
109 | |
110 this._jsonTokenizer.write(chunk); | |
111 }, | |
112 | |
113 /** | |
114 * @param {string} data | |
115 */ | |
116 _writeBalancedJSON: function(data) | |
117 { | |
118 var json = data + "]"; | |
119 | |
120 if (this._firstChunk) { | |
121 this._model.startCollectingTraceEvents(true); | |
122 } else { | |
123 var commaIndex = json.indexOf(","); | |
124 if (commaIndex !== -1) | |
125 json = json.slice(commaIndex + 1); | |
126 json = "[" + json; | |
127 } | |
128 | |
129 var items; | |
130 try { | |
131 items = /** @type {!Array.<!WebInspector.TracingManager.EventPayload
>} */ (JSON.parse(json)); | |
132 } catch (e) { | |
133 this._reportErrorAndCancelLoading(WebInspector.UIString("Malformed t
imeline data: %s", e.toString())); | |
134 return; | |
135 } | |
136 | |
137 if (this._firstChunk) { | |
138 this._firstChunk = false; | |
139 if (this._looksLikeAppVersion(items[0])) { | |
140 this._reportErrorAndCancelLoading(WebInspector.UIString("Legacy
Timeline format is not supported.")); | |
141 return; | |
142 } | |
143 } | |
144 | |
145 try { | |
146 this._model.traceEventsCollected(items); | |
147 } catch(e) { | |
148 this._reportErrorAndCancelLoading(WebInspector.UIString("Malformed t
imeline data: %s", e.toString())); | |
149 return; | |
150 } | |
151 }, | |
152 | |
153 /** | |
154 * @param {string=} message | |
155 */ | |
156 _reportErrorAndCancelLoading: function(message) | |
157 { | |
158 if (message) | |
159 WebInspector.console.error(message); | |
160 this._model.tracingComplete(); | |
161 this._model.reset(); | |
162 if (this._canceledCallback) | |
163 this._canceledCallback(); | |
164 this._progress.done(); | |
165 }, | |
166 | |
167 /** | |
168 * @param {*} item | |
169 * @return {boolean} | |
170 */ | |
171 _looksLikeAppVersion: function(item) | |
172 { | |
173 return typeof item === "string" && item.indexOf("Chrome") !== -1; | |
174 }, | |
175 | |
176 /** | |
177 * @override | |
178 */ | |
179 close: function() | |
180 { | |
181 this._model._loadedFromFile = true; | |
182 this._model.tracingComplete(); | |
183 if (this._progress) | |
184 this._progress.done(); | |
185 } | |
186 } | |
187 | |
188 /** | |
189 * @constructor | |
190 * @implements {WebInspector.OutputStreamDelegate} | |
191 * @param {!WebInspector.TimelineModel} model | |
192 * @param {!WebInspector.Progress} progress | |
193 */ | |
194 WebInspector.TimelineModelLoadFromFileDelegate = function(model, progress) | |
195 { | |
196 this._model = model; | |
197 this._progress = progress; | |
198 } | |
199 | |
200 WebInspector.TimelineModelLoadFromFileDelegate.prototype = { | |
201 /** | |
202 * @override | |
203 */ | |
204 onTransferStarted: function() | |
205 { | |
206 this._progress.setTitle(WebInspector.UIString("Loading\u2026")); | |
207 }, | |
208 | |
209 /** | |
210 * @override | |
211 * @param {!WebInspector.ChunkedReader} reader | |
212 */ | |
213 onChunkTransferred: function(reader) | |
214 { | |
215 if (this._progress.isCanceled()) { | |
216 reader.cancel(); | |
217 this._progress.done(); | |
218 this._model.reset(); | |
219 return; | |
220 } | |
221 | |
222 var totalSize = reader.fileSize(); | |
223 if (totalSize) { | |
224 this._progress.setTotalWork(totalSize); | |
225 this._progress.setWorked(reader.loadedSize()); | |
226 } | |
227 }, | |
228 | |
229 /** | |
230 * @override | |
231 */ | |
232 onTransferFinished: function() | |
233 { | |
234 this._progress.done(); | |
235 }, | |
236 | |
237 /** | |
238 * @override | |
239 * @param {!WebInspector.ChunkedReader} reader | |
240 * @param {!Event} event | |
241 */ | |
242 onError: function(reader, event) | |
243 { | |
244 this._progress.done(); | |
245 this._model.reset(); | |
246 switch (event.target.error.code) { | |
247 case FileError.NOT_FOUND_ERR: | |
248 WebInspector.console.error(WebInspector.UIString("File \"%s\" not fo
und.", reader.fileName())); | |
249 break; | |
250 case FileError.NOT_READABLE_ERR: | |
251 WebInspector.console.error(WebInspector.UIString("File \"%s\" is not
readable", reader.fileName())); | |
252 break; | |
253 case FileError.ABORT_ERR: | |
254 break; | |
255 default: | |
256 WebInspector.console.error(WebInspector.UIString("An error occurred
while reading the file \"%s\"", reader.fileName())); | |
257 } | |
258 } | |
259 } | |
260 | |
261 /** | |
262 * @constructor | |
263 * @param {!WebInspector.OutputStream} stream | |
264 * @implements {WebInspector.OutputStreamDelegate} | |
265 */ | |
266 WebInspector.TracingTimelineSaver = function(stream) | |
267 { | |
268 this._stream = stream; | |
269 } | |
270 | |
271 WebInspector.TracingTimelineSaver.prototype = { | |
272 /** | |
273 * @override | |
274 */ | |
275 onTransferStarted: function() | |
276 { | |
277 this._stream.write("["); | |
278 }, | |
279 | |
280 /** | |
281 * @override | |
282 */ | |
283 onTransferFinished: function() | |
284 { | |
285 this._stream.write("]"); | |
286 }, | |
287 | |
288 /** | |
289 * @override | |
290 * @param {!WebInspector.ChunkedReader} reader | |
291 */ | |
292 onChunkTransferred: function(reader) { }, | |
293 | |
294 /** | |
295 * @override | |
296 * @param {!WebInspector.ChunkedReader} reader | |
297 * @param {!Event} event | |
298 */ | |
299 onError: function(reader, event) { } | |
300 } | |
OLD | NEW |