/* 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"); const { ViewHelpers } = require("resource:///modules/devtools/ViewHelpers.jsm"); // String used to fill in platform data when it should be hidden. const GECKO_SYMBOL = "(Gecko)"; /** * Localization convenience methods. + TODO: merge these into a single file: Bug 1082695. */ const L10N = new ViewHelpers.MultiL10N([ "chrome://browser/locale/devtools/timeline.properties", "chrome://browser/locale/devtools/profiler.properties" ]); /** * A list of preferences for this tool. The values automatically update * if somebody edits edits about:config or the prefs change somewhere else. */ const Prefs = new ViewHelpers.Prefs("devtools.performance.ui", { showPlatformData: ["Bool", "show-platform-data"] }, { monitorChanges: true }); /** * Details about each profile entry cateogry. * @see CATEGORY_MAPPINGS. */ const CATEGORIES = [{ color: "#5e88b0", abbrev: "other", label: L10N.getStr("category.other") }, { color: "#46afe3", abbrev: "css", label: L10N.getStr("category.css") }, { color: "#d96629", abbrev: "js", label: L10N.getStr("category.js") }, { color: "#eb5368", abbrev: "gc", label: L10N.getStr("category.gc") }, { color: "#df80ff", abbrev: "network", label: L10N.getStr("category.network") }, { color: "#70bf53", abbrev: "graphics", label: L10N.getStr("category.graphics") }, { color: "#8fa1b2", abbrev: "storage", label: L10N.getStr("category.storage") }, { color: "#d99b28", abbrev: "events", label: L10N.getStr("category.events") }]; /** * Mapping from category bitmasks in the profiler data to additional details. * To be kept in sync with the js::ProfileEntry::Category in ProfilingStack.h */ const CATEGORY_MAPPINGS = { "16": CATEGORIES[0], // js::ProfileEntry::Category::OTHER "32": CATEGORIES[1], // js::ProfileEntry::Category::CSS "64": CATEGORIES[2], // js::ProfileEntry::Category::JS "128": CATEGORIES[3], // js::ProfileEntry::Category::GC "256": CATEGORIES[3], // js::ProfileEntry::Category::CC "512": CATEGORIES[4], // js::ProfileEntry::Category::NETWORK "1024": CATEGORIES[5], // js::ProfileEntry::Category::GRAPHICS "2048": CATEGORIES[6], // js::ProfileEntry::Category::STORAGE "4096": CATEGORIES[7], // js::ProfileEntry::Category::EVENTS }; /** * A simple schema for mapping markers to the timeline UI. The keys correspond * to marker names, while the values are objects with the following format: * * - group: The row index in the timeline overview graph; multiple markers * can be added on the same row. @see * - label: The label used in the waterfall to identify the marker. Can be a * string or just a function that accepts the marker and returns a * string, if you want to use a dynamic property for the main label. * If you use a function for a label, it *must* handle the case where * no marker is provided for a main label to describe all markers of * this type. * - colorName: The label of the DevTools color used for this marker. If * adding a new color, be sure to check that there's an entry * for `.marker-details-bullet.{COLORNAME}` for the equivilent * entry in ./browser/themes/shared/devtools/performance.inc.css * https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors * - fields: An optional array of marker properties you wish to display in the * marker details view. For example, a field in the array such as * { property: "aCauseName", label: "Cause" } would render a string * like `Cause: ${marker.aCauseName}` in the marker details view. * Each `field` item may take the following properties: * - property: The property that must exist on the marker to render, * and the value of the property will be displayed. * - label: The name of the property that should be displayed. * - formatter: If a formatter is provided, instead of directly using * the `property` property on the marker, the marker is * passed into the formatter function to determine the * displayed value. * Can also be a function that returns an object. Each key in the object * will be rendered as a field, with its value rendering as the value. * * Whenever this is changed, browser_timeline_waterfall-styles.js *must* be * updated as well. */ const TIMELINE_BLUEPRINT = { /* Group 0 - Reflow and Rendering pipeline */ "Styles": { group: 0, colorName: "graphs-purple", label: L10N.getStr("timeline.label.styles2"), fields: getStylesFields, }, "Reflow": { group: 0, colorName: "graphs-purple", label: L10N.getStr("timeline.label.reflow2") }, "Paint": { group: 0, colorName: "graphs-green", label: L10N.getStr("timeline.label.paint") }, /* Group 1 - JS */ "DOMEvent": { group: 1, colorName: "graphs-yellow", label: L10N.getStr("timeline.label.domevent"), fields: getDOMEventFields, }, "Javascript": { group: 1, colorName: "graphs-yellow", label: getJSLabel, fields: getJSFields, }, "Parse HTML": { group: 1, colorName: "graphs-yellow", label: L10N.getStr("timeline.label.parseHTML") }, "Parse XML": { group: 1, colorName: "graphs-yellow", label: L10N.getStr("timeline.label.parseXML") }, "GarbageCollection": { group: 1, colorName: "graphs-red", label: getGCLabel, fields: [ { property: "causeName", label: "Reason:" }, { property: "nonincrementalReason", label: "Non-incremental Reason:" } ] }, /* Group 2 - User Controlled */ "ConsoleTime": { group: 2, colorName: "graphs-grey", label: sublabelForProperty(L10N.getStr("timeline.label.consoleTime"), "causeName"), fields: [{ property: "causeName", label: L10N.getStr("timeline.markerDetail.consoleTimerName") }] }, "TimeStamp": { group: 2, colorName: "graphs-blue", label: sublabelForProperty(L10N.getStr("timeline.label.timestamp"), "causeName"), fields: [{ property: "causeName", label: "Label:" }] }, }; /** * A series of formatters used by the blueprint. */ function getGCLabel (marker={}) { let label = L10N.getStr("timeline.label.garbageCollection"); // Only if a `nonincrementalReason` exists, do we want to label // this as a non incremental GC event. if ("nonincrementalReason" in marker) { label = `${label} (Non-incremental)`; } return label; } /** * Mapping of JS marker causes to a friendlier form. Only * markers that are considered "from content" should be labeled here. */ const JS_MARKER_MAP = { "