| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 * @implements {WebInspector.OutputStream} | 5 * @implements {Common.OutputStream} |
| 6 * @implements {WebInspector.OutputStreamDelegate} | 6 * @implements {Bindings.OutputStreamDelegate} |
| 7 * @unrestricted | 7 * @unrestricted |
| 8 */ | 8 */ |
| 9 WebInspector.TimelineLoader = class { | 9 Timeline.TimelineLoader = class { |
| 10 /** | 10 /** |
| 11 * @param {!WebInspector.TracingModel} model | 11 * @param {!SDK.TracingModel} model |
| 12 * @param {!WebInspector.TimelineLifecycleDelegate} delegate | 12 * @param {!Timeline.TimelineLifecycleDelegate} delegate |
| 13 */ | 13 */ |
| 14 constructor(model, delegate) { | 14 constructor(model, delegate) { |
| 15 this._model = model; | 15 this._model = model; |
| 16 this._delegate = delegate; | 16 this._delegate = delegate; |
| 17 | 17 |
| 18 /** @type {?function()} */ | 18 /** @type {?function()} */ |
| 19 this._canceledCallback = null; | 19 this._canceledCallback = null; |
| 20 | 20 |
| 21 this._state = WebInspector.TimelineLoader.State.Initial; | 21 this._state = Timeline.TimelineLoader.State.Initial; |
| 22 this._buffer = ''; | 22 this._buffer = ''; |
| 23 this._firstChunk = true; | 23 this._firstChunk = true; |
| 24 | 24 |
| 25 this._loadedBytes = 0; | 25 this._loadedBytes = 0; |
| 26 /** @type {number} */ | 26 /** @type {number} */ |
| 27 this._totalSize; | 27 this._totalSize; |
| 28 this._jsonTokenizer = new WebInspector.TextUtils.BalancedJSONTokenizer(this.
_writeBalancedJSON.bind(this), true); | 28 this._jsonTokenizer = new Common.TextUtils.BalancedJSONTokenizer(this._write
BalancedJSON.bind(this), true); |
| 29 } | 29 } |
| 30 | 30 |
| 31 /** | 31 /** |
| 32 * @param {!WebInspector.TracingModel} model | 32 * @param {!SDK.TracingModel} model |
| 33 * @param {!File} file | 33 * @param {!File} file |
| 34 * @param {!WebInspector.TimelineLifecycleDelegate} delegate | 34 * @param {!Timeline.TimelineLifecycleDelegate} delegate |
| 35 * @return {!WebInspector.TimelineLoader} | 35 * @return {!Timeline.TimelineLoader} |
| 36 */ | 36 */ |
| 37 static loadFromFile(model, file, delegate) { | 37 static loadFromFile(model, file, delegate) { |
| 38 var loader = new WebInspector.TimelineLoader(model, delegate); | 38 var loader = new Timeline.TimelineLoader(model, delegate); |
| 39 var fileReader = WebInspector.TimelineLoader._createFileReader(file, loader)
; | 39 var fileReader = Timeline.TimelineLoader._createFileReader(file, loader); |
| 40 loader._canceledCallback = fileReader.cancel.bind(fileReader); | 40 loader._canceledCallback = fileReader.cancel.bind(fileReader); |
| 41 loader._totalSize = file.size; | 41 loader._totalSize = file.size; |
| 42 fileReader.start(loader); | 42 fileReader.start(loader); |
| 43 return loader; | 43 return loader; |
| 44 } | 44 } |
| 45 | 45 |
| 46 /** | 46 /** |
| 47 * @param {!WebInspector.TracingModel} model | 47 * @param {!SDK.TracingModel} model |
| 48 * @param {string} url | 48 * @param {string} url |
| 49 * @param {!WebInspector.TimelineLifecycleDelegate} delegate | 49 * @param {!Timeline.TimelineLifecycleDelegate} delegate |
| 50 * @return {!WebInspector.TimelineLoader} | 50 * @return {!Timeline.TimelineLoader} |
| 51 */ | 51 */ |
| 52 static loadFromURL(model, url, delegate) { | 52 static loadFromURL(model, url, delegate) { |
| 53 var stream = new WebInspector.TimelineLoader(model, delegate); | 53 var stream = new Timeline.TimelineLoader(model, delegate); |
| 54 WebInspector.ResourceLoader.loadAsStream(url, null, stream); | 54 Host.ResourceLoader.loadAsStream(url, null, stream); |
| 55 return stream; | 55 return stream; |
| 56 } | 56 } |
| 57 | 57 |
| 58 /** | 58 /** |
| 59 * @param {!File} file | 59 * @param {!File} file |
| 60 * @param {!WebInspector.OutputStreamDelegate} delegate | 60 * @param {!Bindings.OutputStreamDelegate} delegate |
| 61 * @return {!WebInspector.ChunkedReader} | 61 * @return {!Bindings.ChunkedReader} |
| 62 */ | 62 */ |
| 63 static _createFileReader(file, delegate) { | 63 static _createFileReader(file, delegate) { |
| 64 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineLoader.
TransferChunkLengthBytes, delegate); | 64 return new Bindings.ChunkedFileReader(file, Timeline.TimelineLoader.Transfer
ChunkLengthBytes, delegate); |
| 65 } | 65 } |
| 66 | 66 |
| 67 cancel() { | 67 cancel() { |
| 68 this._model.reset(); | 68 this._model.reset(); |
| 69 this._delegate.loadingComplete(false); | 69 this._delegate.loadingComplete(false); |
| 70 this._delegate = null; | 70 this._delegate = null; |
| 71 if (this._canceledCallback) | 71 if (this._canceledCallback) |
| 72 this._canceledCallback(); | 72 this._canceledCallback(); |
| 73 } | 73 } |
| 74 | 74 |
| 75 /** | 75 /** |
| 76 * @override | 76 * @override |
| 77 * @param {string} chunk | 77 * @param {string} chunk |
| 78 */ | 78 */ |
| 79 write(chunk) { | 79 write(chunk) { |
| 80 if (!this._delegate) | 80 if (!this._delegate) |
| 81 return; | 81 return; |
| 82 this._loadedBytes += chunk.length; | 82 this._loadedBytes += chunk.length; |
| 83 if (!this._firstChunk) | 83 if (!this._firstChunk) |
| 84 this._delegate.loadingProgress(this._totalSize ? this._loadedBytes / this.
_totalSize : undefined); | 84 this._delegate.loadingProgress(this._totalSize ? this._loadedBytes / this.
_totalSize : undefined); |
| 85 | 85 |
| 86 if (this._state === WebInspector.TimelineLoader.State.Initial) { | 86 if (this._state === Timeline.TimelineLoader.State.Initial) { |
| 87 if (chunk[0] === '{') | 87 if (chunk[0] === '{') |
| 88 this._state = WebInspector.TimelineLoader.State.LookingForEvents; | 88 this._state = Timeline.TimelineLoader.State.LookingForEvents; |
| 89 else if (chunk[0] === '[') | 89 else if (chunk[0] === '[') |
| 90 this._state = WebInspector.TimelineLoader.State.ReadingEvents; | 90 this._state = Timeline.TimelineLoader.State.ReadingEvents; |
| 91 else { | 91 else { |
| 92 this._reportErrorAndCancelLoading(WebInspector.UIString('Malformed timel
ine data: Unknown JSON format')); | 92 this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline da
ta: Unknown JSON format')); |
| 93 return; | 93 return; |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 if (this._state === WebInspector.TimelineLoader.State.LookingForEvents) { | 97 if (this._state === Timeline.TimelineLoader.State.LookingForEvents) { |
| 98 var objectName = '"traceEvents":'; | 98 var objectName = '"traceEvents":'; |
| 99 var startPos = this._buffer.length - objectName.length; | 99 var startPos = this._buffer.length - objectName.length; |
| 100 this._buffer += chunk; | 100 this._buffer += chunk; |
| 101 var pos = this._buffer.indexOf(objectName, startPos); | 101 var pos = this._buffer.indexOf(objectName, startPos); |
| 102 if (pos === -1) | 102 if (pos === -1) |
| 103 return; | 103 return; |
| 104 chunk = this._buffer.slice(pos + objectName.length); | 104 chunk = this._buffer.slice(pos + objectName.length); |
| 105 this._state = WebInspector.TimelineLoader.State.ReadingEvents; | 105 this._state = Timeline.TimelineLoader.State.ReadingEvents; |
| 106 } | 106 } |
| 107 | 107 |
| 108 if (this._state !== WebInspector.TimelineLoader.State.ReadingEvents) | 108 if (this._state !== Timeline.TimelineLoader.State.ReadingEvents) |
| 109 return; | 109 return; |
| 110 if (this._jsonTokenizer.write(chunk)) | 110 if (this._jsonTokenizer.write(chunk)) |
| 111 return; | 111 return; |
| 112 this._state = WebInspector.TimelineLoader.State.SkippingTail; | 112 this._state = Timeline.TimelineLoader.State.SkippingTail; |
| 113 if (this._firstChunk) { | 113 if (this._firstChunk) { |
| 114 this._reportErrorAndCancelLoading(WebInspector.UIString('Malformed timelin
e input, wrong JSON brackets balance')); | 114 this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline inpu
t, wrong JSON brackets balance')); |
| 115 return; | 115 return; |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 /** | 119 /** |
| 120 * @param {string} data | 120 * @param {string} data |
| 121 */ | 121 */ |
| 122 _writeBalancedJSON(data) { | 122 _writeBalancedJSON(data) { |
| 123 var json = data + ']'; | 123 var json = data + ']'; |
| 124 | 124 |
| 125 if (this._firstChunk) { | 125 if (this._firstChunk) { |
| 126 this._delegate.loadingStarted(); | 126 this._delegate.loadingStarted(); |
| 127 } else { | 127 } else { |
| 128 var commaIndex = json.indexOf(','); | 128 var commaIndex = json.indexOf(','); |
| 129 if (commaIndex !== -1) | 129 if (commaIndex !== -1) |
| 130 json = json.slice(commaIndex + 1); | 130 json = json.slice(commaIndex + 1); |
| 131 json = '[' + json; | 131 json = '[' + json; |
| 132 } | 132 } |
| 133 | 133 |
| 134 var items; | 134 var items; |
| 135 try { | 135 try { |
| 136 items = /** @type {!Array.<!WebInspector.TracingManager.EventPayload>} */
(JSON.parse(json)); | 136 items = /** @type {!Array.<!SDK.TracingManager.EventPayload>} */ (JSON.par
se(json)); |
| 137 } catch (e) { | 137 } catch (e) { |
| 138 this._reportErrorAndCancelLoading(WebInspector.UIString('Malformed timelin
e data: %s', e.toString())); | 138 this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline data
: %s', e.toString())); |
| 139 return; | 139 return; |
| 140 } | 140 } |
| 141 | 141 |
| 142 if (this._firstChunk) { | 142 if (this._firstChunk) { |
| 143 this._firstChunk = false; | 143 this._firstChunk = false; |
| 144 this._model.reset(); | 144 this._model.reset(); |
| 145 if (this._looksLikeAppVersion(items[0])) { | 145 if (this._looksLikeAppVersion(items[0])) { |
| 146 this._reportErrorAndCancelLoading(WebInspector.UIString('Legacy Timeline
format is not supported.')); | 146 this._reportErrorAndCancelLoading(Common.UIString('Legacy Timeline forma
t is not supported.')); |
| 147 return; | 147 return; |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 | 150 |
| 151 try { | 151 try { |
| 152 this._model.addEvents(items); | 152 this._model.addEvents(items); |
| 153 } catch (e) { | 153 } catch (e) { |
| 154 this._reportErrorAndCancelLoading(WebInspector.UIString('Malformed timelin
e data: %s', e.toString())); | 154 this._reportErrorAndCancelLoading(Common.UIString('Malformed timeline data
: %s', e.toString())); |
| 155 return; | 155 return; |
| 156 } | 156 } |
| 157 } | 157 } |
| 158 | 158 |
| 159 /** | 159 /** |
| 160 * @param {string=} message | 160 * @param {string=} message |
| 161 */ | 161 */ |
| 162 _reportErrorAndCancelLoading(message) { | 162 _reportErrorAndCancelLoading(message) { |
| 163 if (message) | 163 if (message) |
| 164 WebInspector.console.error(message); | 164 Common.console.error(message); |
| 165 this.cancel(); | 165 this.cancel(); |
| 166 } | 166 } |
| 167 | 167 |
| 168 /** | 168 /** |
| 169 * @param {*} item | 169 * @param {*} item |
| 170 * @return {boolean} | 170 * @return {boolean} |
| 171 */ | 171 */ |
| 172 _looksLikeAppVersion(item) { | 172 _looksLikeAppVersion(item) { |
| 173 return typeof item === 'string' && item.indexOf('Chrome') !== -1; | 173 return typeof item === 'string' && item.indexOf('Chrome') !== -1; |
| 174 } | 174 } |
| 175 | 175 |
| 176 /** | 176 /** |
| 177 * @override | 177 * @override |
| 178 */ | 178 */ |
| 179 close() { | 179 close() { |
| 180 this._model.tracingComplete(); | 180 this._model.tracingComplete(); |
| 181 if (this._delegate) | 181 if (this._delegate) |
| 182 this._delegate.loadingComplete(true); | 182 this._delegate.loadingComplete(true); |
| 183 } | 183 } |
| 184 | 184 |
| 185 /** | 185 /** |
| 186 * @override | 186 * @override |
| 187 */ | 187 */ |
| 188 onTransferStarted() { | 188 onTransferStarted() { |
| 189 } | 189 } |
| 190 | 190 |
| 191 /** | 191 /** |
| 192 * @override | 192 * @override |
| 193 * @param {!WebInspector.ChunkedReader} reader | 193 * @param {!Bindings.ChunkedReader} reader |
| 194 */ | 194 */ |
| 195 onChunkTransferred(reader) { | 195 onChunkTransferred(reader) { |
| 196 } | 196 } |
| 197 | 197 |
| 198 /** | 198 /** |
| 199 * @override | 199 * @override |
| 200 */ | 200 */ |
| 201 onTransferFinished() { | 201 onTransferFinished() { |
| 202 } | 202 } |
| 203 | 203 |
| 204 /** | 204 /** |
| 205 * @override | 205 * @override |
| 206 * @param {!WebInspector.ChunkedReader} reader | 206 * @param {!Bindings.ChunkedReader} reader |
| 207 * @param {!Event} event | 207 * @param {!Event} event |
| 208 */ | 208 */ |
| 209 onError(reader, event) { | 209 onError(reader, event) { |
| 210 switch (event.target.error.name) { | 210 switch (event.target.error.name) { |
| 211 case 'NotFoundError': | 211 case 'NotFoundError': |
| 212 this._reportErrorAndCancelLoading(WebInspector.UIString('File "%s" not f
ound.', reader.fileName())); | 212 this._reportErrorAndCancelLoading(Common.UIString('File "%s" not found.'
, reader.fileName())); |
| 213 break; | 213 break; |
| 214 case 'NotReadableError': | 214 case 'NotReadableError': |
| 215 this._reportErrorAndCancelLoading(WebInspector.UIString('File "%s" is no
t readable', reader.fileName())); | 215 this._reportErrorAndCancelLoading(Common.UIString('File "%s" is not read
able', reader.fileName())); |
| 216 break; | 216 break; |
| 217 case 'AbortError': | 217 case 'AbortError': |
| 218 break; | 218 break; |
| 219 default: | 219 default: |
| 220 this._reportErrorAndCancelLoading( | 220 this._reportErrorAndCancelLoading( |
| 221 WebInspector.UIString('An error occurred while reading the file "%s"
', reader.fileName())); | 221 Common.UIString('An error occurred while reading the file "%s"', rea
der.fileName())); |
| 222 } | 222 } |
| 223 } | 223 } |
| 224 }; | 224 }; |
| 225 | 225 |
| 226 | 226 |
| 227 WebInspector.TimelineLoader.TransferChunkLengthBytes = 5000000; | 227 Timeline.TimelineLoader.TransferChunkLengthBytes = 5000000; |
| 228 | 228 |
| 229 | 229 |
| 230 /** | 230 /** |
| 231 * @enum {symbol} | 231 * @enum {symbol} |
| 232 */ | 232 */ |
| 233 WebInspector.TimelineLoader.State = { | 233 Timeline.TimelineLoader.State = { |
| 234 Initial: Symbol('Initial'), | 234 Initial: Symbol('Initial'), |
| 235 LookingForEvents: Symbol('LookingForEvents'), | 235 LookingForEvents: Symbol('LookingForEvents'), |
| 236 ReadingEvents: Symbol('ReadingEvents'), | 236 ReadingEvents: Symbol('ReadingEvents'), |
| 237 SkippingTail: Symbol('SkippingTail') | 237 SkippingTail: Symbol('SkippingTail') |
| 238 }; | 238 }; |
| 239 | 239 |
| 240 /** | 240 /** |
| 241 * @implements {WebInspector.OutputStreamDelegate} | 241 * @implements {Bindings.OutputStreamDelegate} |
| 242 * @unrestricted | 242 * @unrestricted |
| 243 */ | 243 */ |
| 244 WebInspector.TracingTimelineSaver = class { | 244 Timeline.TracingTimelineSaver = class { |
| 245 /** | 245 /** |
| 246 * @override | 246 * @override |
| 247 */ | 247 */ |
| 248 onTransferStarted() { | 248 onTransferStarted() { |
| 249 } | 249 } |
| 250 | 250 |
| 251 /** | 251 /** |
| 252 * @override | 252 * @override |
| 253 */ | 253 */ |
| 254 onTransferFinished() { | 254 onTransferFinished() { |
| 255 } | 255 } |
| 256 | 256 |
| 257 /** | 257 /** |
| 258 * @override | 258 * @override |
| 259 * @param {!WebInspector.ChunkedReader} reader | 259 * @param {!Bindings.ChunkedReader} reader |
| 260 */ | 260 */ |
| 261 onChunkTransferred(reader) { | 261 onChunkTransferred(reader) { |
| 262 } | 262 } |
| 263 | 263 |
| 264 /** | 264 /** |
| 265 * @override | 265 * @override |
| 266 * @param {!WebInspector.ChunkedReader} reader | 266 * @param {!Bindings.ChunkedReader} reader |
| 267 * @param {!Event} event | 267 * @param {!Event} event |
| 268 */ | 268 */ |
| 269 onError(reader, event) { | 269 onError(reader, event) { |
| 270 var error = event.target.error; | 270 var error = event.target.error; |
| 271 WebInspector.console.error( | 271 Common.console.error( |
| 272 WebInspector.UIString('Failed to save timeline: %s (%s, %s)', error.mess
age, error.name, error.code)); | 272 Common.UIString('Failed to save timeline: %s (%s, %s)', error.message, e
rror.name, error.code)); |
| 273 } | 273 } |
| 274 }; | 274 }; |
| OLD | NEW |