blob: 24952f35194712e45dd52e2c0297eace0dd06bd6 [file] [log] [blame]
/*
* Copyright 2015 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/**
* @unrestricted
*/
export default class FilmStripModel {
/**
* @param {!SDK.TracingModel} tracingModel
* @param {number=} zeroTime
*/
constructor(tracingModel, zeroTime) {
this.reset(tracingModel, zeroTime);
}
/**
* @param {!SDK.TracingModel} tracingModel
* @param {number=} zeroTime
*/
reset(tracingModel, zeroTime) {
this._zeroTime = zeroTime || tracingModel.minimumRecordTime();
this._spanTime = tracingModel.maximumRecordTime() - this._zeroTime;
/** @type {!Array<!Frame>} */
this._frames = [];
const browserMain = SDK.TracingModel.browserMainThread(tracingModel);
if (!browserMain) {
return;
}
const events = browserMain.events();
for (let i = 0; i < events.length; ++i) {
const event = events[i];
if (event.startTime < this._zeroTime) {
continue;
}
if (!event.hasCategory(_category)) {
continue;
}
if (event.name === TraceEvents.CaptureFrame) {
const data = event.args['data'];
if (data) {
this._frames.push(Frame._fromEvent(this, event, this._frames.length));
}
} else if (event.name === TraceEvents.Screenshot) {
this._frames.push(
Frame._fromSnapshot(this, /** @type {!SDK.TracingModel.ObjectSnapshot} */ (event), this._frames.length));
}
}
}
/**
* @return {!Array<!Frame>}
*/
frames() {
return this._frames;
}
/**
* @return {number}
*/
zeroTime() {
return this._zeroTime;
}
/**
* @return {number}
*/
spanTime() {
return this._spanTime;
}
/**
* @param {number} timestamp
* @return {?Frame}
*/
frameByTimestamp(timestamp) {
const index = this._frames.upperBound(timestamp, (timestamp, frame) => timestamp - frame.timestamp) - 1;
return index >= 0 ? this._frames[index] : null;
}
}
const _category = 'disabled-by-default-devtools.screenshot';
const TraceEvents = {
CaptureFrame: 'CaptureFrame',
Screenshot: 'Screenshot'
};
/**
* @unrestricted
*/
export class Frame {
/**
* @param {!FilmStripModel} model
* @param {number} timestamp
* @param {number} index
*/
constructor(model, timestamp, index) {
this._model = model;
this.timestamp = timestamp;
this.index = index;
/** @type {?string} */
this._imageData = null;
/** @type {?SDK.TracingModel.ObjectSnapshot} */
this._snapshot = null;
}
/**
* @param {!FilmStripModel} model
* @param {!SDK.TracingModel.Event} event
* @param {number} index
* @return {!Frame}
*/
static _fromEvent(model, event, index) {
const frame = new Frame(model, event.startTime, index);
frame._imageData = event.args['data'];
return frame;
}
/**
* @param {!FilmStripModel} model
* @param {!SDK.TracingModel.ObjectSnapshot} snapshot
* @param {number} index
* @return {!Frame}
*/
static _fromSnapshot(model, snapshot, index) {
const frame = new Frame(model, snapshot.startTime, index);
frame._snapshot = snapshot;
return frame;
}
/**
* @return {!FilmStripModel}
*/
model() {
return this._model;
}
/**
* @return {!Promise<?string>}
*/
imageDataPromise() {
if (this._imageData || !this._snapshot) {
return Promise.resolve(this._imageData);
}
return /** @type {!Promise<?string>} */ (this._snapshot.objectPromise());
}
}
/* Legacy exported object */
self.SDK = self.SDK || {};
/* Legacy exported object */
SDK = SDK || {};
/** @constructor */
SDK.FilmStripModel = FilmStripModel;
/** @constructor */
SDK.FilmStripModel.Frame = Frame;