forked from mirrors/gecko-dev
Bug 1482091: Part 2 - Remove TelemetryStopwatch.jsm in favor of native implementation. r=chutten
Differential Revision: https://phabricator.services.mozilla.com/D9888 --HG-- extra : rebase_source : a9daea3a9efea37acdbcaecda8bf0b7f69631de4 extra : histedit_source : bb8b416b1387da9de3bd95c7a171f10426a22602
This commit is contained in:
parent
4bd1fb01dd
commit
96f3e16d1a
28 changed files with 11 additions and 482 deletions
|
|
@ -64,7 +64,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
SitePermissions: "resource:///modules/SitePermissions.jsm",
|
SitePermissions: "resource:///modules/SitePermissions.jsm",
|
||||||
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
|
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
|
||||||
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
|
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
Translation: "resource:///modules/translation/Translation.jsm",
|
Translation: "resource:///modules/translation/Translation.jsm",
|
||||||
UITour: "resource:///modules/UITour.jsm",
|
UITour: "resource:///modules/UITour.jsm",
|
||||||
UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
|
UpdateUtils: "resource://gre/modules/UpdateUtils.jsm",
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ const intermittently_loaded_whitelist = {
|
||||||
]),
|
]),
|
||||||
modules: new Set([
|
modules: new Set([
|
||||||
"resource://gre/modules/sessionstore/Utils.jsm",
|
"resource://gre/modules/sessionstore/Utils.jsm",
|
||||||
"resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ ChromeUtils.defineModuleGetter(this, "ResponsivenessMonitor",
|
||||||
"resource://gre/modules/ResponsivenessMonitor.jsm");
|
"resource://gre/modules/ResponsivenessMonitor.jsm");
|
||||||
ChromeUtils.defineModuleGetter(this, "Sqlite",
|
ChromeUtils.defineModuleGetter(this, "Sqlite",
|
||||||
"resource://gre/modules/Sqlite.jsm");
|
"resource://gre/modules/Sqlite.jsm");
|
||||||
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
|
|
||||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
ChromeUtils.defineModuleGetter(this, "WindowsRegistry",
|
ChromeUtils.defineModuleGetter(this, "WindowsRegistry",
|
||||||
"resource://gre/modules/WindowsRegistry.jsm");
|
"resource://gre/modules/WindowsRegistry.jsm");
|
||||||
ChromeUtils.defineModuleGetter(this, "setTimeout",
|
ChromeUtils.defineModuleGetter(this, "setTimeout",
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@ XPCOMUtils.defineLazyScriptGetter(this, ["PlacesInsertionPoint", "PlacesControll
|
||||||
"chrome://browser/content/places/controller.js");
|
"chrome://browser/content/places/controller.js");
|
||||||
/* End Shared Places Import */
|
/* End Shared Places Import */
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
|
|
||||||
var gHistoryTree;
|
var gHistoryTree;
|
||||||
var gSearchBox;
|
var gSearchBox;
|
||||||
var gHistoryGrouping = "";
|
var gHistoryGrouping = "";
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ XPCOMUtils.defineLazyScriptGetter(this, ["PlacesInsertionPoint", "PlacesControll
|
||||||
/* End Shared Places Import */
|
/* End Shared Places Import */
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
ChromeUtils.defineModuleGetter(this, "MigrationUtils",
|
ChromeUtils.defineModuleGetter(this, "MigrationUtils",
|
||||||
"resource:///modules/MigrationUtils.jsm");
|
"resource:///modules/MigrationUtils.jsm");
|
||||||
ChromeUtils.defineModuleGetter(this, "BookmarkJSONUtils",
|
ChromeUtils.defineModuleGetter(this, "BookmarkJSONUtils",
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,6 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
|
|
||||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
|
|
||||||
function debug(msg) {
|
function debug(msg) {
|
||||||
Services.console.logStringMessage("SessionStoreContent: " + msg);
|
Services.console.logStringMessage("SessionStoreContent: " + msg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ var EXPORTED_SYMBOLS = ["SessionSaver"];
|
||||||
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,6 @@ const RESTORE_TAB_CONTENT_REASON = {
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
|
ChromeUtils.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryTimestamps.jsm", this);
|
ChromeUtils.import("resource://gre/modules/TelemetryTimestamps.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Timer.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||||
Services: "resource://gre/modules/Services.jsm",
|
Services: "resource://gre/modules/Services.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingEnabled",
|
XPCOMUtils.defineLazyPreferenceGetter(this, "gTabWarmingEnabled",
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||||
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
||||||
FormHistory: "resource://gre/modules/FormHistory.jsm",
|
FormHistory: "resource://gre/modules/FormHistory.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
|
ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@
|
||||||
var EXPORTED_SYMBOLS = ["SchedulePressure"];
|
var EXPORTED_SYMBOLS = ["SchedulePressure"];
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
|
|
||||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "SCHEDULE_PRESSURE_ENABLED",
|
XPCOMUtils.defineLazyPreferenceGetter(this, "SCHEDULE_PRESSURE_ENABLED",
|
||||||
"browser.schedulePressure.enabled", true);
|
"browser.schedulePressure.enabled", true);
|
||||||
XPCOMUtils.defineLazyPreferenceGetter(this, "TIMEOUT_AMOUNT",
|
XPCOMUtils.defineLazyPreferenceGetter(this, "TIMEOUT_AMOUNT",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const { TelemetryStopwatch } = require("resource://gre/modules/TelemetryStopwatch.jsm");
|
const TelemetryStopwatch = require("TelemetryStopwatch");
|
||||||
const { getNthPathExcluding } = require("devtools/shared/platform/stack");
|
const { getNthPathExcluding } = require("devtools/shared/platform/stack");
|
||||||
const { TelemetryEnvironment } = require("resource://gre/modules/TelemetryEnvironment.jsm");
|
const { TelemetryEnvironment } = require("resource://gre/modules/TelemetryEnvironment.jsm");
|
||||||
const WeakMapMap = require("devtools/client/shared/WeakMapMap");
|
const WeakMapMap = require("devtools/client/shared/WeakMapMap");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
// This test tends to trigger a race in the fullscreen time telemetry,
|
||||||
|
// where the fullscreen enter and fullscreen exit events (which use the
|
||||||
|
// same histogram ID) overlap. That causes TelemetryStopwatch to log an
|
||||||
|
// error.
|
||||||
|
SimpleTest.ignoreAllUncaughtExceptions(true);
|
||||||
|
|
||||||
const kPage = "http://example.org/browser/" +
|
const kPage = "http://example.org/browser/" +
|
||||||
"dom/html/test/file_fullscreen-newtab.html";
|
"dom/html/test/file_fullscreen-newtab.html";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
ChromeUtils.import("resource://services-common/utils.js"); /* global: CommonUtils */
|
ChromeUtils.import("resource://services-common/utils.js"); /* global: CommonUtils */
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(window, "gChromeWin", () =>
|
XPCOMUtils.defineLazyGetter(window, "gChromeWin", () =>
|
||||||
window.docShell.rootTreeItem.domWindow
|
window.docShell.rootTreeItem.domWindow
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,6 @@ ChromeUtils.defineModuleGetter(this, "RuntimePermissions", "resource://gre/modul
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(this, "WebsiteMetadata", "resource://gre/modules/WebsiteMetadata.jsm");
|
ChromeUtils.defineModuleGetter(this, "WebsiteMetadata", "resource://gre/modules/WebsiteMetadata.jsm");
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch", "resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "FontEnumerator",
|
XPCOMUtils.defineLazyServiceGetter(this, "FontEnumerator",
|
||||||
"@mozilla.org/gfx/fontenumerator;1",
|
"@mozilla.org/gfx/fontenumerator;1",
|
||||||
"nsIFontEnumerator");
|
"nsIFontEnumerator");
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.jsm",
|
SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.jsm",
|
||||||
SharedPreferences: "resource://gre/modules/SharedPreferences.jsm",
|
SharedPreferences: "resource://gre/modules/SharedPreferences.jsm",
|
||||||
Task: "resource://gre/modules/Task.jsm",
|
Task: "resource://gre/modules/Task.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
|
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
OS: "resource://gre/modules/osfile.jsm",
|
OS: "resource://gre/modules/osfile.jsm",
|
||||||
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
|
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
|
||||||
Task: "resource://gre/modules/Task.jsm",
|
Task: "resource://gre/modules/Task.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetters(this, {
|
XPCOMUtils.defineLazyServiceGetters(this, {
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@ var EXPORTED_SYMBOLS = ["ExtensionTelemetry", "getTrimmedString"];
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(this, "Services",
|
ChromeUtils.defineModuleGetter(this, "Services",
|
||||||
"resource://gre/modules/Services.jsm");
|
"resource://gre/modules/Services.jsm");
|
||||||
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
|
|
||||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
|
|
||||||
// Map of the base histogram ids for the metrics recorded for the extensions.
|
// Map of the base histogram ids for the metrics recorded for the extensions.
|
||||||
const histograms = {
|
const histograms = {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ ChromeUtils.import("resource://gre/modules/narrate/VoiceSelect.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/narrate/Narrator.jsm");
|
ChromeUtils.import("resource://gre/modules/narrate/Narrator.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/AsyncPrefs.jsm");
|
ChromeUtils.import("resource://gre/modules/AsyncPrefs.jsm");
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["NarrateControls"];
|
var EXPORTED_SYMBOLS = ["NarrateControls"];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@ ChromeUtils.defineModuleGetter(this, "Task",
|
||||||
// The implementation of communications
|
// The implementation of communications
|
||||||
ChromeUtils.import("resource://gre/modules/PromiseWorker.jsm", this);
|
ChromeUtils.import("resource://gre/modules/PromiseWorker.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
|
||||||
ChromeUtils.import("resource://gre/modules/AsyncShutdown.jsm", this);
|
ChromeUtils.import("resource://gre/modules/AsyncShutdown.jsm", this);
|
||||||
var Native = ChromeUtils.import("resource://gre/modules/osfile/osfile_native.jsm", {});
|
var Native = ChromeUtils.import("resource://gre/modules/osfile/osfile_native.jsm", {});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
|
||||||
ProfileAge: "resource://gre/modules/ProfileAge.jsm",
|
ProfileAge: "resource://gre/modules/ProfileAge.jsm",
|
||||||
Sqlite: "resource://gre/modules/Sqlite.jsm",
|
Sqlite: "resource://gre/modules/Sqlite.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
|
UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm",
|
||||||
UrlbarProviderOpenTabs: "resource:///modules/UrlbarProviderOpenTabs.jsm",
|
UrlbarProviderOpenTabs: "resource:///modules/UrlbarProviderOpenTabs.jsm",
|
||||||
UrlbarProvidersManager: "resource:///modules/UrlbarProvidersManager.jsm",
|
UrlbarProvidersManager: "resource:///modules/UrlbarProvidersManager.jsm",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||||
AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
|
AsyncShutdown: "resource://gre/modules/AsyncShutdown.jsm",
|
||||||
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
|
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
|
||||||
OS: "resource://gre/modules/osfile.jsm",
|
OS: "resource://gre/modules/osfile.jsm",
|
||||||
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
|
|
||||||
Deprecated: "resource://gre/modules/Deprecated.jsm",
|
Deprecated: "resource://gre/modules/Deprecated.jsm",
|
||||||
SearchStaticData: "resource://gre/modules/SearchStaticData.jsm",
|
SearchStaticData: "resource://gre/modules/SearchStaticData.jsm",
|
||||||
setTimeout: "resource://gre/modules/Timer.jsm",
|
setTimeout: "resource://gre/modules/Timer.jsm",
|
||||||
|
|
|
||||||
|
|
@ -1,434 +0,0 @@
|
||||||
/* 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";
|
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["TelemetryStopwatch"];
|
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
||||||
ChromeUtils.defineModuleGetter(this, "Log",
|
|
||||||
"resource://gre/modules/Log.jsm");
|
|
||||||
|
|
||||||
// Weak map does not allow using null objects as keys. These objects are used
|
|
||||||
// as 'null' placeholders.
|
|
||||||
const NULL_OBJECT = {};
|
|
||||||
const NULL_KEY = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timers is a variation of a Map used for storing information about running
|
|
||||||
* Stopwatches. Timers has the following data structure:
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* "HISTOGRAM_NAME": WeakMap {
|
|
||||||
* Object || NULL_OBJECT: Map {
|
|
||||||
* "KEY" || NULL_KEY: startTime
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // Stores current time for a keyed histogram "PLAYING_WITH_CUTE_ANIMALS".
|
|
||||||
* Timers.put("PLAYING_WITH_CUTE_ANIMALS", null, "CATS", Date.now());
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* // Returns information about a simple Stopwatch.
|
|
||||||
* let startTime = Timers.get("PLAYING_WITH_CUTE_ANIMALS", null, "CATS");
|
|
||||||
*/
|
|
||||||
const Timers = {
|
|
||||||
_timers: new Map(),
|
|
||||||
|
|
||||||
_inSeconds: new Set(),
|
|
||||||
|
|
||||||
_validTypes(histogram, obj, key) {
|
|
||||||
const nonEmptyString = value => {
|
|
||||||
return typeof value === "string" && value !== "" && value.length > 0;
|
|
||||||
};
|
|
||||||
return nonEmptyString(histogram) &&
|
|
||||||
typeof obj == "object" &&
|
|
||||||
(key === NULL_KEY || nonEmptyString(key));
|
|
||||||
},
|
|
||||||
|
|
||||||
get(histogram, obj, key) {
|
|
||||||
key = key === null ? NULL_KEY : key;
|
|
||||||
obj = obj || NULL_OBJECT;
|
|
||||||
|
|
||||||
if (!this.has(histogram, obj, key)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._timers.get(histogram).get(obj).get(key);
|
|
||||||
},
|
|
||||||
|
|
||||||
put(histogram, obj, key, startTime, {inSeconds} = {}) {
|
|
||||||
key = key === null ? NULL_KEY : key;
|
|
||||||
obj = obj || NULL_OBJECT;
|
|
||||||
|
|
||||||
if (!this._validTypes(histogram, obj, key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inSeconds) {
|
|
||||||
this._inSeconds.add(histogram);
|
|
||||||
}
|
|
||||||
|
|
||||||
const objectMap = this._timers.get(histogram) || new WeakMap();
|
|
||||||
const keyedInfo = objectMap.get(obj) || new Map();
|
|
||||||
keyedInfo.set(key, startTime);
|
|
||||||
objectMap.set(obj, keyedInfo);
|
|
||||||
this._timers.set(histogram, objectMap);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
has(histogram, obj, key) {
|
|
||||||
key = key === null ? NULL_KEY : key;
|
|
||||||
obj = obj || NULL_OBJECT;
|
|
||||||
|
|
||||||
return this._timers.has(histogram) &&
|
|
||||||
this._timers.get(histogram).has(obj) &&
|
|
||||||
this._timers.get(histogram).get(obj).has(key);
|
|
||||||
},
|
|
||||||
|
|
||||||
delete(histogram, obj, key) {
|
|
||||||
key = key === null ? NULL_KEY : key;
|
|
||||||
obj = obj || NULL_OBJECT;
|
|
||||||
|
|
||||||
if (!this.has(histogram, obj, key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._inSeconds.delete(histogram);
|
|
||||||
|
|
||||||
const objectMap = this._timers.get(histogram);
|
|
||||||
const keyedInfo = objectMap.get(obj);
|
|
||||||
if (keyedInfo.size > 1) {
|
|
||||||
keyedInfo.delete(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
objectMap.delete(obj);
|
|
||||||
// NOTE:
|
|
||||||
// We never delete empty objecMaps from this._timers because there is no
|
|
||||||
// nice solution for tracking the number of objects in a WeakMap.
|
|
||||||
// WeakMap is not enumerable, so we can't deterministically say when it's
|
|
||||||
// empty. We accept that trade-off here, given that entries for short-lived
|
|
||||||
// objects will go away when they are no longer referenced
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var TelemetryStopwatch = {
|
|
||||||
/**
|
|
||||||
* Starts a timer associated with a telemetry histogram. The timer can be
|
|
||||||
* directly associated with a histogram, or with a pair of a histogram and
|
|
||||||
* an object.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer is
|
|
||||||
* associated with this object, meaning that multiple
|
|
||||||
* timers for the same histogram may be run
|
|
||||||
* concurrently, as long as they are associated with
|
|
||||||
* different objects.
|
|
||||||
* @param {Object} [options.inSeconds=false] - Record elapsed time for this
|
|
||||||
* histogram in seconds instead of milliseconds. Defaults to
|
|
||||||
* false.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer was successfully started, false
|
|
||||||
* otherwise. If a timer already exists, it can't be
|
|
||||||
* started again, and the existing one will be cleared in
|
|
||||||
* order to avoid measurements errors.
|
|
||||||
*/
|
|
||||||
start(aHistogram, aObj, {inSeconds} = {}) {
|
|
||||||
return TelemetryStopwatchImpl.start(aHistogram, aObj, null, {inSeconds});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a timer associated with a telemetry histogram is currently
|
|
||||||
* running. The timer can be directly associated with a histogram, or with a
|
|
||||||
* pair of a histogram and an object.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer is
|
|
||||||
* associated with this object, meaning that multiple
|
|
||||||
* timers for the same histogram may be run
|
|
||||||
* concurrently, as long as they are associated with
|
|
||||||
* different objects.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer exists and is currently running.
|
|
||||||
*/
|
|
||||||
running(aHistogram, aObj) {
|
|
||||||
return TelemetryStopwatchImpl.running(aHistogram, aObj, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the timer associated with a telemetry histogram. The timer can be
|
|
||||||
* directly associated with a histogram, or with a pair of a histogram and
|
|
||||||
* an object. Important: Only use this method when a legitimate cancellation
|
|
||||||
* should be done.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer is
|
|
||||||
* associated with this object, meaning that multiple
|
|
||||||
* timers or a same histogram may be run concurrently,
|
|
||||||
* as long as they are associated with different
|
|
||||||
* objects.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer exist and it was cleared, False
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
cancel(aHistogram, aObj) {
|
|
||||||
return TelemetryStopwatchImpl.cancel(aHistogram, aObj, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the elapsed time for a particular stopwatch. Primarily for
|
|
||||||
* debugging purposes. Must be called prior to finish.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
* If an invalid name is given, the function will
|
|
||||||
* throw.
|
|
||||||
*
|
|
||||||
* @param (Object) aObj - Optional parameter which associates the histogram
|
|
||||||
* timer with the given object.
|
|
||||||
*
|
|
||||||
* @param {Boolean} aCanceledOkay - Optional parameter which will suppress any
|
|
||||||
* warnings that normally fire when a stopwatch
|
|
||||||
* is finished after being cancelled. Defaults
|
|
||||||
* to false.
|
|
||||||
*
|
|
||||||
* @returns {Integer} time in milliseconds or -1 if the stopwatch was not
|
|
||||||
* found.
|
|
||||||
*/
|
|
||||||
timeElapsed(aHistogram, aObj, aCanceledOkay) {
|
|
||||||
return TelemetryStopwatchImpl.timeElapsed(aHistogram, aObj, null,
|
|
||||||
aCanceledOkay);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the timer associated with the given histogram (and object),
|
|
||||||
* calculates the time delta between start and finish, and adds the value
|
|
||||||
* to the histogram.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter which associates the histogram
|
|
||||||
* timer with the given object.
|
|
||||||
*
|
|
||||||
* @param {Boolean} aCanceledOkay - Optional parameter which will suppress any
|
|
||||||
* warnings that normally fire when a stopwatch
|
|
||||||
* is finished after being cancelled. Defaults
|
|
||||||
* to false.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer was succesfully stopped and the data
|
|
||||||
* was added to the histogram, False otherwise.
|
|
||||||
*/
|
|
||||||
finish(aHistogram, aObj, aCanceledOkay) {
|
|
||||||
return TelemetryStopwatchImpl.finish(aHistogram, aObj, null, aCanceledOkay);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a timer associated with a keyed telemetry histogram. The timer can
|
|
||||||
* be directly associated with a histogram and its key. Similarly to
|
|
||||||
* @see{TelemetryStopwatch.stat} the histogram and its key can be associated
|
|
||||||
* with an object. Each key may have multiple associated objects and each
|
|
||||||
* object can be associated with multiple keys.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {String} aKey - a string which must be a valid histgram key.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer is
|
|
||||||
* associated with this object, meaning that multiple
|
|
||||||
* timers for the same histogram may be run
|
|
||||||
* concurrently,as long as they are associated with
|
|
||||||
* different objects.
|
|
||||||
* @param {Object} [options.inSeconds=false] - Record elapsed time for this
|
|
||||||
* histogram in seconds instead of milliseconds. Defaults to
|
|
||||||
* false.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer was successfully started, false
|
|
||||||
* otherwise. If a timer already exists, it can't be
|
|
||||||
* started again, and the existing one will be cleared in
|
|
||||||
* order to avoid measurements errors.
|
|
||||||
*/
|
|
||||||
startKeyed(aHistogram, aKey, aObj, {inSeconds} = {}) {
|
|
||||||
return TelemetryStopwatchImpl.start(aHistogram, aObj, aKey, {inSeconds});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a timer associated with a telemetry histogram is currently
|
|
||||||
* running. Similarly to @see{TelemetryStopwatch.running} the timer and its
|
|
||||||
* key can be associated with an object. Each key may have multiple associated
|
|
||||||
* objects and each object can be associated with multiple keys.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {String} aKey - a string which must be a valid histgram key.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer is
|
|
||||||
* associated with this object, meaning that multiple
|
|
||||||
* timers for the same histogram may be run
|
|
||||||
* concurrently, as long as they are associated with
|
|
||||||
* different objects.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer exists and is currently running.
|
|
||||||
*/
|
|
||||||
runningKeyed(aHistogram, aKey, aObj) {
|
|
||||||
return TelemetryStopwatchImpl.running(aHistogram, aObj, aKey);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the timer associated with a keyed histogram. Important: Only use
|
|
||||||
* this method when a legitimate cancellation should be done.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {String} aKey - a string which must be a valid histgram key.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer
|
|
||||||
* associated with this object is deleted.
|
|
||||||
*
|
|
||||||
* @return {Boolean} True if the timer exist and it was cleared, False
|
|
||||||
* otherwise.
|
|
||||||
*/
|
|
||||||
cancelKeyed(aHistogram, aKey, aObj) {
|
|
||||||
return TelemetryStopwatchImpl.cancel(aHistogram, aObj, aKey);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the elapsed time for a particular stopwatch. Primarily for
|
|
||||||
* debugging purposes. Must be called prior to finish.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {String} aKey - a string which must be a valid histgram key.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - Optional parameter. If specified, the timer
|
|
||||||
* associated with this object is used to calculate
|
|
||||||
* the elapsed time.
|
|
||||||
*
|
|
||||||
* @return {Integer} time in milliseconds or -1 if the stopwatch was not
|
|
||||||
* found.
|
|
||||||
*/
|
|
||||||
timeElapsedKeyed(aHistogram, aKey, aObj, aCanceledOkay) {
|
|
||||||
return TelemetryStopwatchImpl.timeElapsed(aHistogram, aObj, aKey,
|
|
||||||
aCanceledOkay);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the timer associated with the given keyed histogram (and object),
|
|
||||||
* calculates the time delta between start and finish, and adds the value
|
|
||||||
* to the keyed histogram.
|
|
||||||
*
|
|
||||||
* @param {String} aHistogram - a string which must be a valid histogram name.
|
|
||||||
*
|
|
||||||
* @param {String} aKey - a string which must be a valid histgram key.
|
|
||||||
*
|
|
||||||
* @param {Object} aObj - optional parameter which associates the histogram
|
|
||||||
* timer with the given object.
|
|
||||||
*
|
|
||||||
* @param {Boolean} aCanceledOkay - Optional parameter which will suppress any
|
|
||||||
* warnings that normally fire when a stopwatch
|
|
||||||
* is finished after being cancelled. Defaults
|
|
||||||
* to false.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} True if the timer was succesfully stopped and the data
|
|
||||||
* was added to the histogram, False otherwise.
|
|
||||||
*/
|
|
||||||
finishKeyed(aHistogram, aKey, aObj, aCanceledOkay) {
|
|
||||||
return TelemetryStopwatchImpl.finish(aHistogram, aObj, aKey, aCanceledOkay);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the testing mode. Used by tests.
|
|
||||||
*/
|
|
||||||
setTestModeEnabled(testing = true) {
|
|
||||||
TelemetryStopwatchImpl.suppressErrors(testing);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var TelemetryStopwatchImpl = {
|
|
||||||
// Suppress errors. Used when testing.
|
|
||||||
_suppressErrors: false,
|
|
||||||
|
|
||||||
suppressErrors(suppress) {
|
|
||||||
this._suppressErrors = suppress;
|
|
||||||
},
|
|
||||||
|
|
||||||
start(histogram, object, key, {inSeconds} = {}) {
|
|
||||||
if (Timers.has(histogram, object, key)) {
|
|
||||||
Timers.delete(histogram, object, key);
|
|
||||||
if (!this._suppressErrors) {
|
|
||||||
Cu.reportError(`TelemetryStopwatch: key "${histogram}" was already ` +
|
|
||||||
"initialized");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Timers.put(histogram, object, key, Cu.now(), {inSeconds});
|
|
||||||
},
|
|
||||||
|
|
||||||
running(histogram, object, key) {
|
|
||||||
return Timers.has(histogram, object, key);
|
|
||||||
},
|
|
||||||
|
|
||||||
cancel(histogram, object, key) {
|
|
||||||
return Timers.delete(histogram, object, key);
|
|
||||||
},
|
|
||||||
|
|
||||||
timeElapsed(histogram, object, key, aCanceledOkay) {
|
|
||||||
const startTime = Timers.get(histogram, object, key);
|
|
||||||
if (startTime === null) {
|
|
||||||
if (!aCanceledOkay && !this._suppressErrors) {
|
|
||||||
Cu.reportError("TelemetryStopwatch: requesting elapsed time for " +
|
|
||||||
`nonexisting stopwatch. Histogram: "${histogram}", ` +
|
|
||||||
`key: "${key}"`);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const delta = Cu.now() - startTime;
|
|
||||||
if (Timers._inSeconds.has(histogram)) {
|
|
||||||
return Math.round(delta / 1000);
|
|
||||||
}
|
|
||||||
return Math.round(delta);
|
|
||||||
} catch (e) {
|
|
||||||
if (!this._suppressErrors) {
|
|
||||||
Cu.reportError("TelemetryStopwatch: failed to calculate elapsed time " +
|
|
||||||
`for Histogram: "${histogram}", key: "${key}", ` +
|
|
||||||
`exception: ${Log.exceptionStr(e)}`);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
finish(histogram, object, key, aCanceledOkay) {
|
|
||||||
const delta = this.timeElapsed(histogram, object, key, aCanceledOkay);
|
|
||||||
if (delta == -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (key) {
|
|
||||||
Services.telemetry.getKeyedHistogramById(histogram).add(key, delta);
|
|
||||||
} else {
|
|
||||||
Services.telemetry.getHistogramById(histogram).add(delta);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (!this._suppressErrors) {
|
|
||||||
Cu.reportError("TelemetryStopwatch: failed to update the Histogram " +
|
|
||||||
`"${histogram}", using key: "${key}", ` +
|
|
||||||
`exception: ${Log.exceptionStr(e)}`);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Timers.delete(histogram, object, key);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -272,7 +272,7 @@ Note that ``nsITelemetry.getHistogramById()`` will throw an ``NS_ERROR_FAILURE``
|
||||||
|
|
||||||
Adding a new Telemetry probe is not possible with Artifact builds. A full build is needed.
|
Adding a new Telemetry probe is not possible with Artifact builds. A full build is needed.
|
||||||
|
|
||||||
For histograms measuring time, `TelemetryStopwatch <https://dxr.mozilla.org/mozilla-central/source/toolkit/components/telemetry/TelemetryStopwatch.jsm>`_ can be used to avoid working with Dates manually:
|
For histograms measuring time, TelemetryStopwatch can be used to avoid working with Dates manually:
|
||||||
|
|
||||||
.. code-block:: js
|
.. code-block:: js
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ These helpers record the elapsed time into histograms, so you have to create sui
|
||||||
|
|
||||||
From JavaScript
|
From JavaScript
|
||||||
===============
|
===============
|
||||||
JavaScript can measure elapsed time using `TelemetryStopwatch.jsm <https://dxr.mozilla.org/mozilla-central/source/toolkit/components/telemetry/TelemetryStopwatch.jsm>`_.
|
JavaScript can measure elapsed time using TelemetryStopwatch.
|
||||||
|
|
||||||
``TelemetryStopwatch`` is a helper that simplifies recording elapsed time (in milliseconds) into histograms (plain or keyed).
|
``TelemetryStopwatch`` is a helper that simplifies recording elapsed time (in milliseconds) into histograms (plain or keyed).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,6 @@ EXTRA_JS_MODULES += [
|
||||||
'app/TelemetryEnvironment.jsm',
|
'app/TelemetryEnvironment.jsm',
|
||||||
'app/TelemetryReportingPolicy.jsm',
|
'app/TelemetryReportingPolicy.jsm',
|
||||||
'app/TelemetrySend.jsm',
|
'app/TelemetrySend.jsm',
|
||||||
'app/TelemetryStopwatch.jsm',
|
|
||||||
'app/TelemetryStorage.jsm',
|
'app/TelemetryStorage.jsm',
|
||||||
'app/TelemetryTimestamps.jsm',
|
'app/TelemetryTimestamps.jsm',
|
||||||
'app/TelemetryUtils.jsm',
|
'app/TelemetryUtils.jsm',
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@ ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
|
ChromeUtils.import("resource://gre/modules/osfile.jsm", this);
|
||||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||||
|
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
|
||||||
|
|
||||||
ChromeUtils.defineModuleGetter(this, "TelemetryHealthPing",
|
ChromeUtils.defineModuleGetter(this, "TelemetryHealthPing",
|
||||||
"resource://gre/modules/HealthPing.jsm");
|
"resource://gre/modules/HealthPing.jsm");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -421,19 +421,6 @@
|
||||||
<field name="arrowKeysShouldWrap" readonly="true">
|
<field name="arrowKeysShouldWrap" readonly="true">
|
||||||
/Mac/.test(navigator.platform)
|
/Mac/.test(navigator.platform)
|
||||||
</field>
|
</field>
|
||||||
<property name="TelemetryStopwatch" readonly="true">
|
|
||||||
<getter><![CDATA[
|
|
||||||
let module = {};
|
|
||||||
ChromeUtils.import("resource://gre/modules/TelemetryStopwatch.jsm", module);
|
|
||||||
Object.defineProperty(this, "TelemetryStopwatch", {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: true,
|
|
||||||
writable: true,
|
|
||||||
value: module.TelemetryStopwatch,
|
|
||||||
});
|
|
||||||
return module.TelemetryStopwatch;
|
|
||||||
]]></getter>
|
|
||||||
</property>
|
|
||||||
</implementation>
|
</implementation>
|
||||||
|
|
||||||
<handlers>
|
<handlers>
|
||||||
|
|
@ -447,7 +434,7 @@
|
||||||
if (this != this.parentNode.selectedItem) { // Not selected yet
|
if (this != this.parentNode.selectedItem) { // Not selected yet
|
||||||
let stopwatchid = this.parentNode.getAttribute("stopwatchid");
|
let stopwatchid = this.parentNode.getAttribute("stopwatchid");
|
||||||
if (stopwatchid) {
|
if (stopwatchid) {
|
||||||
this.TelemetryStopwatch.start(stopwatchid);
|
TelemetryStopwatch.start(stopwatchid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this before setting the 'ignorefocus' attribute because this
|
// Call this before setting the 'ignorefocus' attribute because this
|
||||||
|
|
@ -469,7 +456,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stopwatchid) {
|
if (stopwatchid) {
|
||||||
this.TelemetryStopwatch.finish(stopwatchid);
|
TelemetryStopwatch.finish(stopwatchid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise this tab is already selected and we will fall
|
// Otherwise this tab is already selected and we will fall
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue