In a following patch, all DevTools moz.build files will use DevToolsModules to install JS modules at a path that corresponds directly to their source tree location. Here we rewrite all require and import calls to match the new location that these files are installed to.
167 lines
5.2 KiB
JavaScript
167 lines
5.2 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
const { Cc, Ci, Cu, Cr } = require("chrome");
|
|
|
|
loader.lazyRequireGetter(this, "Services");
|
|
loader.lazyRequireGetter(this, "promise");
|
|
loader.lazyRequireGetter(this, "RecordingUtils",
|
|
"devtools/shared/performance/utils");
|
|
|
|
loader.lazyImporter(this, "FileUtils",
|
|
"resource://gre/modules/FileUtils.jsm");
|
|
loader.lazyImporter(this, "NetUtil",
|
|
"resource://gre/modules/NetUtil.jsm");
|
|
|
|
// This identifier string is used to tentatively ascertain whether or not
|
|
// a JSON loaded from disk is actually something generated by this tool.
|
|
// It isn't, of course, a definitive verification, but a Good Enough™
|
|
// approximation before continuing the import. Don't localize this.
|
|
const PERF_TOOL_SERIALIZER_IDENTIFIER = "Recorded Performance Data";
|
|
const PERF_TOOL_SERIALIZER_LEGACY_VERSION = 1;
|
|
const PERF_TOOL_SERIALIZER_CURRENT_VERSION = 2;
|
|
|
|
/**
|
|
* Helpers for importing/exporting JSON.
|
|
*/
|
|
|
|
/**
|
|
* Gets a nsIScriptableUnicodeConverter instance with a default UTF-8 charset.
|
|
* @return object
|
|
*/
|
|
function getUnicodeConverter () {
|
|
let className = "@mozilla.org/intl/scriptableunicodeconverter";
|
|
let converter = Cc[className].createInstance(Ci.nsIScriptableUnicodeConverter);
|
|
converter.charset = "UTF-8";
|
|
return converter;
|
|
}
|
|
|
|
/**
|
|
* Saves a recording as JSON to a file. The provided data is assumed to be
|
|
* acyclical, so that it can be properly serialized.
|
|
*
|
|
* @param object recordingData
|
|
* The recording data to stream as JSON.
|
|
* @param nsILocalFile file
|
|
* The file to stream the data into.
|
|
* @return object
|
|
* A promise that is resolved once streaming finishes, or rejected
|
|
* if there was an error.
|
|
*/
|
|
function saveRecordingToFile (recordingData, file) {
|
|
let deferred = promise.defer();
|
|
|
|
recordingData.fileType = PERF_TOOL_SERIALIZER_IDENTIFIER;
|
|
recordingData.version = PERF_TOOL_SERIALIZER_CURRENT_VERSION;
|
|
|
|
let string = JSON.stringify(recordingData);
|
|
let inputStream = this.getUnicodeConverter().convertToInputStream(string);
|
|
let outputStream = FileUtils.openSafeFileOutputStream(file);
|
|
|
|
NetUtil.asyncCopy(inputStream, outputStream, deferred.resolve);
|
|
return deferred.promise;
|
|
}
|
|
|
|
/**
|
|
* Loads a recording stored as JSON from a file.
|
|
*
|
|
* @param nsILocalFile file
|
|
* The file to import the data from.
|
|
* @return object
|
|
* A promise that is resolved once importing finishes, or rejected
|
|
* if there was an error.
|
|
*/
|
|
function loadRecordingFromFile (file) {
|
|
let deferred = promise.defer();
|
|
|
|
let channel = NetUtil.newChannel({
|
|
uri: NetUtil.newURI(file),
|
|
loadUsingSystemPrincipal: true});
|
|
|
|
channel.contentType = "text/plain";
|
|
|
|
NetUtil.asyncFetch(channel, (inputStream, status) => {
|
|
try {
|
|
let string = NetUtil.readInputStreamToString(inputStream, inputStream.available());
|
|
var recordingData = JSON.parse(string);
|
|
} catch (e) {
|
|
deferred.reject(new Error("Could not read recording data file."));
|
|
return;
|
|
}
|
|
if (recordingData.fileType != PERF_TOOL_SERIALIZER_IDENTIFIER) {
|
|
deferred.reject(new Error("Unrecognized recording data file."));
|
|
return;
|
|
}
|
|
if (!isValidSerializerVersion(recordingData.version)) {
|
|
deferred.reject(new Error("Unsupported recording data file version."));
|
|
return;
|
|
}
|
|
if (recordingData.version === PERF_TOOL_SERIALIZER_LEGACY_VERSION) {
|
|
recordingData = convertLegacyData(recordingData);
|
|
}
|
|
if (recordingData.profile.meta.version === 2) {
|
|
RecordingUtils.deflateProfile(recordingData.profile);
|
|
}
|
|
deferred.resolve(recordingData);
|
|
});
|
|
|
|
return deferred.promise;
|
|
}
|
|
|
|
/**
|
|
* Returns a boolean indicating whether or not the passed in `version`
|
|
* is supported by this serializer.
|
|
*
|
|
* @param number version
|
|
* @return boolean
|
|
*/
|
|
function isValidSerializerVersion (version) {
|
|
return !!~[
|
|
PERF_TOOL_SERIALIZER_LEGACY_VERSION,
|
|
PERF_TOOL_SERIALIZER_CURRENT_VERSION
|
|
].indexOf(version);
|
|
}
|
|
|
|
/**
|
|
* Takes recording data (with version `1`, from the original profiler tool), and
|
|
* massages the data to be line with the current performance tool's property names
|
|
* and values.
|
|
*
|
|
* @param object legacyData
|
|
* @return object
|
|
*/
|
|
function convertLegacyData (legacyData) {
|
|
let { profilerData, ticksData, recordingDuration } = legacyData;
|
|
|
|
// The `profilerData` and `ticksData` stay, but the previously unrecorded
|
|
// fields just are empty arrays or objects.
|
|
let data = {
|
|
label: profilerData.profilerLabel,
|
|
duration: recordingDuration,
|
|
markers: [],
|
|
frames: [],
|
|
memory: [],
|
|
ticks: ticksData,
|
|
allocations: { sites: [], timestamps: [], frames: [], sizes: [] },
|
|
profile: profilerData.profile,
|
|
// Fake a configuration object here if there's tick data,
|
|
// so that it can be rendered
|
|
configuration: {
|
|
withTicks: !!ticksData.length,
|
|
withMarkers: false,
|
|
withMemory: false,
|
|
withAllocations: false
|
|
},
|
|
systemHost: {},
|
|
systemClient: {},
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
exports.getUnicodeConverter = getUnicodeConverter;
|
|
exports.saveRecordingToFile = saveRecordingToFile;
|
|
exports.loadRecordingFromFile = loadRecordingFromFile;
|