зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b2g-inbound a=merge CLOSED TREE
This commit is contained in:
Коммит
1b2b74bdb6
|
@ -319,7 +319,7 @@ pref("media.fragmented-mp4.gonk.enabled", true);
|
|||
pref("media.video-queue.default-size", 3);
|
||||
|
||||
// optimize images' memory usage
|
||||
pref("image.mem.decodeondraw", true);
|
||||
pref("image.mem.decodeondraw", false);
|
||||
pref("image.mem.allow_locking_in_content_processes", false); /* don't allow image locking */
|
||||
// Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller.
|
||||
// Almost everything that was factored into 'max_decoded_image_kb' is now stored
|
||||
|
|
|
@ -1438,6 +1438,7 @@ pref("devtools.profiler.ui.show-idle-blocks", true);
|
|||
|
||||
// The default Performance UI settings
|
||||
pref("devtools.performance.ui.invert-call-tree", true);
|
||||
pref("devtools.performance.ui.invert-flame-graph", false);
|
||||
pref("devtools.performance.ui.flatten-tree-recursion", true);
|
||||
pref("devtools.performance.ui.show-platform-data", false);
|
||||
pref("devtools.performance.ui.show-idle-blocks", true);
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
# 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/.
|
||||
|
||||
function gEMEListener(msg /*{target: browser, data: data} */) {
|
||||
let browser = msg.target;
|
||||
let notificationId = "drmContentPlaying";
|
||||
// Don't need to show if disabled, nor reshow if it's already there
|
||||
if (!Services.prefs.getBoolPref("browser.eme.ui.enabled") ||
|
||||
PopupNotifications.getNotification(notificationId, browser)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let msgId = "emeNotifications.drmContentPlaying.message";
|
||||
let brandName = document.getElementById("bundle_brand").getString("brandShortName");
|
||||
let message = gNavigatorBundle.getFormattedString(msgId, [msg.data.drmProvider, brandName]);
|
||||
let anchorId = "eme-notification-icon";
|
||||
|
||||
let mainAction = {
|
||||
label: gNavigatorBundle.getString("emeNotifications.drmContentPlaying.button.label"),
|
||||
accessKey: gNavigatorBundle.getString("emeNotifications.drmContentPlaying.button.accesskey"),
|
||||
callback: function() { openPreferences("paneContent"); },
|
||||
dismiss: true
|
||||
};
|
||||
let options = {
|
||||
dismissed: true,
|
||||
eventCallback: aTopic => aTopic == "swapping",
|
||||
};
|
||||
PopupNotifications.show(browser, notificationId, message, anchorId, mainAction, null, options);
|
||||
};
|
||||
|
||||
window.messageManager.addMessageListener("EMEVideo:MetadataLoaded", gEMEListener);
|
||||
window.addEventListener("unload", function() {
|
||||
window.messageManager.removeMessageListener("EMEVideo:MetadataLoaded", gEMEListener);
|
||||
}, false);
|
|
@ -214,6 +214,7 @@ let gInitialPages = [
|
|||
#include browser-ctrlTab.js
|
||||
#include browser-customization.js
|
||||
#include browser-devedition.js
|
||||
#include browser-eme.js
|
||||
#include browser-feeds.js
|
||||
#include browser-fullScreen.js
|
||||
#include browser-fullZoom.js
|
||||
|
|
|
@ -822,6 +822,7 @@
|
|||
<image id="servicesInstall-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="translate-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="translated-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="eme-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
</box>
|
||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||
code fires onmousedown, and hence eats our favicon drag events.
|
||||
|
|
|
@ -8,6 +8,7 @@ let {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/ContentWebRTC.jsm");
|
||||
Cu.import("resource:///modules/ContentObservers.jsm");
|
||||
Cu.import("resource://gre/modules/InlineSpellChecker.jsm");
|
||||
Cu.import("resource://gre/modules/InlineSpellCheckerContent.jsm");
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ DIRS += [
|
|||
'sessionstore',
|
||||
'shell',
|
||||
'selfsupport',
|
||||
'sidebar',
|
||||
'tabview',
|
||||
'uitour',
|
||||
'translation',
|
||||
|
|
|
@ -11,6 +11,7 @@ support-files =
|
|||
testEngine.xml
|
||||
testEngine_dupe.xml
|
||||
testEngine_mozsearch.xml
|
||||
webapi.html
|
||||
|
||||
[browser_405664.js]
|
||||
[browser_426329.js]
|
||||
|
@ -43,3 +44,4 @@ skip-if = e10s || true # Bug ??????, Bug 1100301 - leaks windows until shutdown
|
|||
[browser_searchbar_openpopup.js]
|
||||
skip-if = os == "linux" || e10s # Linux has different focus behaviours and e10s seems to have timing issues.
|
||||
[browser_searchbar_keyboard_navigation.js]
|
||||
[browser_webapi.js]
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
let ROOT = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
|
||||
|
||||
function AddSearchProvider(...args) {
|
||||
return gBrowser.addTab(ROOT + "webapi.html?AddSearchProvider:" + encodeURIComponent(JSON.stringify(args)));
|
||||
}
|
||||
|
||||
function addSearchEngine(...args) {
|
||||
return gBrowser.addTab(ROOT + "webapi.html?addSearchEngine:" + encodeURIComponent(JSON.stringify(args)));
|
||||
}
|
||||
|
||||
function promiseDialogOpened() {
|
||||
return new Promise((resolve, reject) => {
|
||||
Services.wm.addListener({
|
||||
onOpenWindow: function(xulWin) {
|
||||
Services.wm.removeListener(this);
|
||||
|
||||
let win = xulWin.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
waitForFocus(() => {
|
||||
if (win.location == "chrome://global/content/commonDialog.xul")
|
||||
resolve(win)
|
||||
else
|
||||
reject();
|
||||
}, win);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* test_working_AddSearchProvider() {
|
||||
gBrowser.selectedTab = AddSearchProvider(ROOT + "testEngine.xml");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Foo\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_HTTP_AddSearchProvider() {
|
||||
gBrowser.selectedTab = AddSearchProvider(ROOT.replace("http:", "HTTP:") + "testEngine.xml");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Foo\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_relative_AddSearchProvider() {
|
||||
gBrowser.selectedTab = AddSearchProvider("testEngine.xml");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Foo\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_invalid_AddSearchProvider() {
|
||||
gBrowser.selectedTab = AddSearchProvider("z://foobar");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, "This search engine isn't supported by Nightly and can't be installed.",
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_missing_AddSearchProvider() {
|
||||
let url = ROOT + "foobar.xml";
|
||||
gBrowser.selectedTab = AddSearchProvider(url);
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, "Nightly could not download the search plugin from:\n" + url,
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_working_addSearchEngine_xml() {
|
||||
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.xml", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Foo\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_working_addSearchEngine_src() {
|
||||
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.src", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Test Sherlock\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_relative_addSearchEngine_xml() {
|
||||
gBrowser.selectedTab = addSearchEngine("testEngine.xml", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Foo\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_relative_addSearchEngine_src() {
|
||||
gBrowser.selectedTab = addSearchEngine("testEngine.src", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "confirmEx", "Should see the confirmation dialog.");
|
||||
is(dialog.args.text, "Add \"Test Sherlock\" to the list of engines available in the search bar?\n\nFrom: example.com",
|
||||
"Should have seen the right install message");
|
||||
dialog.document.documentElement.cancelDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_invalid_addSearchEngine() {
|
||||
gBrowser.selectedTab = addSearchEngine("z://foobar", "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, "This search engine isn't supported by Nightly and can't be installed.",
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_invalid_icon_addSearchEngine() {
|
||||
gBrowser.selectedTab = addSearchEngine(ROOT + "testEngine.src", "z://foobar", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, "This search engine isn't supported by Nightly and can't be installed.",
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
add_task(function* test_missing_addSearchEngine() {
|
||||
let url = ROOT + "foobar.xml";
|
||||
gBrowser.selectedTab = addSearchEngine(url, "", "", "");
|
||||
|
||||
let dialog = yield promiseDialogOpened();
|
||||
is(dialog.args.promptType, "alert", "Should see the alert dialog.");
|
||||
is(dialog.args.text, "Nightly could not download the search plugin from:\n" + url,
|
||||
"Should have seen the right error message")
|
||||
dialog.document.documentElement.acceptDialog();
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function installEngine() {
|
||||
var query = window.location.search.substring(1).split(":");
|
||||
var func = query[0];
|
||||
var args = JSON.parse(decodeURIComponent(query[1]));
|
||||
|
||||
if (func == "AddSearchProvider")
|
||||
window.external.AddSearchProvider(...args);
|
||||
else if (func == "addSearchEngine")
|
||||
window.sidebar.addSearchEngine(...args);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="installEngine()">
|
||||
</body>
|
||||
</html>
|
|
@ -1,10 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'nsSidebar.js',
|
||||
'nsSidebar.manifest',
|
||||
]
|
|
@ -1,127 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */
|
||||
/* 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/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const DEBUG = false; /* set to false to suppress debug messages */
|
||||
|
||||
const SIDEBAR_CONTRACTID = "@mozilla.org/sidebar;1";
|
||||
const SIDEBAR_CID = Components.ID("{22117140-9c6e-11d3-aaf1-00805f8a4905}");
|
||||
|
||||
// File extension for Sherlock search plugin description files
|
||||
const SHERLOCK_FILE_EXT_REGEXP = /\.src$/i;
|
||||
|
||||
function nsSidebar()
|
||||
{
|
||||
}
|
||||
|
||||
nsSidebar.prototype.classID = SIDEBAR_CID;
|
||||
|
||||
nsSidebar.prototype.validateSearchEngine =
|
||||
function (engineURL, iconURL)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Make sure the URLs are HTTP, HTTPS, or FTP.
|
||||
var isWeb = /^(https?|ftp):\/\//i;
|
||||
|
||||
if (!isWeb.test(engineURL))
|
||||
throw "Unsupported search engine URL";
|
||||
|
||||
if (iconURL && !isWeb.test(iconURL))
|
||||
throw "Unsupported search icon URL.";
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
debug(ex);
|
||||
Components.utils.reportError("Invalid argument passed to window.sidebar.addSearchEngine: " + ex);
|
||||
|
||||
var searchBundle = Services.strings.createBundle("chrome://global/locale/search/search.properties");
|
||||
var brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
var brandName = brandBundle.GetStringFromName("brandShortName");
|
||||
var title = searchBundle.GetStringFromName("error_invalid_engine_title");
|
||||
var msg = searchBundle.formatStringFromName("error_invalid_engine_msg",
|
||||
[brandName], 1);
|
||||
Services.ww.getNewPrompter(null).alert(title, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The suggestedTitle and suggestedCategory parameters are ignored, but remain
|
||||
// for backward compatibility.
|
||||
nsSidebar.prototype.addSearchEngine =
|
||||
function (engineURL, iconURL, suggestedTitle, suggestedCategory)
|
||||
{
|
||||
debug("addSearchEngine(" + engineURL + ", " + iconURL + ", " +
|
||||
suggestedCategory + ", " + suggestedTitle + ")");
|
||||
|
||||
if (!this.validateSearchEngine(engineURL, iconURL))
|
||||
return;
|
||||
|
||||
// OpenSearch files will likely be far more common than Sherlock files, and
|
||||
// have less consistent suffixes, so we assume that ".src" is a Sherlock
|
||||
// (text) file, and anything else is OpenSearch (XML).
|
||||
var dataType;
|
||||
if (SHERLOCK_FILE_EXT_REGEXP.test(engineURL))
|
||||
dataType = Components.interfaces.nsISearchEngine.DATA_TEXT;
|
||||
else
|
||||
dataType = Components.interfaces.nsISearchEngine.DATA_XML;
|
||||
|
||||
Services.search.addEngine(engineURL, dataType, iconURL, true);
|
||||
}
|
||||
|
||||
// This function exists largely to implement window.external.AddSearchProvider(),
|
||||
// to match other browsers' APIs. The capitalization, although nonstandard here,
|
||||
// is therefore important.
|
||||
nsSidebar.prototype.AddSearchProvider =
|
||||
function (aDescriptionURL)
|
||||
{
|
||||
// Get the favicon URL for the current page, or our best guess at the current
|
||||
// page since we don't have easy access to the active document. Most search
|
||||
// engines will override this with an icon specified in the OpenSearch
|
||||
// description anyway.
|
||||
var win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
var browser = win.gBrowser;
|
||||
var iconURL = "";
|
||||
// Use documentURIObject in the check for shouldLoadFavIcon so that we
|
||||
// do the right thing with about:-style error pages. Bug 453442
|
||||
if (browser.shouldLoadFavIcon(browser.selectedBrowser
|
||||
.contentDocument
|
||||
.documentURIObject))
|
||||
iconURL = browser.getIcon();
|
||||
|
||||
if (!this.validateSearchEngine(aDescriptionURL, iconURL))
|
||||
return;
|
||||
|
||||
const typeXML = Components.interfaces.nsISearchEngine.DATA_XML;
|
||||
Services.search.addEngine(aDescriptionURL, typeXML, iconURL, true);
|
||||
}
|
||||
|
||||
// This function exists to implement window.external.IsSearchProviderInstalled(),
|
||||
// for compatibility with other browsers. It will return an integer value
|
||||
// indicating whether the given engine is installed for the current user.
|
||||
// However, it is currently stubbed out due to security/privacy concerns
|
||||
// stemming from difficulties in determining what domain issued the request.
|
||||
// See bug 340604 and
|
||||
// http://msdn.microsoft.com/en-us/library/aa342526%28VS.85%29.aspx .
|
||||
// XXX Implement this!
|
||||
nsSidebar.prototype.IsSearchProviderInstalled =
|
||||
function (aSearchURL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsSidebar.prototype.QueryInterface = XPCOMUtils.generateQI([Components.interfaces.nsISupports]);
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsSidebar]);
|
||||
|
||||
/* static functions */
|
||||
if (DEBUG)
|
||||
debug = function (s) { dump("-*- sidebar component: " + s + "\n"); }
|
||||
else
|
||||
debug = function (s) {}
|
|
@ -1,2 +0,0 @@
|
|||
component {22117140-9c6e-11d3-aaf1-00805f8a4905} nsSidebar.js
|
||||
contract @mozilla.org/sidebar;1 {22117140-9c6e-11d3-aaf1-00805f8a4905}
|
|
@ -20,6 +20,12 @@ const RecordingModel = function (options={}) {
|
|||
this._front = options.front;
|
||||
this._performance = options.performance;
|
||||
this._label = options.label || "";
|
||||
|
||||
this._configuration = {
|
||||
withTicks: options.withTicks || false,
|
||||
withMemory: options.withMemory || false,
|
||||
withAllocations: options.withAllocations || false
|
||||
};
|
||||
};
|
||||
|
||||
RecordingModel.prototype = {
|
||||
|
@ -29,6 +35,7 @@ RecordingModel.prototype = {
|
|||
_profilerStartTime: 0,
|
||||
_timelineStartTime: 0,
|
||||
_memoryStartTime: 0,
|
||||
_configuration: {},
|
||||
|
||||
// Serializable fields, necessary and sufficient for import and export.
|
||||
_label: "",
|
||||
|
@ -99,12 +106,9 @@ RecordingModel.prototype = {
|
|||
|
||||
/**
|
||||
* Stops recording with the PerformanceFront.
|
||||
*
|
||||
* @param object options
|
||||
* @see RecordingModel.prototype.startRecording
|
||||
*/
|
||||
stopRecording: Task.async(function *(options) {
|
||||
let info = yield this._front.stopRecording(options);
|
||||
stopRecording: Task.async(function *() {
|
||||
let info = yield this._front.stopRecording(this.getConfiguration());
|
||||
this._profile = info.profile;
|
||||
this._duration = info.profilerEndTime - this._profilerStartTime;
|
||||
this._recording = false;
|
||||
|
@ -143,6 +147,15 @@ RecordingModel.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns configuration object of specifying whether the recording
|
||||
* was started withTicks, withMemory and withAllocations.
|
||||
* @return object
|
||||
*/
|
||||
getConfiguration: function () {
|
||||
return this._configuration;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the accumulated markers in the current recording.
|
||||
* @return array
|
||||
|
|
|
@ -58,11 +58,10 @@ const BRANCH_NAME = "devtools.performance.ui.";
|
|||
// Events emitted by various objects in the panel.
|
||||
const EVENTS = {
|
||||
// Fired by the OptionsView when a preference changes.
|
||||
PREF_CHANGED: "Preformance:PrefChanged",
|
||||
PREF_CHANGED: "Performance:PrefChanged",
|
||||
|
||||
// Emitted by the PerformanceController or RecordingView
|
||||
// when a recording model is selected
|
||||
RECORDING_SELECTED: "Performance:RecordingSelected",
|
||||
// Emitted by the PerformanceView when the state (display mode) changes.
|
||||
UI_STATE_CHANGED: "Performance:UI:StateChanged",
|
||||
|
||||
// Emitted by the PerformanceView on clear button click
|
||||
UI_CLEAR_RECORDINGS: "Performance:UI:ClearRecordings",
|
||||
|
@ -82,6 +81,10 @@ const EVENTS = {
|
|||
RECORDING_WILL_START: "Performance:RecordingWillStart",
|
||||
RECORDING_WILL_STOP: "Performance:RecordingWillStop",
|
||||
|
||||
// Emitted by the PerformanceController or RecordingView
|
||||
// when a recording model is selected
|
||||
RECORDING_SELECTED: "Performance:RecordingSelected",
|
||||
|
||||
// When recordings have been cleared out
|
||||
RECORDINGS_CLEARED: "Performance:RecordingsCleared",
|
||||
|
||||
|
@ -220,15 +223,15 @@ let PerformanceController = {
|
|||
* when the front has started to record.
|
||||
*/
|
||||
startRecording: Task.async(function *() {
|
||||
let recording = this._createRecording();
|
||||
|
||||
let withMemory = this.getPref("enable-memory");
|
||||
let withTicks = this.getPref("enable-framerate");
|
||||
let withAllocations = true;
|
||||
let withAllocations = this.getPref("enable-memory");
|
||||
|
||||
let recording = this._createRecording({ withMemory, withTicks, withAllocations });
|
||||
|
||||
this.emit(EVENTS.RECORDING_WILL_START, recording);
|
||||
yield recording.startRecording({ withTicks, withMemory, withAllocations });
|
||||
this.emit(EVENTS.RECORDING_STARTED, recording, { withTicks, withMemory, withAllocations });
|
||||
this.emit(EVENTS.RECORDING_STARTED, recording);
|
||||
|
||||
this.setCurrentRecording(recording);
|
||||
}),
|
||||
|
@ -241,9 +244,7 @@ let PerformanceController = {
|
|||
let recording = this._getLatestRecording();
|
||||
|
||||
this.emit(EVENTS.RECORDING_WILL_STOP, recording);
|
||||
yield recording.stopRecording({
|
||||
withAllocations: true
|
||||
});
|
||||
yield recording.stopRecording();
|
||||
this.emit(EVENTS.RECORDING_STOPPED, recording);
|
||||
}),
|
||||
|
||||
|
@ -295,11 +296,18 @@ let PerformanceController = {
|
|||
* Creates a new RecordingModel, fires events and stores it
|
||||
* internally in the controller.
|
||||
*
|
||||
* @param object options
|
||||
* @see PerformanceFront.prototype.startRecording
|
||||
* @return RecordingModel
|
||||
* The newly created recording model.
|
||||
*/
|
||||
_createRecording: function () {
|
||||
let recording = new RecordingModel({ front: gFront, performance });
|
||||
_createRecording: function (options={}) {
|
||||
let { withMemory, withTicks, withAllocations } = options;
|
||||
let front = gFront;
|
||||
|
||||
let recording = new RecordingModel(
|
||||
{ front, performance, withMemory, withTicks, withAllocations });
|
||||
|
||||
this._recordings.push(recording);
|
||||
return recording;
|
||||
},
|
||||
|
|
|
@ -29,7 +29,7 @@ let PerformanceView = {
|
|||
/**
|
||||
* Sets up the view with event binding and main subviews.
|
||||
*/
|
||||
initialize: function () {
|
||||
initialize: Task.async(function* () {
|
||||
this._recordButton = $("#main-record-button");
|
||||
this._importButton = $("#import-button");
|
||||
this._clearButton = $("#clear-button");
|
||||
|
@ -59,22 +59,23 @@ let PerformanceView = {
|
|||
|
||||
this.setState("empty");
|
||||
|
||||
return promise.all([
|
||||
RecordingsView.initialize(),
|
||||
OverviewView.initialize(),
|
||||
ToolbarView.initialize(),
|
||||
DetailsView.initialize()
|
||||
]);
|
||||
},
|
||||
// Initialize the ToolbarView first, because other views may need access
|
||||
// to the OptionsView via the controller, to read prefs.
|
||||
yield ToolbarView.initialize();
|
||||
yield RecordingsView.initialize();
|
||||
yield OverviewView.initialize();
|
||||
yield DetailsView.initialize();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Unbinds events and destroys subviews.
|
||||
*/
|
||||
destroy: function () {
|
||||
destroy: Task.async(function* () {
|
||||
for (let button of $$(".record-button")) {
|
||||
button.removeEventListener("click", this._onRecordButtonClick);
|
||||
}
|
||||
this._importButton.removeEventListener("click", this._onImportButtonClick);
|
||||
this._clearButton.removeEventListener("click", this._onClearButtonClick);
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
|
||||
PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
||||
|
@ -82,13 +83,11 @@ let PerformanceView = {
|
|||
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
||||
PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
|
||||
|
||||
return promise.all([
|
||||
RecordingsView.destroy(),
|
||||
OverviewView.destroy(),
|
||||
ToolbarView.destroy(),
|
||||
DetailsView.destroy()
|
||||
]);
|
||||
},
|
||||
yield ToolbarView.destroy();
|
||||
yield RecordingsView.destroy();
|
||||
yield OverviewView.destroy();
|
||||
yield DetailsView.destroy();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets the state of the profiler view. Possible options are "empty",
|
||||
|
@ -104,6 +103,7 @@ let PerformanceView = {
|
|||
}
|
||||
|
||||
this._state = state;
|
||||
this.emit(EVENTS.UI_STATE_CHANGED, state);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,6 +50,11 @@
|
|||
data-pref="invert-call-tree"
|
||||
label="&profilerUI.invertTree;"
|
||||
tooltiptext="&profilerUI.invertTree.tooltiptext;"/>
|
||||
<menuitem id="option-invert-flame-graph"
|
||||
type="checkbox"
|
||||
data-pref="invert-flame-graph"
|
||||
label="&profilerUI.invertFlameGraph;"
|
||||
tooltiptext="&profilerUI.invertFlameGraph.tooltiptext;"/>
|
||||
<menuitem id="option-flatten-tree-recursion"
|
||||
type="checkbox"
|
||||
data-pref="flatten-tree-recursion"
|
||||
|
|
|
@ -21,6 +21,7 @@ support-files =
|
|||
[browser_perf-details-waterfall-render.js]
|
||||
[browser_perf-details-01.js]
|
||||
[browser_perf-details-02.js]
|
||||
[browser_perf-details-03.js]
|
||||
[browser_perf-front-basic-profiler-01.js]
|
||||
[browser_perf-front-basic-timeline-01.js]
|
||||
#[browser_perf-front-profiler-01.js] bug 1077464
|
||||
|
@ -36,13 +37,16 @@ support-files =
|
|||
[browser_perf-options-02.js]
|
||||
[browser_perf-options-invert-call-tree-01.js]
|
||||
[browser_perf-options-invert-call-tree-02.js]
|
||||
[browser_perf-options-invert-flame-graph-01.js]
|
||||
[browser_perf-options-invert-flame-graph-02.js]
|
||||
[browser_perf-options-flatten-tree-recursion-01.js]
|
||||
[browser_perf-options-flatten-tree-recursion-02.js]
|
||||
[browser_perf-options-show-platform-data-01.js]
|
||||
[browser_perf-options-show-platform-data-02.js]
|
||||
[browser_perf-options-show-idle-blocks-01.js]
|
||||
[browser_perf-options-show-idle-blocks-02.js]
|
||||
[browser_perf-options-enable-memory.js]
|
||||
[browser_perf-options-enable-memory-01.js]
|
||||
[browser_perf-options-enable-memory-02.js]
|
||||
[browser_perf-options-enable-framerate.js]
|
||||
[browser_perf-overview-render-01.js]
|
||||
[browser_perf-overview-render-02.js]
|
||||
|
@ -53,6 +57,7 @@ support-files =
|
|||
[browser_perf-overview-time-interval.js]
|
||||
[browser_perf-shared-connection-02.js]
|
||||
[browser_perf-shared-connection-03.js]
|
||||
[browser_perf-states.js]
|
||||
[browser_perf-ui-recording.js]
|
||||
[browser_perf-recording-notices-01.js]
|
||||
[browser_perf-recording-notices-02.js]
|
||||
|
|
|
@ -20,22 +20,19 @@ let TEST_DATA = {
|
|||
sites: [0, 0, 1, 2, 3],
|
||||
timestamps: [50, 100, 150, 200, 250],
|
||||
frames: [
|
||||
null,
|
||||
{
|
||||
null, {
|
||||
source: "A",
|
||||
line: 1,
|
||||
column: 2,
|
||||
functionDisplayName: "x",
|
||||
parent: 0
|
||||
},
|
||||
{
|
||||
}, {
|
||||
source: "B",
|
||||
line: 3,
|
||||
column: 4,
|
||||
functionDisplayName: "y",
|
||||
parent: 1
|
||||
},
|
||||
{
|
||||
}, {
|
||||
source: "C",
|
||||
line: 5,
|
||||
column: 6,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
let test = Task.async(function*() {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, PerformanceView, RecordingsView } = panel.panelWin;
|
||||
let { EVENTS, PerformanceController, PerformanceView, RecordingsView, OverviewView } = panel.panelWin;
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
|
|
@ -14,7 +14,7 @@ function spawnTest () {
|
|||
|
||||
let selected = DetailsView.whenViewSelected(JsCallTreeView);
|
||||
let notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
ok(DetailsView.isViewSelected(JsCallTreeView),
|
||||
|
@ -22,7 +22,7 @@ function spawnTest () {
|
|||
|
||||
selected = DetailsView.whenViewSelected(JsFlameGraphView);
|
||||
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
DetailsView.selectView("js-flamegraph");
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
ok(DetailsView.isViewSelected(JsFlameGraphView),
|
||||
|
@ -30,7 +30,7 @@ function spawnTest () {
|
|||
|
||||
selected = DetailsView.whenViewSelected(WaterfallView);
|
||||
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
DetailsView.selectView("waterfall");
|
||||
yield DetailsView.selectView("waterfall");
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
ok(DetailsView.isViewSelected(WaterfallView),
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let MEMORY_PREF = "devtools.performance.ui.enable-memory";
|
||||
|
||||
/**
|
||||
* Tests that the details view hides the memory buttons when `enable-memory` is toggled,
|
||||
* and that it switches to default panel if toggling while a memory panel is selected.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView } = panel.panelWin;
|
||||
let { $, WaterfallView, MemoryCallTreeView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
|
||||
ok(DetailsView.isViewSelected(WaterfallView),
|
||||
"The waterfall view is selected by default in the details view.");
|
||||
|
||||
let flameBtn = $("toolbarbutton[data-view='memory-flamegraph']");
|
||||
let callBtn = $("toolbarbutton[data-view='memory-calltree']");
|
||||
|
||||
is(flameBtn.hidden, true, "memory-flamegraph button hidden when enable-memory=false");
|
||||
is(callBtn.hidden, true, "memory-calltree button hidden when enable-memory=false");
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
is(flameBtn.hidden, false, "memory-flamegraph button shown when enable-memory=true");
|
||||
is(callBtn.hidden, false, "memory-calltree button shown when enable-memory=true");
|
||||
|
||||
let selected = DetailsView.whenViewSelected(MemoryCallTreeView);
|
||||
let notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
DetailsView.selectView("memory-calltree");
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
selected = DetailsView.whenViewSelected(WaterfallView);
|
||||
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
ok(DetailsView.isViewSelected(WaterfallView),
|
||||
"The waterfall view is now selected when toggling off enable-memory when a memory panel is selected.");
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
selected = DetailsView.whenViewSelected(MemoryFlameGraphView);
|
||||
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
DetailsView.selectView("memory-flamegraph");
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
selected = DetailsView.whenViewSelected(WaterfallView);
|
||||
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
yield Promise.all([selected, notified]);
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -8,7 +8,7 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
ok(DetailsView.isViewSelected(JsCallTreeView), "The call tree is now selected.");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -8,7 +8,7 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-flamegraph");
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
ok(DetailsView.isViewSelected(JsFlameGraphView), "The flamegraph is now selected.");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -8,7 +8,7 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryCallTreeView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("memory-calltree");
|
||||
yield DetailsView.selectView("memory-calltree");
|
||||
ok(DetailsView.isViewSelected(MemoryCallTreeView), "The call tree is now selected.");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -8,7 +8,7 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("memory-flamegraph");
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
ok(DetailsView.isViewSelected(MemoryFlameGraphView), "The flamegraph is now selected.");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -10,16 +10,36 @@ let WAIT_TIME = 1000;
|
|||
function spawnTest () {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
|
||||
let { profilerStartTime, timelineStartTime } = yield front.startRecording();
|
||||
let startData = yield front.startRecording();
|
||||
let { profilerStartTime, timelineStartTime, memoryStartTime } = startData;
|
||||
|
||||
ok("profilerStartTime" in startData,
|
||||
"A `profilerStartTime` property is properly set in the recording data.");
|
||||
ok("timelineStartTime" in startData,
|
||||
"A `timelineStartTime` property is properly set in the recording data.");
|
||||
ok("memoryStartTime" in startData,
|
||||
"A `memoryStartTime` property is properly set in the recording data.");
|
||||
|
||||
ok(profilerStartTime !== undefined,
|
||||
"A `profilerStartTime` property exists in the recording data.");
|
||||
ok(timelineStartTime !== undefined,
|
||||
"A `timelineStartTime` property exists in the recording data.");
|
||||
is(memoryStartTime, 0,
|
||||
"A `memoryStartTime` property exists in the recording data, but it's 0.");
|
||||
|
||||
yield busyWait(WAIT_TIME);
|
||||
|
||||
let { profile, profilerEndTime, timelineEndTime } = yield front.stopRecording();
|
||||
let stopData = yield front.stopRecording();
|
||||
let { profile, profilerEndTime, timelineEndTime, memoryEndTime } = stopData;
|
||||
|
||||
ok("profile" in stopData,
|
||||
"A `profile` property is properly set in the recording data.");
|
||||
ok("profilerEndTime" in stopData,
|
||||
"A `profilerEndTime` property is properly set in the recording data.");
|
||||
ok("timelineEndTime" in stopData,
|
||||
"A `timelineEndTime` property is properly set in the recording data.");
|
||||
ok("memoryEndTime" in stopData,
|
||||
"A `memoryEndTime` property is properly set in the recording data.");
|
||||
|
||||
ok(profile,
|
||||
"A `profile` property exists in the recording data.");
|
||||
|
@ -27,6 +47,8 @@ function spawnTest () {
|
|||
"A `profilerEndTime` property exists in the recording data.");
|
||||
ok(timelineEndTime !== undefined,
|
||||
"A `timelineEndTime` property exists in the recording data.");
|
||||
is(memoryEndTime, 0,
|
||||
"A `memoryEndTime` property exists in the recording data, but it's 0.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
|
|
@ -28,9 +28,7 @@ function spawnTest () {
|
|||
front.on("ticks", handler);
|
||||
|
||||
yield front.startRecording({ withMemory: true, withTicks: true });
|
||||
|
||||
yield Promise.all(Object.keys(deferreds).map(type => deferreds[type].promise));
|
||||
|
||||
yield front.stopRecording();
|
||||
|
||||
is(counters.markers.length, 1, "one marker event fired.");
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the performance tool can jump to the debugger, when the source was already
|
||||
* loaded in that tool.
|
||||
* Tests if the performance tool can jump to the debugger, when the source was
|
||||
* already loaded in that tool.
|
||||
*/
|
||||
|
||||
function spawnTest() {
|
||||
|
|
|
@ -8,7 +8,7 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
|
||||
// Manually call the _onPrefChanged function so we can catch an error
|
||||
try {
|
||||
|
|
|
@ -8,7 +8,7 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const FRAMERATE_PREF = "devtools.performance.ui.enable-framerate";
|
||||
|
||||
/**
|
||||
* Tests that `enable-framerate` toggles the visibility of the fps graph,
|
||||
* as well as enabling ticks data on the PerformanceFront.
|
||||
|
@ -11,20 +9,14 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $ } = panel.panelWin;
|
||||
|
||||
let recordedWithTicks = null;
|
||||
|
||||
let onStart = (_, recording, { withMemory, withTicks }) => {
|
||||
recordedWithTicks = withTicks;
|
||||
};
|
||||
PerformanceController.on(EVENTS.RECORDING_STARTED, onStart);
|
||||
|
||||
Services.prefs.setBoolPref(FRAMERATE_PREF, false);
|
||||
ok($("#time-framerate").hidden, "fps graph is hidden when ticks disabled");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
ok(recordedWithTicks === false, "PerformanceFront started without ticks recording.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withTicks, false,
|
||||
"PerformanceFront started without ticks recording.");
|
||||
|
||||
Services.prefs.setBoolPref(FRAMERATE_PREF, true);
|
||||
ok(!$("#time-framerate").hidden, "fps graph is not hidden when ticks enabled");
|
||||
|
@ -32,9 +24,9 @@ function spawnTest () {
|
|||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
ok(recordedWithTicks === true, "PerformanceFront started with ticks recording.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withTicks, true,
|
||||
"PerformanceFront started with ticks recording.");
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_STARTED, onStart);
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const MEMORY_PREF = "devtools.performance.ui.enable-memory";
|
||||
|
||||
/**
|
||||
* Tests that `enable-memory` toggles the visibility of the memory graph,
|
||||
* as well as enabling memory data on the PerformanceFront.
|
||||
|
@ -11,20 +9,16 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $ } = panel.panelWin;
|
||||
|
||||
let recordedWithMemory = null;
|
||||
|
||||
let onStart = (_, recording, { withMemory, withTicks }) => {
|
||||
recordedWithMemory = withMemory;
|
||||
};
|
||||
PerformanceController.on(EVENTS.RECORDING_STARTED, onStart);
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
ok($("#memory-overview").hidden, "memory graph is hidden when memory disabled");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
ok(recordedWithMemory === false, "PerformanceFront started without memory recording.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withMemory, false,
|
||||
"PerformanceFront started without memory recording.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withAllocations, false,
|
||||
"PerformanceFront started without allocations recording.");
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
ok(!$("#memory-overview").hidden, "memory graph is not hidden when memory enabled");
|
||||
|
@ -32,9 +26,11 @@ function spawnTest () {
|
|||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
ok(recordedWithMemory === true, "PerformanceFront started with memory recording.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withMemory, true,
|
||||
"PerformanceFront started with memory recording.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withAllocations, true,
|
||||
"PerformanceFront started with allocations recording.");
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_STARTED, onStart);
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that toggling `enable-memory` during a recording doesn't change that
|
||||
* recording's state and does not break.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $ } = panel.panelWin;
|
||||
|
||||
// Test starting without memory, and stopping with it.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
yield startRecording(panel);
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
yield stopRecording(panel);
|
||||
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withMemory, false,
|
||||
"The recording finished without tracking memory.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withAllocations, false,
|
||||
"The recording finished without tracking allocations.");
|
||||
|
||||
// Test starting with memory, and stopping without it.
|
||||
yield startRecording(panel);
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, false);
|
||||
yield stopRecording(panel);
|
||||
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withMemory, true,
|
||||
"The recording finished with tracking memory.");
|
||||
is(PerformanceController.getCurrentRecording().getConfiguration().withAllocations, true,
|
||||
"The recording finished with tracking allocations.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -1,19 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const FLATTEN_PREF = "devtools.performance.ui.flatten-tree-recursion";
|
||||
|
||||
/**
|
||||
* Tests that the js Flamegraphs gets rerendered when toggling `flatten-tree-recursion`
|
||||
* Tests that the js flamegraphs get rerendered when toggling `flatten-tree-recursion`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-flamegraph");
|
||||
let { EVENTS, PerformanceController, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
Services.prefs.setBoolPref(FLATTEN_PREF, true);
|
||||
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
|
@ -21,18 +19,42 @@ function spawnTest () {
|
|||
yield stopRecording(panel);
|
||||
yield rendered;
|
||||
|
||||
let samples1 = PerformanceController.getCurrentRecording().getProfile().threads[0].samples;
|
||||
let rendering1 = FlameGraphUtils._cache.get(samples1);
|
||||
|
||||
ok(samples1,
|
||||
"The samples were retrieved from the controller.");
|
||||
ok(rendering1,
|
||||
"The rendering data was cached.");
|
||||
|
||||
rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(FLATTEN_PREF, false);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "JsFlameGraphView rerendered when toggling flatten-tree-recursion.");
|
||||
|
||||
let samples2 = PerformanceController.getCurrentRecording().getProfile().threads[0].samples;
|
||||
let rendering2 = FlameGraphUtils._cache.get(samples2);
|
||||
|
||||
is(samples1, samples2,
|
||||
"The same samples data should be retrieved from the controller (1).");
|
||||
isnot(rendering1, rendering2,
|
||||
"The rendering data should be different because other options were used (1).");
|
||||
|
||||
rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(FLATTEN_PREF, true);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "JsFlameGraphView rerendered when toggling back flatten-tree-recursion.");
|
||||
|
||||
let samples3 = PerformanceController.getCurrentRecording().getProfile().threads[0].samples;
|
||||
let rendering3 = FlameGraphUtils._cache.get(samples3);
|
||||
|
||||
is(samples2, samples3,
|
||||
"The same samples data should be retrieved from the controller (2).");
|
||||
isnot(rendering2, rendering3,
|
||||
"The rendering data should be different because other options were used (2).");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const FLATTEN_PREF = "devtools.performance.ui.flatten-tree-recursion";
|
||||
|
||||
/**
|
||||
* Tests that the memory Flamegraphs gets rerendered when toggling `flatten-tree-recursion`
|
||||
* Tests that the memory flamegraphs get rerendered when toggling `flatten-tree-recursion`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("memory-flamegraph");
|
||||
let { EVENTS, PerformanceController, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
// Enable memory to test
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
Services.prefs.setBoolPref(FLATTEN_PREF, true);
|
||||
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
|
@ -21,18 +21,51 @@ function spawnTest () {
|
|||
yield stopRecording(panel);
|
||||
yield rendered;
|
||||
|
||||
let allocations1 = PerformanceController.getCurrentRecording().getAllocations();
|
||||
let samples1 = RecordingUtils.getSamplesFromAllocations(allocations1);
|
||||
let rendering1 = FlameGraphUtils._cache.get(samples1);
|
||||
|
||||
ok(allocations1,
|
||||
"The allocations were retrieved from the controller.");
|
||||
ok(samples1,
|
||||
"The samples were retrieved from the utility funcs.");
|
||||
ok(rendering1,
|
||||
"The rendering data was cached.");
|
||||
|
||||
rendered = once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(FLATTEN_PREF, false);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "MemoryFlameGraphView rerendered when toggling flatten-tree-recursion.");
|
||||
|
||||
let allocations2 = PerformanceController.getCurrentRecording().getAllocations();
|
||||
let samples2 = RecordingUtils.getSamplesFromAllocations(allocations2);
|
||||
let rendering2 = FlameGraphUtils._cache.get(samples2);
|
||||
|
||||
is(allocations1, allocations2,
|
||||
"The same allocations data should be retrieved from the controller (1).");
|
||||
is(samples1, samples2,
|
||||
"The same samples data should be retrieved from the utility funcs. (1).");
|
||||
isnot(rendering1, rendering2,
|
||||
"The rendering data should be different because other options were used (1).");
|
||||
|
||||
rendered = once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(FLATTEN_PREF, true);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "MemoryFlameGraphView rerendered when toggling back flatten-tree-recursion.");
|
||||
|
||||
let allocations3 = PerformanceController.getCurrentRecording().getAllocations();
|
||||
let samples3 = RecordingUtils.getSamplesFromAllocations(allocations3);
|
||||
let rendering3 = FlameGraphUtils._cache.get(samples3);
|
||||
|
||||
is(allocations2, allocations3,
|
||||
"The same allocations data should be retrieved from the controller (2).");
|
||||
is(samples2, samples3,
|
||||
"The same samples data should be retrieved from the utility funcs. (2).");
|
||||
isnot(rendering2, rendering3,
|
||||
"The rendering data should be different because other options were used (2).");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const INVERT_PREF = "devtools.performance.ui.invert-call-tree";
|
||||
|
||||
/**
|
||||
* Tests that the js call tree view is re-rendered after the
|
||||
* "invert-call-tree" pref is changed.
|
||||
* Tests that the js call tree views get rerendered when toggling `invert-call-tree`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
|
@ -13,7 +10,7 @@ function spawnTest () {
|
|||
|
||||
Services.prefs.setBoolPref(INVERT_PREF, true);
|
||||
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
ok(DetailsView.isViewSelected(JsCallTreeView), "The call tree is now selected.");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const INVERT_PREF = "devtools.performance.ui.invert-call-tree";
|
||||
|
||||
/**
|
||||
* Tests that the memory call tree view is re-rendered after the
|
||||
* "invert-call-tree" pref is changed.
|
||||
* Tests that the memory call tree views get rerendered when toggling `invert-call-tree`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryCallTreeView } = panel.panelWin;
|
||||
|
||||
// Enable memory to test
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
Services.prefs.setBoolPref(INVERT_PREF, true);
|
||||
|
||||
DetailsView.selectView("memory-calltree");
|
||||
yield DetailsView.selectView("memory-calltree");
|
||||
ok(DetailsView.isViewSelected(MemoryCallTreeView), "The call tree is now selected.");
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const INVERT_PREF = "devtools.performance.ui.invert-flame-graph";
|
||||
|
||||
/**
|
||||
* Tests that the js Flamegraphs gets rerendered when toggling `invert-flame-graph`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
|
||||
Services.prefs.setBoolPref(INVERT_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
let rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
yield stopRecording(panel);
|
||||
yield rendered;
|
||||
|
||||
rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(INVERT_PREF, false);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "JsFlameGraphView rerendered when toggling invert-flame-graph.");
|
||||
|
||||
rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(INVERT_PREF, true);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "JsFlameGraphView rerendered when toggling back invert-flame-graph.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const INVERT_PREF = "devtools.performance.ui.invert-flame-graph";
|
||||
|
||||
/**
|
||||
* Tests that the memory Flamegraphs gets rerendered when toggling `invert-flame-graph`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
Services.prefs.setBoolPref(INVERT_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
let rendered = once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED);
|
||||
yield stopRecording(panel);
|
||||
yield rendered;
|
||||
|
||||
rendered = once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(INVERT_PREF, false);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "MemoryFlameGraphView rerendered when toggling invert-flame-graph.");
|
||||
|
||||
rendered = once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED);
|
||||
Services.prefs.setBoolPref(INVERT_PREF, true);
|
||||
yield rendered;
|
||||
|
||||
ok(true, "MemoryFlameGraphView rerendered when toggling back invert-flame-graph.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -1,19 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const IDLE_PREF = "devtools.performance.ui.show-idle-blocks";
|
||||
|
||||
/**
|
||||
* Tests that the js Flamegraphs gets rerendered when toggling `show-idle-blocks`
|
||||
* Tests that the js flamegraphs get rerendered when toggling `show-idle-blocks`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-flamegraph");
|
||||
|
||||
Services.prefs.setBoolPref(IDLE_PREF, true);
|
||||
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const IDLE_PREF = "devtools.performance.ui.show-idle-blocks";
|
||||
|
||||
/**
|
||||
* Tests that the memory Flamegraphs gets rerendered when toggling `show-idle-blocks`
|
||||
* Tests that the memory flamegraphs get rerendered when toggling `show-idle-blocks`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
// Enable memory to test
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
Services.prefs.setBoolPref(IDLE_PREF, true);
|
||||
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const PLATFORM_DATA_PREF = "devtools.performance.ui.show-platform-data";
|
||||
|
||||
/**
|
||||
* Tests that the JsCallTree get rerendered when toggling `show-platform-data`
|
||||
* Tests that the js call tree views get rerendered when toggling `show-platform-data`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
DetailsView.selectView("js-calltree");
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, true);
|
||||
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const PLATFORM_DATA_PREF = "devtools.performance.ui.show-platform-data";
|
||||
|
||||
/**
|
||||
* Tests that the JsFlamegraphs get rerendered when toggling `show-platform-data`
|
||||
* Tests that the js flamegraphs get rerendered when toggling `show-platform-data`
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, false);
|
||||
DetailsView.selectView("js-flamegraph");
|
||||
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield busyWait(100);
|
||||
|
|
|
@ -8,6 +8,9 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
// Enable memory to test all the overview graphs.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
yield Promise.all([
|
||||
|
|
|
@ -9,8 +9,18 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
// Enable memory to test all the overview graphs.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
yield Promise.all([
|
||||
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
|
||||
]);
|
||||
|
||||
ok("selectionEnabled" in OverviewView.framerateGraph,
|
||||
"The selection should not be enabled for the framerate overview (1).");
|
||||
is(OverviewView.framerateGraph.selectionEnabled, false,
|
||||
|
|
|
@ -8,8 +8,8 @@ function spawnTest () {
|
|||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
|
||||
|
||||
Services.prefs.setBoolPref("devtools.performance.ui.enable-memory", true);
|
||||
Services.prefs.setBoolPref("devtools.performance.ui.enable-framerate", true);
|
||||
// Enable memory to test all the overview graphs.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
|
@ -24,9 +24,6 @@ function spawnTest () {
|
|||
|
||||
yield stopRecording(panel);
|
||||
|
||||
// Wait for the overview graph to be rerendered *after* recording.
|
||||
yield once(OverviewView, EVENTS.OVERVIEW_RENDERED);
|
||||
|
||||
ok(OverviewView.markersOverview.width > 0,
|
||||
"The overview's framerate graph has a width.");
|
||||
ok(OverviewView.markersOverview.dataScaleX > 0,
|
||||
|
|
|
@ -11,14 +11,14 @@ function spawnTest () {
|
|||
|
||||
yield startRecording(panel);
|
||||
|
||||
// Wait for the overview graph to be rendered while recording.
|
||||
yield once(OverviewView, EVENTS.OVERVIEW_RENDERED);
|
||||
yield Promise.all([
|
||||
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.OVERVIEW_RENDERED)
|
||||
]);
|
||||
|
||||
yield stopRecording(panel);
|
||||
|
||||
// Wait for the overview graph to be rerendered *after* recording.
|
||||
yield once(OverviewView, EVENTS.OVERVIEW_RENDERED);
|
||||
|
||||
let graph = OverviewView.markersOverview;
|
||||
let MAX = graph.width;
|
||||
|
||||
|
|
|
@ -7,12 +7,30 @@
|
|||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
let framerateGraph = OverviewView.framerateGraph;
|
||||
let markersOverview = OverviewView.markersOverview;
|
||||
let memoryOverview = OverviewView.memoryOverview;
|
||||
|
||||
// Enable memory to test all the overview graphs.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
yield Promise.all([
|
||||
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
|
||||
]);
|
||||
|
||||
let markersOverview = OverviewView.markersOverview;
|
||||
let memoryOverview = OverviewView.memoryOverview;
|
||||
let framerateGraph = OverviewView.framerateGraph;
|
||||
|
||||
ok(markersOverview,
|
||||
"The markers graph should have been created now.");
|
||||
ok(memoryOverview,
|
||||
"The memory graph should have been created now.");
|
||||
ok(framerateGraph,
|
||||
"The framerate graph should have been created now.");
|
||||
|
||||
ok(!framerateGraph.selectionEnabled,
|
||||
"Selection shouldn't be enabled when the first recording started (1).");
|
||||
ok(!markersOverview.selectionEnabled,
|
||||
|
@ -31,6 +49,13 @@ function spawnTest () {
|
|||
|
||||
yield startRecording(panel);
|
||||
|
||||
yield Promise.all([
|
||||
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
|
||||
]);
|
||||
|
||||
ok(!framerateGraph.selectionEnabled,
|
||||
"Selection shouldn't be enabled when the second recording started (1).");
|
||||
ok(!markersOverview.selectionEnabled,
|
||||
|
|
|
@ -7,15 +7,26 @@
|
|||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
// Enable memory to test all the overview graphs.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
yield startRecording(panel);
|
||||
|
||||
yield Promise.all([
|
||||
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
|
||||
]);
|
||||
|
||||
yield stopRecording(panel);
|
||||
|
||||
let framerateGraph = OverviewView.framerateGraph;
|
||||
let markersOverview = OverviewView.markersOverview;
|
||||
let memoryOverview = OverviewView.memoryOverview;
|
||||
|
||||
let MAX = framerateGraph.width;
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
// Perform a selection inside the framerate graph.
|
||||
|
||||
let selected = once(OverviewView, EVENTS.OVERVIEW_RANGE_SELECTED);
|
||||
|
|
|
@ -24,11 +24,14 @@ function spawnTest () {
|
|||
}
|
||||
|
||||
yield startRecording(panel);
|
||||
busyWait(100);
|
||||
|
||||
let rendered = once(OverviewView, EVENTS.OVERVIEW_RENDERED);
|
||||
yield Promise.all([
|
||||
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
|
||||
once(OverviewView, EVENTS.OVERVIEW_RENDERED)
|
||||
]);
|
||||
|
||||
yield stopRecording(panel);
|
||||
yield rendered;
|
||||
|
||||
// Get/set the time interval and wait for the event propagation.
|
||||
|
||||
|
|
|
@ -27,12 +27,12 @@ function spawnTest () {
|
|||
ok(true, "Waterfall rerenders when a range in the overview graph is selected.");
|
||||
|
||||
rendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
yield rendered;
|
||||
ok(true, "Call tree rerenders after its corresponding pane is shown.");
|
||||
|
||||
rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
DetailsView.selectView("js-flamegraph");
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
yield rendered;
|
||||
ok(true, "Flamegraph rerenders after its corresponding pane is shown.");
|
||||
|
||||
|
@ -42,12 +42,12 @@ function spawnTest () {
|
|||
ok(true, "Flamegraph rerenders when a range in the overview graph is removed.");
|
||||
|
||||
rendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
|
||||
DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
yield rendered;
|
||||
ok(true, "Call tree rerenders after its corresponding pane is shown.");
|
||||
|
||||
rendered = once(WaterfallView, EVENTS.WATERFALL_RENDERED);
|
||||
DetailsView.selectView("waterfall");
|
||||
yield DetailsView.selectView("waterfall");
|
||||
yield rendered;
|
||||
ok(true, "Waterfall rerenders after its corresponding pane is shown.");
|
||||
|
||||
|
|
|
@ -8,10 +8,23 @@
|
|||
|
||||
let test = Task.async(function*() {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, PerformanceController, DetailsSubview, RecordingsView } = panel.panelWin;
|
||||
let { $, EVENTS, PerformanceController, DetailsView, DetailsSubview, RecordingsView } = panel.panelWin;
|
||||
|
||||
// Enable memory to test the memory-calltree and memory-flamegraph.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
// Need to allow widgets to be updated while hidden, otherwise we can't use
|
||||
// `waitForWidgetsRendered`.
|
||||
DetailsSubview.canUpdateWhileHidden = true;
|
||||
|
||||
// Cycle through all the views to initialize them, otherwise we can't use
|
||||
// `waitForWidgetsRendered`. The waterfall is shown by default, but all the
|
||||
// other views are created lazily, so won't emit any events.
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
yield DetailsView.selectView("memory-calltree");
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that view states and lazy component intialization works.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceView, OverviewView, DetailsView } = panel.panelWin;
|
||||
|
||||
is(PerformanceView.getState(), "empty",
|
||||
"The intial state of the performance panel view is correct.");
|
||||
|
||||
ok(!("markersOverview" in OverviewView),
|
||||
"The markers graph should not have been created yet.");
|
||||
ok(!("memoryOverview" in OverviewView),
|
||||
"The memory graph should not have been created yet.");
|
||||
ok(!("framerateGraph" in OverviewView),
|
||||
"The framerate graph should not have been created yet.");
|
||||
|
||||
ok(DetailsView.components["waterfall"].initialized,
|
||||
"The waterfall detail view should have been created by default.");
|
||||
ok(!DetailsView.components["js-calltree"].initialized,
|
||||
"The js-calltree detail view should not have been created yet.");
|
||||
ok(!DetailsView.components["js-flamegraph"].initialized,
|
||||
"The js-flamegraph detail view should not have been created yet.");
|
||||
ok(!DetailsView.components["memory-calltree"].initialized,
|
||||
"The memory-calltree detail view should not have been created yet.");
|
||||
ok(!DetailsView.components["memory-flamegraph"].initialized,
|
||||
"The memory-flamegraph detail view should not have been created yet.");
|
||||
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
ok(!("markersOverview" in OverviewView),
|
||||
"The markers graph should still not have been created yet.");
|
||||
ok(!("memoryOverview" in OverviewView),
|
||||
"The memory graph should still not have been created yet.");
|
||||
ok(!("framerateGraph" in OverviewView),
|
||||
"The framerate graph should still not have been created yet.");
|
||||
|
||||
let stateChanged = once(PerformanceView, EVENTS.UI_STATE_CHANGED);
|
||||
yield startRecording(panel);
|
||||
yield stateChanged;
|
||||
|
||||
is(PerformanceView.getState(), "recording",
|
||||
"The current state of the performance panel view is 'recording'.");
|
||||
ok(OverviewView.memoryOverview,
|
||||
"The memory graph should have been created now.");
|
||||
ok(OverviewView.framerateGraph,
|
||||
"The framerate graph should have been created now.");
|
||||
|
||||
stateChanged = once(PerformanceView, EVENTS.UI_STATE_CHANGED);
|
||||
yield stopRecording(panel);
|
||||
yield stateChanged;
|
||||
|
||||
is(PerformanceView.getState(), "recorded",
|
||||
"The current state of the performance panel view is 'recorded'.");
|
||||
ok(!DetailsView.components["js-calltree"].initialized,
|
||||
"The js-calltree detail view should still not have been created yet.");
|
||||
ok(!DetailsView.components["js-flamegraph"].initialized,
|
||||
"The js-flamegraph detail view should still not have been created yet.");
|
||||
ok(!DetailsView.components["memory-calltree"].initialized,
|
||||
"The memory-calltree detail view should still not have been created yet.");
|
||||
ok(!DetailsView.components["memory-flamegraph"].initialized,
|
||||
"The memory-flamegraph detail view should still not have been created yet.");
|
||||
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
|
||||
is(PerformanceView.getState(), "recorded",
|
||||
"The current state of the performance panel view is still 'recorded'.");
|
||||
ok(DetailsView.components["js-calltree"].initialized,
|
||||
"The js-calltree detail view should still have been created now.");
|
||||
ok(!DetailsView.components["js-flamegraph"].initialized,
|
||||
"The js-flamegraph detail view should still not have been created yet.");
|
||||
ok(!DetailsView.components["memory-calltree"].initialized,
|
||||
"The memory-calltree detail view should still not have been created yet.");
|
||||
ok(!DetailsView.components["memory-flamegraph"].initialized,
|
||||
"The memory-flamegraph detail view should still not have been created yet.");
|
||||
|
||||
yield DetailsView.selectView("memory-calltree");
|
||||
|
||||
is(PerformanceView.getState(), "recorded",
|
||||
"The current state of the performance panel view is still 'recorded'.");
|
||||
ok(DetailsView.components["js-calltree"].initialized,
|
||||
"The js-calltree detail view should still register as being created.");
|
||||
ok(!DetailsView.components["js-flamegraph"].initialized,
|
||||
"The js-flamegraph detail view should still not have been created yet.");
|
||||
ok(DetailsView.components["memory-calltree"].initialized,
|
||||
"The memory-calltree detail view should still have been created now.");
|
||||
ok(!DetailsView.components["memory-flamegraph"].initialized,
|
||||
"The memory-flamegraph detail view should still not have been created yet.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -7,8 +7,21 @@
|
|||
|
||||
let test = Task.async(function*() {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, DetailsSubview } = panel.panelWin;
|
||||
let { EVENTS, PerformanceController, DetailsView, DetailsSubview } = panel.panelWin;
|
||||
|
||||
// Enable memory to test the memory-calltree and memory-flamegraph.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
// Cycle through all the views to initialize them, otherwise we can't use
|
||||
// `waitForWidgetsRendered`. The waterfall is shown by default, but all the
|
||||
// other views are created lazily, so won't emit any events.
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
yield DetailsView.selectView("memory-calltree");
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
// Need to allow widgets to be updated while hidden, otherwise we can't use
|
||||
// `waitForWidgetsRendered`.
|
||||
DetailsSubview.canUpdateWhileHidden = true;
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -8,8 +8,21 @@
|
|||
|
||||
let test = Task.async(function*() {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, DetailsSubview } = panel.panelWin;
|
||||
let { EVENTS, PerformanceController, DetailsView, DetailsSubview } = panel.panelWin;
|
||||
|
||||
// Enable memory to test the memory-calltree and memory-flamegraph.
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
// Cycle through all the views to initialize them, otherwise we can't use
|
||||
// `waitForWidgetsRendered`. The waterfall is shown by default, but all the
|
||||
// other views are created lazily, so won't emit any events.
|
||||
yield DetailsView.selectView("js-calltree");
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
yield DetailsView.selectView("memory-calltree");
|
||||
yield DetailsView.selectView("memory-flamegraph");
|
||||
|
||||
// Need to allow widgets to be updated while hidden, otherwise we can't use
|
||||
// `waitForWidgetsRendered`.
|
||||
DetailsSubview.canUpdateWhileHidden = true;
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -22,6 +22,13 @@ const FRAME_SCRIPT_UTILS_URL = "chrome://browser/content/devtools/frame-script-u
|
|||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/performance/test/";
|
||||
const SIMPLE_URL = EXAMPLE_URL + "doc_simple-test.html";
|
||||
|
||||
const FRAMERATE_PREF = "devtools.performance.ui.enable-framerate";
|
||||
const MEMORY_PREF = "devtools.performance.ui.enable-memory";
|
||||
const PLATFORM_DATA_PREF = "devtools.performance.ui.show-platform-data";
|
||||
const IDLE_PREF = "devtools.performance.ui.show-idle-blocks";
|
||||
const INVERT_PREF = "devtools.performance.ui.invert-call-tree";
|
||||
const FLATTEN_PREF = "devtools.performance.ui.flatten-tree-recursion";
|
||||
|
||||
// All tests are asynchronous.
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
@ -248,12 +255,10 @@ function* startRecording(panel) {
|
|||
|
||||
ok(!button.hasAttribute("checked"),
|
||||
"The record button should not be checked yet.");
|
||||
|
||||
ok(!button.hasAttribute("locked"),
|
||||
"The record button should not be locked yet.");
|
||||
|
||||
click(win, button);
|
||||
|
||||
yield clicked;
|
||||
|
||||
ok(button.hasAttribute("checked"),
|
||||
|
@ -262,7 +267,16 @@ function* startRecording(panel) {
|
|||
"The record button should be locked.");
|
||||
|
||||
yield willStart;
|
||||
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
|
||||
|
||||
yield hasStarted;
|
||||
let overviewRendered = once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED);
|
||||
|
||||
yield stateChanged;
|
||||
yield overviewRendered;
|
||||
|
||||
is(win.PerformanceView.getState(), "recording",
|
||||
"The current state is 'recording'.");
|
||||
|
||||
ok(button.hasAttribute("checked"),
|
||||
"The record button should still be checked.");
|
||||
|
@ -283,7 +297,6 @@ function* stopRecording(panel) {
|
|||
"The record button should not be locked yet.");
|
||||
|
||||
click(win, button);
|
||||
|
||||
yield clicked;
|
||||
|
||||
ok(!button.hasAttribute("checked"),
|
||||
|
@ -292,7 +305,16 @@ function* stopRecording(panel) {
|
|||
"The record button should be locked.");
|
||||
|
||||
yield willStop;
|
||||
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
|
||||
|
||||
yield hasStopped;
|
||||
let overviewRendered = once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED);
|
||||
|
||||
yield stateChanged;
|
||||
yield overviewRendered;
|
||||
|
||||
is(win.PerformanceView.getState(), "recorded",
|
||||
"The current state is 'recorded'.");
|
||||
|
||||
ok(!button.hasAttribute("checked"),
|
||||
"The record button should not be checked.");
|
||||
|
@ -306,7 +328,9 @@ function waitForWidgetsRendered(panel) {
|
|||
OverviewView,
|
||||
WaterfallView,
|
||||
JsCallTreeView,
|
||||
JsFlameGraphView
|
||||
JsFlameGraphView,
|
||||
MemoryCallTreeView,
|
||||
MemoryFlameGraphView,
|
||||
} = panel.panelWin;
|
||||
|
||||
return Promise.all([
|
||||
|
@ -316,7 +340,9 @@ function waitForWidgetsRendered(panel) {
|
|||
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
|
||||
once(WaterfallView, EVENTS.WATERFALL_RENDERED),
|
||||
once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED),
|
||||
once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED)
|
||||
once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED),
|
||||
once(MemoryCallTreeView, EVENTS.MEMORY_CALL_TREE_RENDERED),
|
||||
once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
@ -102,11 +102,10 @@ let DetailsSubview = {
|
|||
/**
|
||||
* Fired when a preference in `devtools.performance.ui.` is changed.
|
||||
*/
|
||||
_onPrefChanged: function (_, prefName, value) {
|
||||
_onPrefChanged: function (_, prefName) {
|
||||
// All detail views require a recording to be complete, so do not
|
||||
// attempt to render if recording is in progress or does not exist.
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
|
||||
if (!recording || recording.isRecording()) {
|
||||
return;
|
||||
}
|
||||
|
@ -115,6 +114,10 @@ let DetailsSubview = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this._onRerenderPrefChanged) {
|
||||
this._onRerenderPrefChanged();
|
||||
}
|
||||
|
||||
if (DetailsView.isViewSelected(this) || this.canUpdateWhileHidden) {
|
||||
this.render(OverviewView.getTimeInterval());
|
||||
} else {
|
||||
|
|
|
@ -8,7 +8,10 @@
|
|||
*/
|
||||
let JsCallTreeView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
rerenderPrefs: ["invert-call-tree", "show-platform-data"],
|
||||
rerenderPrefs: [
|
||||
"invert-call-tree",
|
||||
"show-platform-data"
|
||||
],
|
||||
|
||||
rangeChangeDebounceTime: 50, // ms
|
||||
|
||||
|
|
|
@ -9,7 +9,12 @@
|
|||
*/
|
||||
let JsFlameGraphView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
rerenderPrefs: ["flatten-tree-recursion", "show-platform-data", "show-idle-blocks"],
|
||||
rerenderPrefs: [
|
||||
"invert-flame-graph",
|
||||
"flatten-tree-recursion",
|
||||
"show-platform-data",
|
||||
"show-idle-blocks"
|
||||
],
|
||||
|
||||
/**
|
||||
* Sets up the view with event binding.
|
||||
|
@ -48,6 +53,7 @@ let JsFlameGraphView = Heritage.extend(DetailsSubview, {
|
|||
let samples = profile.threads[0].samples;
|
||||
|
||||
let data = FlameGraphUtils.createFlameGraphDataFromSamples(samples, {
|
||||
invertStack: PerformanceController.getPref("invert-flame-graph"),
|
||||
flattenRecursion: PerformanceController.getPref("flatten-tree-recursion"),
|
||||
filterFrames: !PerformanceController.getPref("show-platform-data") && FrameNode.isContent,
|
||||
showIdleBlocks: PerformanceController.getPref("show-idle-blocks") && L10N.getStr("table.idle")
|
||||
|
@ -73,5 +79,15 @@ let JsFlameGraphView = Heritage.extend(DetailsSubview, {
|
|||
_onRangeChangeInGraph: function () {
|
||||
let interval = this.graph.getViewRange();
|
||||
OverviewView.setTimeInterval(interval, { stopPropagation: true });
|
||||
},
|
||||
|
||||
/**
|
||||
* Called whenever a pref is changed and this view needs to be rerendered.
|
||||
*/
|
||||
_onRerenderPrefChanged: function() {
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
let profile = recording.getProfile();
|
||||
let samples = profile.threads[0].samples;
|
||||
FlameGraphUtils.removeFromCache(samples);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
*/
|
||||
let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
rerenderPrefs: ["invert-call-tree", "show-platform-data"],
|
||||
rerenderPrefs: [
|
||||
"invert-call-tree"
|
||||
],
|
||||
|
||||
rangeChangeDebounceTime: 100, // ms
|
||||
|
||||
|
@ -60,11 +62,10 @@ let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
|
|||
*/
|
||||
_prepareCallTree: function (allocations, { startTime, endTime }, options) {
|
||||
let samples = RecordingUtils.getSamplesFromAllocations(allocations);
|
||||
let contentOnly = !PerformanceController.getPref("show-platform-data");
|
||||
let invertTree = PerformanceController.getPref("invert-call-tree");
|
||||
|
||||
let threadNode = new ThreadNode(samples,
|
||||
{ startTime, endTime, contentOnly, invertTree });
|
||||
{ startTime, endTime, invertTree });
|
||||
|
||||
// If we have an empty profile (no samples), then don't invert the tree, as
|
||||
// it would hide the root node and a completely blank call tree space can be
|
||||
|
@ -101,5 +102,4 @@ let MemoryCallTreeView = Heritage.extend(DetailsSubview, {
|
|||
// Memory allocation samples don't contain cateogry labels.
|
||||
root.toggleCategories(false);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
*/
|
||||
let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
rerenderPrefs: ["flatten-tree-recursion", "show-idle-blocks"],
|
||||
rerenderPrefs: [
|
||||
"invert-flame-graph",
|
||||
"flatten-tree-recursion",
|
||||
"show-idle-blocks"
|
||||
],
|
||||
|
||||
/**
|
||||
* Sets up the view with event binding.
|
||||
|
@ -48,6 +52,7 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
|
|||
|
||||
let samples = RecordingUtils.getSamplesFromAllocations(allocations);
|
||||
let data = FlameGraphUtils.createFlameGraphDataFromSamples(samples, {
|
||||
invertStack: PerformanceController.getPref("invert-flame-graph"),
|
||||
flattenRecursion: PerformanceController.getPref("flatten-tree-recursion"),
|
||||
showIdleBlocks: PerformanceController.getPref("show-idle-blocks") && L10N.getStr("table.idle")
|
||||
});
|
||||
|
@ -72,5 +77,15 @@ let MemoryFlameGraphView = Heritage.extend(DetailsSubview, {
|
|||
_onRangeChangeInGraph: function () {
|
||||
let interval = this.graph.getViewRange();
|
||||
OverviewView.setTimeInterval(interval, { stopPropagation: true });
|
||||
},
|
||||
|
||||
/**
|
||||
* Called whenever a pref is changed and this view needs to be rerendered.
|
||||
*/
|
||||
_onRerenderPrefChanged: function() {
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
let allocations = recording.getAllocations();
|
||||
let samples = RecordingUtils.getSamplesFromAllocations(allocations);
|
||||
FlameGraphUtils.removeFromCache(samples);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* Waterfall view containing the timeline markers, controlled by DetailsView.
|
||||
*/
|
||||
let WaterfallView = Heritage.extend(DetailsSubview, {
|
||||
|
||||
rangeChangeDebounceTime: 10, // ms
|
||||
|
||||
/**
|
||||
|
@ -18,12 +19,9 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
|||
this.waterfall = new Waterfall($("#waterfall-breakdown"), $("#details-pane"), TIMELINE_BLUEPRINT);
|
||||
this.details = new MarkerDetails($("#waterfall-details"), $("#waterfall-view > splitter"));
|
||||
|
||||
this._onRecordingStarted = this._onRecordingStarted.bind(this);
|
||||
this._onMarkerSelected = this._onMarkerSelected.bind(this);
|
||||
this._onResize = this._onResize.bind(this);
|
||||
|
||||
PerformanceController.on(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
|
||||
|
||||
this.waterfall.on("selected", this._onMarkerSelected);
|
||||
this.waterfall.on("unselected", this._onMarkerSelected);
|
||||
this.details.on("resize", this._onResize);
|
||||
|
@ -37,8 +35,6 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
|||
destroy: function () {
|
||||
DetailsSubview.destroy.call(this);
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
|
||||
|
||||
this.waterfall.off("selected", this._onMarkerSelected);
|
||||
this.waterfall.off("unselected", this._onMarkerSelected);
|
||||
this.details.off("resize", this._onResize);
|
||||
|
@ -59,13 +55,6 @@ let WaterfallView = Heritage.extend(DetailsSubview, {
|
|||
this.emit(EVENTS.WATERFALL_RENDERED);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when recording starts.
|
||||
*/
|
||||
_onRecordingStarted: function () {
|
||||
this.waterfall.clearView();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a marker is selected in the waterfall view,
|
||||
* updating the markers detail view.
|
||||
|
|
|
@ -17,8 +17,8 @@ let DetailsView = {
|
|||
"waterfall": { id: "waterfall-view", view: WaterfallView },
|
||||
"js-calltree": { id: "js-calltree-view", view: JsCallTreeView },
|
||||
"js-flamegraph": { id: "js-flamegraph-view", view: JsFlameGraphView },
|
||||
"memory-calltree": { id: "memory-calltree-view", view: MemoryCallTreeView },
|
||||
"memory-flamegraph": { id: "memory-flamegraph-view", view: MemoryFlameGraphView }
|
||||
"memory-calltree": { id: "memory-calltree-view", view: MemoryCallTreeView, pref: "enable-memory" },
|
||||
"memory-flamegraph": { id: "memory-flamegraph-view", view: MemoryFlameGraphView, pref: "enable-memory" }
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -29,16 +29,16 @@ let DetailsView = {
|
|||
this.toolbar = $("#performance-toolbar-controls-detail-views");
|
||||
|
||||
this._onViewToggle = this._onViewToggle.bind(this);
|
||||
this.setAvailableViews = this.setAvailableViews.bind(this);
|
||||
|
||||
for (let button of $$("toolbarbutton[data-view]", this.toolbar)) {
|
||||
button.addEventListener("command", this._onViewToggle);
|
||||
}
|
||||
|
||||
for (let [_, { view }] of Iterator(this.components)) {
|
||||
yield view.initialize();
|
||||
}
|
||||
yield this.selectView(DEFAULT_DETAILS_SUBVIEW);
|
||||
this.setAvailableViews();
|
||||
|
||||
this.selectView(DEFAULT_DETAILS_SUBVIEW);
|
||||
PerformanceController.on(EVENTS.PREF_CHANGED, this.setAvailableViews);
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -49,11 +49,34 @@ let DetailsView = {
|
|||
button.removeEventListener("command", this._onViewToggle);
|
||||
}
|
||||
|
||||
for (let [_, { view }] of Iterator(this.components)) {
|
||||
yield view.destroy();
|
||||
for (let [_, component] of Iterator(this.components)) {
|
||||
component.initialized && (yield component.view.destroy());
|
||||
}
|
||||
|
||||
PerformanceController.off(EVENTS.PREF_CHANGED, this.setAvailableViews);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets the possible views based off of prefs by hiding/showing the
|
||||
* buttons that select them and going to default view if currently selected.
|
||||
* Called when a preference changes in `devtools.performance.ui.`.
|
||||
*/
|
||||
setAvailableViews: function () {
|
||||
for (let [name, { view, pref }] of Iterator(this.components)) {
|
||||
if (!pref) {
|
||||
continue;
|
||||
}
|
||||
let value = PerformanceController.getPref(pref);
|
||||
$(`toolbarbutton[data-view=${name}]`).hidden = !value;
|
||||
|
||||
// If the view is currently selected and not enabled, go back to the
|
||||
// default view.
|
||||
if (!value && this.isViewSelected(view)) {
|
||||
this.selectView(DEFAULT_DETAILS_SUBVIEW);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Select one of the DetailView's subviews to be rendered,
|
||||
* hiding the others.
|
||||
|
@ -61,8 +84,11 @@ let DetailsView = {
|
|||
* @param String viewName
|
||||
* Name of the view to be shown.
|
||||
*/
|
||||
selectView: function (viewName) {
|
||||
this.el.selectedPanel = $("#" + this.components[viewName].id);
|
||||
selectView: Task.async(function *(viewName) {
|
||||
let component = this.components[viewName];
|
||||
this.el.selectedPanel = $("#" + component.id);
|
||||
|
||||
yield this._whenViewInitialized(component);
|
||||
|
||||
for (let button of $$("toolbarbutton[data-view]", this.toolbar)) {
|
||||
if (button.getAttribute("data-view") === viewName) {
|
||||
|
@ -73,7 +99,7 @@ let DetailsView = {
|
|||
}
|
||||
|
||||
this.emit(EVENTS.DETAILS_VIEW_SELECTED, viewName);
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
* Checks if the provided view is currently selected.
|
||||
|
@ -109,6 +135,30 @@ let DetailsView = {
|
|||
return this.whenViewSelected(viewObject);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Initializes a subview if it wasn't already set up, and makes sure
|
||||
* it's populated with recording data if there is some available.
|
||||
*
|
||||
* @param object component
|
||||
* A component descriptor from DetailsView.components
|
||||
*/
|
||||
_whenViewInitialized: Task.async(function *(component) {
|
||||
if (component.initialized) {
|
||||
return;
|
||||
}
|
||||
component.initialized = true;
|
||||
yield component.view.initialize();
|
||||
|
||||
// If this view is initialized *after* a recording is shown, it won't display
|
||||
// any data. Make sure it's populated by setting `shouldUpdateWhenShown`.
|
||||
// All detail views require a recording to be complete, so do not
|
||||
// attempt to render if recording is in progress or does not exist.
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
if (recording && !recording.isRecording()) {
|
||||
component.view.shouldUpdateWhenShown = true;
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Called when a view button is clicked.
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,7 @@ let OverviewView = {
|
|||
/**
|
||||
* Sets up the view with event binding.
|
||||
*/
|
||||
initialize: Task.async(function *() {
|
||||
initialize: function () {
|
||||
this._onRecordingWillStart = this._onRecordingWillStart.bind(this);
|
||||
this._onRecordingStarted = this._onRecordingStarted.bind(this);
|
||||
this._onRecordingWillStop = this._onRecordingWillStop.bind(this);
|
||||
|
@ -35,39 +35,25 @@ let OverviewView = {
|
|||
this._onGraphSelecting = this._onGraphSelecting.bind(this);
|
||||
this._onPrefChanged = this._onPrefChanged.bind(this);
|
||||
|
||||
yield this._showMarkersGraph();
|
||||
yield this._showMemoryGraph();
|
||||
yield this._showFramerateGraph();
|
||||
|
||||
this.markersOverview.on("selecting", this._onGraphSelecting);
|
||||
|
||||
PerformanceController.on(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
|
||||
|
||||
// Toggle the initial state of memory and framerate graph based off of
|
||||
// the prefs.
|
||||
// Toggle the initial visibility of memory and framerate graph containers
|
||||
// based off of prefs.
|
||||
$("#memory-overview").hidden = !PerformanceController.getPref("enable-memory");
|
||||
$("#time-framerate").hidden = !PerformanceController.getPref("enable-framerate");
|
||||
|
||||
PerformanceController.on(EVENTS.PREF_CHANGED, this._onPrefChanged);
|
||||
PerformanceController.on(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
|
||||
PerformanceController.on(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
|
||||
PerformanceController.on(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
||||
PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
||||
PerformanceController.on(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
|
||||
|
||||
// Populate this overview with some dummy initial data.
|
||||
this.markersOverview.setData({ duration: 1000, markers: [] });
|
||||
this.memoryOverview.setData([]);
|
||||
this.framerateGraph.setData([]);
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Unbinds events.
|
||||
*/
|
||||
destroy: function () {
|
||||
this.markersOverview.off("selecting", this._onGraphSelecting);
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
|
||||
PerformanceController.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
|
||||
PerformanceController.off(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
|
||||
PerformanceController.off(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
|
||||
PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
|
||||
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
||||
|
@ -111,43 +97,64 @@ let OverviewView = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Sets up the framerate graph.
|
||||
* Sets up the markers overivew graph, if needed.
|
||||
*
|
||||
* @return object
|
||||
* A promise resolved to `true` when the graph was initialized.
|
||||
*/
|
||||
_showFramerateGraph: Task.async(function *() {
|
||||
this.framerateGraph = new LineGraphWidget($("#time-framerate"), {
|
||||
metric: L10N.getStr("graphs.fps")
|
||||
});
|
||||
this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
|
||||
yield this.framerateGraph.ready();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets up the markers overivew graph.
|
||||
*/
|
||||
_showMarkersGraph: Task.async(function *() {
|
||||
_markersGraphAvailable: Task.async(function *() {
|
||||
if (this.markersOverview) {
|
||||
yield this.markersOverview.ready();
|
||||
return true;
|
||||
}
|
||||
this.markersOverview = new MarkersOverview($("#markers-overview"), TIMELINE_BLUEPRINT);
|
||||
this.markersOverview.headerHeight = MARKERS_GRAPH_HEADER_HEIGHT;
|
||||
this.markersOverview.rowHeight = MARKERS_GRAPH_ROW_HEIGHT;
|
||||
this.markersOverview.groupPadding = MARKERS_GROUP_VERTICAL_PADDING;
|
||||
this.markersOverview.on("selecting", this._onGraphSelecting);
|
||||
yield this.markersOverview.ready();
|
||||
return true;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets up the memory overview graph.
|
||||
* Sets up the memory overview graph, if allowed and needed.
|
||||
*
|
||||
* @return object
|
||||
* A promise resolved to `true` if the graph was initialized and is
|
||||
* ready to use, `false` if the graph is disabled.
|
||||
*/
|
||||
_showMemoryGraph: Task.async(function *() {
|
||||
_memoryGraphAvailable: Task.async(function *() {
|
||||
if (!PerformanceController.getPref("enable-memory")) {
|
||||
return false;
|
||||
}
|
||||
if (this.memoryOverview) {
|
||||
yield this.memoryOverview.ready();
|
||||
return true;
|
||||
}
|
||||
this.memoryOverview = new MemoryOverview($("#memory-overview"));
|
||||
this.memoryOverview.fixedHeight = MEMORY_GRAPH_HEIGHT;
|
||||
yield this.memoryOverview.ready();
|
||||
|
||||
CanvasGraphUtils.linkAnimation(this.markersOverview, this.memoryOverview);
|
||||
CanvasGraphUtils.linkSelection(this.markersOverview, this.memoryOverview);
|
||||
return true;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets up the framerate graph.
|
||||
* Sets up the framerate graph, if allowed and needed.
|
||||
*
|
||||
* @return object
|
||||
* A promise resolved to `true` if the graph was initialized and is
|
||||
* ready to use, `false` if the graph is disabled.
|
||||
*/
|
||||
_showFramerateGraph: Task.async(function *() {
|
||||
_framerateGraphAvailable: Task.async(function *() {
|
||||
if (!PerformanceController.getPref("enable-framerate")) {
|
||||
return false;
|
||||
}
|
||||
if (this.framerateGraph) {
|
||||
yield this.framerateGraph.ready();
|
||||
return true;
|
||||
}
|
||||
let metric = L10N.getStr("graphs.fps");
|
||||
this.framerateGraph = new LineGraphWidget($("#time-framerate"), { metric });
|
||||
this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
|
||||
|
@ -155,6 +162,7 @@ let OverviewView = {
|
|||
|
||||
CanvasGraphUtils.linkAnimation(this.markersOverview, this.framerateGraph);
|
||||
CanvasGraphUtils.linkSelection(this.markersOverview, this.framerateGraph);
|
||||
return true;
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -171,16 +179,16 @@ let OverviewView = {
|
|||
let timestamps = recording.getTicks();
|
||||
|
||||
// Empty or older recordings might yield no markers, memory or timestamps.
|
||||
if (markers) {
|
||||
if (markers && (yield this._markersGraphAvailable())) {
|
||||
this.markersOverview.setData({ markers, duration });
|
||||
this.emit(EVENTS.MARKERS_GRAPH_RENDERED);
|
||||
}
|
||||
if (memory) {
|
||||
if (memory && (yield this._memoryGraphAvailable())) {
|
||||
this.memoryOverview.dataDuration = duration;
|
||||
this.memoryOverview.setData(memory);
|
||||
this.emit(EVENTS.MEMORY_GRAPH_RENDERED);
|
||||
}
|
||||
if (timestamps) {
|
||||
if (timestamps && (yield this._framerateGraphAvailable())) {
|
||||
this.framerateGraph.dataDuration = duration;
|
||||
yield this.framerateGraph.setDataFromTimestamps(timestamps, resolution);
|
||||
this.emit(EVENTS.FRAMERATE_GRAPH_RENDERED);
|
||||
|
@ -200,13 +208,23 @@ let OverviewView = {
|
|||
this._prepareNextTick();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Called to refresh the timer to keep firing _onRecordingTick.
|
||||
*/
|
||||
_prepareNextTick: function () {
|
||||
// Check here to see if there's still a _timeoutId, incase
|
||||
// `stop` was called before the _prepareNextTick call was executed.
|
||||
if (this._timeoutId) {
|
||||
this._timeoutId = setTimeout(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired when the graph selection has changed. Called by
|
||||
* mouseup and scroll events.
|
||||
*/
|
||||
_onGraphSelecting: function () {
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
if (recording == null || this._stopSelectionChangeEventPropagation) {
|
||||
if (this._stopSelectionChangeEventPropagation) {
|
||||
return;
|
||||
}
|
||||
// If the range is smaller than a pixel (which can happen when performing
|
||||
|
@ -219,24 +237,13 @@ let OverviewView = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called to refresh the timer to keep firing _onRecordingTick.
|
||||
*/
|
||||
_prepareNextTick: function () {
|
||||
// Check here to see if there's still a _timeoutId, incase
|
||||
// `stop` was called before the _prepareNextTick call was executed.
|
||||
if (this._timeoutId) {
|
||||
this._timeoutId = setTimeout(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when recording will start.
|
||||
*/
|
||||
_onRecordingWillStart: function (_, recording) {
|
||||
this._checkSelection(recording);
|
||||
this.framerateGraph.dropSelection();
|
||||
},
|
||||
_onRecordingWillStart: Task.async(function* (_, recording) {
|
||||
yield this._checkSelection(recording);
|
||||
this.markersOverview.dropSelection();
|
||||
}),
|
||||
|
||||
/**
|
||||
* Called when recording actually starts.
|
||||
|
@ -256,40 +263,50 @@ let OverviewView = {
|
|||
/**
|
||||
* Called when recording actually stops.
|
||||
*/
|
||||
_onRecordingStopped: function (_, recording) {
|
||||
this._checkSelection(recording);
|
||||
_onRecordingStopped: Task.async(function* (_, recording) {
|
||||
this.render(FRAMERATE_GRAPH_HIGH_RES_INTERVAL);
|
||||
},
|
||||
yield this._checkSelection(recording);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Called when a new recording is selected.
|
||||
*/
|
||||
_onRecordingSelected: function (_, recording) {
|
||||
_onRecordingSelected: Task.async(function* (_, recording) {
|
||||
if (!recording) {
|
||||
return;
|
||||
}
|
||||
this.markersOverview.dropSelection();
|
||||
this._checkSelection(recording);
|
||||
|
||||
// If timeout exists, we have something recording, so
|
||||
// this will still tick away at rendering. Otherwise, force a render.
|
||||
if (!this._timeoutId) {
|
||||
this.render(FRAMERATE_GRAPH_HIGH_RES_INTERVAL);
|
||||
yield this.render(FRAMERATE_GRAPH_HIGH_RES_INTERVAL);
|
||||
}
|
||||
},
|
||||
yield this._checkSelection(recording);
|
||||
this.markersOverview.dropSelection();
|
||||
}),
|
||||
|
||||
_checkSelection: function (recording) {
|
||||
/**
|
||||
* Makes sure the selection is enabled or disabled in all the graphs,
|
||||
* based on whether a recording currently exists and is not in progress.
|
||||
*/
|
||||
_checkSelection: Task.async(function* (recording) {
|
||||
let selectionEnabled = !recording.isRecording();
|
||||
this.markersOverview.selectionEnabled = selectionEnabled;
|
||||
this.memoryOverview.selectionEnabled = selectionEnabled;
|
||||
this.framerateGraph.selectionEnabled = selectionEnabled;
|
||||
},
|
||||
|
||||
if (yield this._markersGraphAvailable()) {
|
||||
this.markersOverview.selectionEnabled = selectionEnabled;
|
||||
}
|
||||
if (yield this._memoryGraphAvailable()) {
|
||||
this.memoryOverview.selectionEnabled = selectionEnabled;
|
||||
}
|
||||
if (yield this._framerateGraphAvailable()) {
|
||||
this.framerateGraph.selectionEnabled = selectionEnabled;
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Called whenever a preference in `devtools.performance.ui.` changes. Used
|
||||
* to toggle the visibility of memory and framerate graphs.
|
||||
*/
|
||||
_onPrefChanged: function (_, prefName, value) {
|
||||
_onPrefChanged: function (_, prefName) {
|
||||
if (prefName === "enable-memory") {
|
||||
$("#memory-overview").hidden = !PerformanceController.getPref("enable-memory");
|
||||
}
|
||||
|
|
|
@ -143,10 +143,10 @@ function FlameGraph(parent, sharpness) {
|
|||
this._onResize = this._onResize.bind(this);
|
||||
this.refresh = this.refresh.bind(this);
|
||||
|
||||
container.addEventListener("mousemove", this._onMouseMove);
|
||||
container.addEventListener("mousedown", this._onMouseDown);
|
||||
container.addEventListener("mouseup", this._onMouseUp);
|
||||
container.addEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
this._window.addEventListener("mousemove", this._onMouseMove);
|
||||
this._window.addEventListener("mousedown", this._onMouseDown);
|
||||
this._window.addEventListener("mouseup", this._onMouseUp);
|
||||
this._window.addEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
|
||||
let ownerWindow = this._parent.ownerDocument.defaultView;
|
||||
ownerWindow.addEventListener("resize", this._onResize);
|
||||
|
@ -181,11 +181,10 @@ FlameGraph.prototype = {
|
|||
* Destroys this graph.
|
||||
*/
|
||||
destroy: function() {
|
||||
let container = this._container;
|
||||
container.removeEventListener("mousemove", this._onMouseMove);
|
||||
container.removeEventListener("mousedown", this._onMouseDown);
|
||||
container.removeEventListener("mouseup", this._onMouseUp);
|
||||
container.removeEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
this._window.removeEventListener("mousemove", this._onMouseMove);
|
||||
this._window.removeEventListener("mousedown", this._onMouseDown);
|
||||
this._window.removeEventListener("mouseup", this._onMouseUp);
|
||||
this._window.removeEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
|
||||
let ownerWindow = this._parent.ownerDocument.defaultView;
|
||||
ownerWindow.removeEventListener("resize", this._onResize);
|
||||
|
@ -870,6 +869,8 @@ let FlameGraphUtils = {
|
|||
* A list of { time, frames: [{ location }] } objects.
|
||||
* @param object options [optional]
|
||||
* Additional options supported by this operation:
|
||||
* - invertStack: specifies if the frames array in every sample
|
||||
* should be reversed
|
||||
* - flattenRecursion: specifies if identical consecutive frames
|
||||
* should be omitted from the output
|
||||
* - filterFrames: predicate used for filtering all frames, passing
|
||||
|
@ -917,6 +918,11 @@ let FlameGraphUtils = {
|
|||
frames = frames.filter(options.filterFrames);
|
||||
}
|
||||
|
||||
// Invert the stack if preferred, reversing the frames array in place.
|
||||
if (options.invertStack) {
|
||||
frames.reverse();
|
||||
}
|
||||
|
||||
// If no frames are available, add a pseudo "idle" block in between.
|
||||
if (options.showIdleBlocks && frames.length == 0) {
|
||||
frames = [{ location: options.showIdleBlocks || "" }];
|
||||
|
|
|
@ -191,11 +191,11 @@ this.AbstractCanvasGraph = function(parent, name, sharpness) {
|
|||
this._onResize = this._onResize.bind(this);
|
||||
this.refresh = this.refresh.bind(this);
|
||||
|
||||
container.addEventListener("mousemove", this._onMouseMove);
|
||||
container.addEventListener("mousedown", this._onMouseDown);
|
||||
container.addEventListener("mouseup", this._onMouseUp);
|
||||
container.addEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
container.addEventListener("mouseout", this._onMouseOut);
|
||||
this._window.addEventListener("mousemove", this._onMouseMove);
|
||||
this._window.addEventListener("mousedown", this._onMouseDown);
|
||||
this._window.addEventListener("mouseup", this._onMouseUp);
|
||||
this._window.addEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
this._window.addEventListener("mouseout", this._onMouseOut);
|
||||
|
||||
let ownerWindow = this._parent.ownerDocument.defaultView;
|
||||
ownerWindow.addEventListener("resize", this._onResize);
|
||||
|
@ -230,12 +230,11 @@ AbstractCanvasGraph.prototype = {
|
|||
* Destroys this graph.
|
||||
*/
|
||||
destroy: function() {
|
||||
let container = this._container;
|
||||
container.removeEventListener("mousemove", this._onMouseMove);
|
||||
container.removeEventListener("mousedown", this._onMouseDown);
|
||||
container.removeEventListener("mouseup", this._onMouseUp);
|
||||
container.removeEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
container.removeEventListener("mouseout", this._onMouseOut);
|
||||
this._window.removeEventListener("mousemove", this._onMouseMove);
|
||||
this._window.removeEventListener("mousedown", this._onMouseDown);
|
||||
this._window.removeEventListener("mouseup", this._onMouseUp);
|
||||
this._window.removeEventListener("MozMousePixelScroll", this._onMouseWheel);
|
||||
this._window.removeEventListener("mouseout", this._onMouseOut);
|
||||
|
||||
let ownerWindow = this._parent.ownerDocument.defaultView;
|
||||
ownerWindow.removeEventListener("resize", this._onResize);
|
||||
|
|
|
@ -24,3 +24,5 @@ webide.jar:
|
|||
content/devicepreferences.xhtml (devicepreferences.xhtml)
|
||||
content/devicesettings.js (devicesettings.js)
|
||||
content/devicesettings.xhtml (devicesettings.xhtml)
|
||||
content/wifi-auth.js (wifi-auth.js)
|
||||
content/wifi-auth.xhtml (wifi-auth.xhtml)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* 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 Cu = Components.utils;
|
||||
const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const { require } =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const QR = require("devtools/toolkit/qrcode/index");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
window.removeEventListener("load", onLoad);
|
||||
document.getElementById("close").onclick = () => window.close();
|
||||
document.getElementById("no-scanner").onclick = showToken;
|
||||
document.getElementById("yes-scanner").onclick = hideToken;
|
||||
buildUI();
|
||||
});
|
||||
|
||||
function buildUI() {
|
||||
let { oob } = window.arguments[0];
|
||||
createQR(oob);
|
||||
createToken(oob);
|
||||
}
|
||||
|
||||
function createQR(oob) {
|
||||
let oobData = JSON.stringify(oob);
|
||||
let imgData = QR.encodeToDataURI(oobData, "L" /* low quality */);
|
||||
document.querySelector("#qr-code img").src = imgData.src;
|
||||
}
|
||||
|
||||
function createToken(oob) {
|
||||
let token = oob.sha256.replace(/:/g, "").toLowerCase() + oob.k;
|
||||
document.querySelector("#token pre").textContent = token;
|
||||
}
|
||||
|
||||
function showToken() {
|
||||
document.querySelector("body").setAttribute("token", "true");
|
||||
}
|
||||
|
||||
function hideToken() {
|
||||
document.querySelector("body").removeAttribute("token");
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE html [
|
||||
<!ENTITY % webideDTD SYSTEM "chrome://browser/locale/devtools/webide.dtd" >
|
||||
%webideDTD;
|
||||
]>
|
||||
|
||||
<html id="devtools:wifi-auth" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf8"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/deck.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://webide/skin/wifi-auth.css" type="text/css"/>
|
||||
<script type="application/javascript;version=1.8" src="chrome://webide/content/wifi-auth.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="controls">
|
||||
<a id="close">&deck_close;</a>
|
||||
</div>
|
||||
|
||||
<h3 id="header">&wifi_auth_header;</h3>
|
||||
<div id="scan-request">&wifi_auth_scan_request;</div>
|
||||
|
||||
<div id="qr-code">
|
||||
<div id="qr-code-wrapper">
|
||||
<img/>
|
||||
</div>
|
||||
<a id="no-scanner" class="toggle-scanner">&wifi_auth_no_scanner;</a>
|
||||
</div>
|
||||
|
||||
<div id="token">
|
||||
<div>&wifi_auth_token_request;</div>
|
||||
<pre id="token-value"/>
|
||||
<a id="yes-scanner" class="toggle-scanner">&wifi_auth_yes_scanner;</a>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -365,7 +365,10 @@ let AppManager = exports.AppManager = {
|
|||
try {
|
||||
// Reset the connection's state to defaults
|
||||
this.connection.resetOptions();
|
||||
deferred.resolve(this.selectedRuntime.connect(this.connection));
|
||||
// Only watch for errors here. Final resolution occurs above, once
|
||||
// we've reached the CONNECTED state.
|
||||
this.selectedRuntime.connect(this.connection)
|
||||
.then(null, e => deferred.reject(e));
|
||||
} catch(e) {
|
||||
deferred.reject(e);
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
const {Cu, Ci} = require("chrome");
|
||||
const {Devices} = Cu.import("resource://gre/modules/devtools/Devices.jsm");
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm");
|
||||
|
@ -11,6 +11,10 @@ const {DebuggerServer} = require("resource://gre/modules/devtools/dbg-server.jsm
|
|||
const discovery = require("devtools/toolkit/discovery/discovery");
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
const promise = require("promise");
|
||||
loader.lazyRequireGetter(this, "AuthenticationResult",
|
||||
"devtools/toolkit/security/auth", true);
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils",
|
||||
"devtools/toolkit/DevToolsUtils");
|
||||
|
||||
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
|
||||
|
||||
|
@ -448,7 +452,7 @@ WiFiRuntime.prototype = {
|
|||
return promise.reject(new Error("Can't find device: " + this.name));
|
||||
}
|
||||
connection.advertisement = service;
|
||||
// TODO: Customize client authentication UX
|
||||
connection.authenticator.sendOOB = this.sendOOB;
|
||||
connection.connect();
|
||||
return promise.resolve();
|
||||
},
|
||||
|
@ -458,6 +462,81 @@ WiFiRuntime.prototype = {
|
|||
get name() {
|
||||
return this.deviceName;
|
||||
},
|
||||
|
||||
/**
|
||||
* During OOB_CERT authentication, a notification dialog like this is used to
|
||||
* to display a token which the user must transfer through some mechanism to the
|
||||
* server to authenticate the devices.
|
||||
*
|
||||
* This implementation presents the token as text for the user to transfer
|
||||
* manually. For a mobile device, you should override this implementation with
|
||||
* something more convenient, such as displaying a QR code.
|
||||
*
|
||||
* This method receives an object containing:
|
||||
* @param host string
|
||||
* The host name or IP address of the debugger server.
|
||||
* @param port number
|
||||
* The port number of the debugger server.
|
||||
* @param cert object (optional)
|
||||
* The server's cert details.
|
||||
* @param authResult AuthenticationResult
|
||||
* Authentication result sent from the server.
|
||||
* @param oob object (optional)
|
||||
* The token data to be transferred during OOB_CERT step 8:
|
||||
* * sha256: hash(ClientCert)
|
||||
* * k : K(random 128-bit number)
|
||||
* @return object containing:
|
||||
* * close: Function to hide the notification
|
||||
*/
|
||||
sendOOB(session) {
|
||||
const WINDOW_ID = "devtools:wifi-auth";
|
||||
let { authResult } = session;
|
||||
// Only show in the PENDING state
|
||||
if (authResult != AuthenticationResult.PENDING) {
|
||||
throw new Error("Expected PENDING result, got " + authResult);
|
||||
}
|
||||
|
||||
// Listen for the window our prompt opens, so we can close it programatically
|
||||
let promptWindow;
|
||||
let windowListener = {
|
||||
onOpenWindow(xulWindow) {
|
||||
let win = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
win.addEventListener("load", function listener() {
|
||||
win.removeEventListener("load", listener, false);
|
||||
if (win.document.documentElement.getAttribute("id") != WINDOW_ID) {
|
||||
return;
|
||||
}
|
||||
// Found the window
|
||||
promptWindow = win;
|
||||
Services.wm.removeListener(windowListener);
|
||||
}, false);
|
||||
},
|
||||
onCloseWindow() {},
|
||||
onWindowTitleChange() {}
|
||||
};
|
||||
Services.wm.addListener(windowListener);
|
||||
|
||||
// |openDialog| is typically a blocking API, so |executeSoon| to get around this
|
||||
DevToolsUtils.executeSoon(() => {
|
||||
let win = Services.wm.getMostRecentWindow("devtools:webide");
|
||||
let width = win.outerWidth * 0.8;
|
||||
let height = win.outerHeight * 0.5;
|
||||
win.openDialog("chrome://webide/content/wifi-auth.xhtml",
|
||||
WINDOW_ID,
|
||||
"modal=yes,width=" + width + ",height=" + height, session);
|
||||
});
|
||||
|
||||
return {
|
||||
close() {
|
||||
if (!promptWindow) {
|
||||
return;
|
||||
}
|
||||
promptWindow.close();
|
||||
promptWindow = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// For testing use only
|
||||
|
|
|
@ -16,3 +16,4 @@ webide.jar:
|
|||
skin/permissionstable.css (permissionstable.css)
|
||||
skin/monitor.css (monitor.css)
|
||||
skin/config-view.css (config-view.css)
|
||||
skin/wifi-auth.css (wifi-auth.css)
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* 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/. */
|
||||
|
||||
html, body {
|
||||
background: white;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 90%;
|
||||
}
|
||||
|
||||
div {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#qr-code {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#qr-code-wrapper {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
margin: 2em 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#qr-code img {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.toggle-scanner {
|
||||
color: #4C9ED9;
|
||||
font-size: small;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
#token {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body[token] > #token {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
body[token] > #qr-code {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#token pre,
|
||||
#token a {
|
||||
align-self: center;
|
||||
}
|
|
@ -400,6 +400,7 @@
|
|||
@RESPATH@/components/toolkitsearch.manifest
|
||||
@RESPATH@/components/nsSearchService.js
|
||||
@RESPATH@/components/nsSearchSuggestions.js
|
||||
@RESPATH@/components/nsSidebar.js
|
||||
@RESPATH@/components/passwordmgr.manifest
|
||||
@RESPATH@/components/nsLoginInfo.js
|
||||
@RESPATH@/components/nsLoginManager.js
|
||||
|
@ -419,8 +420,6 @@
|
|||
@RESPATH@/components/nsHelperAppDlg.js
|
||||
@RESPATH@/components/NetworkGeolocationProvider.manifest
|
||||
@RESPATH@/components/NetworkGeolocationProvider.js
|
||||
@RESPATH@/browser/components/nsSidebar.manifest
|
||||
@RESPATH@/browser/components/nsSidebar.js
|
||||
@RESPATH@/components/extensions.manifest
|
||||
@RESPATH@/components/addonManager.js
|
||||
@RESPATH@/components/amContentHandler.js
|
||||
|
|
|
@ -591,6 +591,11 @@ getUserMedia.sharingMenuMicrophoneWindow = %S (microphone and window)
|
|||
# origin for the sharing menu if no readable origin could be deduced from the URL.
|
||||
getUserMedia.sharingMenuUnknownHost = Unknown origin
|
||||
|
||||
# LOCALIZATION NOTE(emeNotifications.drmContentPlaying.message): %1$S is the vendor name of the DRM that's in use, %2$S is brandShortName.
|
||||
emeNotifications.drmContentPlaying.message = Some audio or video on this site uses %1$S DRM software, which may limit what %2$S can let you do with it.
|
||||
emeNotifications.drmContentPlaying.button.label = Configure…
|
||||
emeNotifications.drmContentPlaying.button.accesskey = C
|
||||
|
||||
# LOCALIZATION NOTE - %S is brandShortName
|
||||
slowStartup.message = %S seems slow… to… start.
|
||||
slowStartup.helpButton.label = Learn How to Speed It Up
|
||||
|
|
|
@ -81,6 +81,11 @@
|
|||
<!ENTITY profilerUI.invertTree "Invert Call Tree">
|
||||
<!ENTITY profilerUI.invertTree.tooltiptext "Inverting the call tree displays the profiled call paths starting from the youngest frames and expanding out to the older frames.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (profilerUI.invertFlameGraph): This is the label shown next to
|
||||
- a checkbox that inverts and un-inverts the profiler's flame graph. -->
|
||||
<!ENTITY profilerUI.invertFlameGraph "Invert Flame Chart">
|
||||
<!ENTITY profilerUI.invertFlameGraph.tooltiptext "Inverting the flame chart displays the profiled call paths starting from the youngest frames and expanding out to the older frames.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (profilerUI.showPlatformData): This is the
|
||||
- label for the checkbox that toggles whether or not Gecko platform data
|
||||
- is displayed in the profiler. -->
|
||||
|
|
|
@ -173,3 +173,21 @@
|
|||
<!-- Monitor -->
|
||||
<!ENTITY monitor_title "Monitor">
|
||||
<!ENTITY monitor_help "Help">
|
||||
|
||||
<!-- WiFi Authentication -->
|
||||
<!-- LOCALIZATION NOTE (wifi_auth_header): The header displayed on the dialog
|
||||
that instructs the user to transfer an authentication token to the
|
||||
server. -->
|
||||
<!ENTITY wifi_auth_header "Client Identification">
|
||||
<!-- LOCALIZATION NOTE (wifi_auth_scan_request): Instructions requesting the
|
||||
user to transfer authentication info by scanning a QR code. -->
|
||||
<!ENTITY wifi_auth_scan_request "The endpoint you are connecting to needs more information to authenticate this connection. Please scan the QR code below via the prompt on your other device.">
|
||||
<!-- LOCALIZATION NOTE (wifi_auth_no_scanner): Link text to assist users with
|
||||
devices that can't scan a QR code. -->
|
||||
<!ENTITY wifi_auth_no_scanner "No QR scanner prompt?">
|
||||
<!-- LOCALIZATION NOTE (wifi_auth_yes_scanner): Link text to assist users with
|
||||
devices that can scan a QR code. -->
|
||||
<!ENTITY wifi_auth_yes_scanner "Have a QR scanner prompt?">
|
||||
<!-- LOCALIZATION NOTE (wifi_auth_token_request): Instructions requesting the
|
||||
user to transfer authentication info by transferring a token. -->
|
||||
<!ENTITY wifi_auth_token_request "If your other device asks for a token instead of scanning a QR code, please copy the value below to the other device:">
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This module is for small observers that we want to register once per content
|
||||
* process, usually in order to forward content-based observer service notifications
|
||||
* to the chrome process through message passing. Using a JSM avoids having them
|
||||
* in content.js and thereby registering N observers for N open tabs, which is bad
|
||||
* for perf.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let gEMEUIObserver = function(subject, topic, data) {
|
||||
let win = subject.ownerDocument.defaultView.top;
|
||||
let mm = getMessageManagerForWindow(win);
|
||||
if (mm) {
|
||||
mm.sendAsyncMessage("EMEVideo:MetadataLoaded", {
|
||||
// bug 1129370 covers making this the actual DRM provider inferred from
|
||||
// either |subject| or |data| here.
|
||||
drmProvider: "Adobe"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function getMessageManagerForWindow(aContentWindow) {
|
||||
let ir = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDocShell)
|
||||
.sameTypeRootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
try {
|
||||
// If e10s is disabled, this throws NS_NOINTERFACE for closed tabs.
|
||||
return ir.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
} catch(e if e.result == Cr.NS_NOINTERFACE) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(gEMEUIObserver, "media-eme-metadataloaded", false);
|
|
@ -278,6 +278,17 @@ let ProcessHangMonitor = {
|
|||
return;
|
||||
}
|
||||
|
||||
// On e10s this counts slow-script/hanged-plugin notice only once.
|
||||
// This code is not reached on non-e10s.
|
||||
if (report.hangType == report.SLOW_SCRIPT) {
|
||||
// On non-e10s, SLOW_SCRIPT_NOTICE_COUNT is probed at nsGlobalWindow.cpp
|
||||
Services.telemetry.getHistogramById("SLOW_SCRIPT_NOTICE_COUNT").add();
|
||||
} else if (report.hangType == report.PLUGIN_HANG) {
|
||||
// On non-e10s we have sufficient plugin telemetry probes,
|
||||
// so PLUGIN_HANG_NOTICE_COUNT is only probed on e10s.
|
||||
Services.telemetry.getHistogramById("PLUGIN_HANG_NOTICE_COUNT").add();
|
||||
}
|
||||
|
||||
// Otherwise create a new timer and display the report.
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(this, HANG_EXPIRATION_TIME, timer.TYPE_ONE_SHOT);
|
||||
|
|
|
@ -16,6 +16,7 @@ EXTRA_JS_MODULES += [
|
|||
'Chat.jsm',
|
||||
'ContentClick.jsm',
|
||||
'ContentLinkHandler.jsm',
|
||||
'ContentObservers.jsm',
|
||||
'ContentSearch.jsm',
|
||||
'ContentWebRTC.jsm',
|
||||
'CustomizationTabPreloader.jsm',
|
||||
|
|
|
@ -2185,6 +2185,17 @@ chatbox {
|
|||
border-top-right-radius: 2.5px;
|
||||
}
|
||||
|
||||
/* EME notifications */
|
||||
|
||||
.popup-notification-icon[popupid="drmContentPlaying"],
|
||||
#eme-notification-icon {
|
||||
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains");
|
||||
}
|
||||
|
||||
#eme-notification-icon:hover:active {
|
||||
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains-pressed");
|
||||
}
|
||||
|
||||
/* Customization mode */
|
||||
|
||||
%include ../shared/customizableui/customizeMode.inc.css
|
||||
|
|
|
@ -30,6 +30,7 @@ browser.jar:
|
|||
skin/classic/browser/content-contextmenu.svg
|
||||
skin/classic/browser/dots.png (../shared/dots.png)
|
||||
skin/classic/browser/dots@2x.png (../shared/dots@2x.png)
|
||||
skin/classic/browser/drm-icon.svg (../shared/drm-icon.svg)
|
||||
* skin/classic/browser/engineManager.css
|
||||
skin/classic/browser/fullscreen-darknoise.png
|
||||
skin/classic/browser/Geolocation-16.png
|
||||
|
|
|
@ -4612,6 +4612,17 @@ window > chatbox {
|
|||
border-bottom-right-radius: @toolbarbuttonCornerRadius@;
|
||||
}
|
||||
|
||||
/* EME notifications */
|
||||
|
||||
.popup-notification-icon[popupid="drmContentPlaying"],
|
||||
#eme-notification-icon {
|
||||
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains");
|
||||
}
|
||||
|
||||
#eme-notification-icon:hover:active {
|
||||
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains-pressed");
|
||||
}
|
||||
|
||||
/* Customization mode */
|
||||
|
||||
%include ../shared/customizableui/customizeMode.inc.css
|
||||
|
|
|
@ -30,6 +30,7 @@ browser.jar:
|
|||
skin/classic/browser/content-contextmenu.svg
|
||||
skin/classic/browser/dots.png (../shared/dots.png)
|
||||
skin/classic/browser/dots@2x.png (../shared/dots@2x.png)
|
||||
skin/classic/browser/drm-icon.svg (../shared/drm-icon.svg)
|
||||
* skin/classic/browser/engineManager.css (engineManager.css)
|
||||
skin/classic/browser/fullscreen-darknoise.png
|
||||
skin/classic/browser/Geolocation-16.png
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<style>
|
||||
#chains > use > path {
|
||||
fill: url(#baseGradient);
|
||||
}
|
||||
#chains-pressed > use > path {
|
||||
fill: url(#pressedGradient);
|
||||
}
|
||||
|
||||
g:not(:target) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<defs>
|
||||
<linearGradient id="baseGradient" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="16" y2="0">
|
||||
<stop offset="0" style="stop-color:#808080"/>
|
||||
<stop offset="1" style="stop-color:#999999"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="pressedGradient" gradientUnits="userSpaceOnUse" x1="8" x2="8" y1="16" y2="0">
|
||||
<stop offset="0" style="stop-color:#4D4D4D"/>
|
||||
<stop offset="1" style="stop-color:#808080"/>
|
||||
</linearGradient>
|
||||
<path id="path1" d="M7.058,9.72c-0.245,0.245-0.62,0.27-0.834,0.056C6.01,9.562,6.035,9.186,6.28,8.942l0.218-0.218
|
||||
c-0.245-0.245-0.645-0.245-0.89,0L4.496,9.836c-0.245,0.245-0.245,0.645,0,0.89l0.779,0.779c0.245,0.245,0.645,0.245,0.89,0
|
||||
l1.112-1.112c0.245-0.245,0.245-0.645,0-0.89L7.058,9.72z"/>
|
||||
<path id="path2" d="M10.726,4.496c-0.245-0.245-0.645-0.245-0.89,0L8.723,5.608c-0.245,0.245-0.245,0.645,0,0.89
|
||||
L8.95,6.272c0.245-0.245,0.62-0.27,0.834-0.056s0.189,0.59-0.056,0.834L9.502,7.277c0.245,0.245,0.645,0.245,0.89,0l1.112-1.112
|
||||
c0.245-0.245,0.245-0.645,0-0.89L10.726,4.496z"/>
|
||||
<path id="path3" d="M8,0C3.582,0,0,3.582,0,8s3.582,8,8,8s8-3.582,8-8S12.418,0,8,0z M12.527,6.81l-1.489,1.489
|
||||
c-0.631,0.631-1.663,0.631-2.293,0L8.612,8.167L8.167,8.612l0.133,0.133c0.631,0.631,0.631,1.663,0,2.293L6.81,12.527
|
||||
c-0.631,0.631-1.663,0.631-2.293,0l-1.044-1.044c-0.631-0.631-0.631-1.663,0-2.293l1.489-1.489c0.631-0.631,1.663-0.631,2.293,0
|
||||
l0.133,0.133l0.445-0.445L7.701,7.255c-0.631-0.631-0.631-1.663,0-2.293L9.19,3.473c0.631-0.631,1.663-0.631,2.293,0l1.044,1.044
|
||||
C13.158,5.148,13.158,6.18,12.527,6.81z"/>
|
||||
</defs>
|
||||
<g id="chains">
|
||||
<use xlink:href="#path1"/>
|
||||
<use xlink:href="#path2"/>
|
||||
<use xlink:href="#path3"/>
|
||||
</g>
|
||||
<g id="chains-pressed">
|
||||
<use xlink:href="#path1"/>
|
||||
<use xlink:href="#path2"/>
|
||||
<use xlink:href="#path3"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.3 KiB |
|
@ -153,15 +153,19 @@ treecol {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#startupTable > tr > .content-cell {
|
||||
display: flex;
|
||||
#startupTable > tr > .content-cell > menulist,
|
||||
#startupTable > tr > .content-cell > textbox {
|
||||
width: calc(100% - 8px);
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#startupTable > tr > .homepage-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#startupTable > tr > td > .content-cell-item {
|
||||
#startupTable > tr > .homepage-buttons > .content-cell-item {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -2807,6 +2807,17 @@ chatbox {
|
|||
border-top-right-radius: 2.5px;
|
||||
}
|
||||
|
||||
/* EME notifications */
|
||||
|
||||
.popup-notification-icon[popupid="drmContentPlaying"],
|
||||
#eme-notification-icon {
|
||||
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains");
|
||||
}
|
||||
|
||||
#eme-notification-icon:hover:active {
|
||||
list-style-image: url("chrome://browser/skin/drm-icon.svg#chains-pressed");
|
||||
}
|
||||
|
||||
/* Customization mode */
|
||||
|
||||
%include ../shared/customizableui/customizeMode.inc.css
|
||||
|
|
|
@ -32,6 +32,7 @@ browser.jar:
|
|||
skin/classic/browser/content-contextmenu.svg
|
||||
skin/classic/browser/dots.png (../shared/dots.png)
|
||||
skin/classic/browser/dots@2x.png (../shared/dots@2x.png)
|
||||
skin/classic/browser/drm-icon.svg (../shared/drm-icon.svg)
|
||||
* skin/classic/browser/engineManager.css
|
||||
skin/classic/browser/fullscreen-darknoise.png
|
||||
skin/classic/browser/Geolocation-16.png
|
||||
|
@ -494,6 +495,7 @@ browser.jar:
|
|||
* skin/classic/aero/browser/content-contextmenu.svg
|
||||
skin/classic/aero/browser/dots.png (../shared/dots.png)
|
||||
skin/classic/aero/browser/dots@2x.png (../shared/dots@2x.png)
|
||||
skin/classic/aero/browser/drm-icon.svg (../shared/drm-icon.svg)
|
||||
* skin/classic/aero/browser/engineManager.css
|
||||
skin/classic/aero/browser/fullscreen-darknoise.png
|
||||
skin/classic/aero/browser/Geolocation-16.png
|
||||
|
|
|
@ -46,7 +46,7 @@ leak:mozilla::TransportLayerDtls::Setup
|
|||
###
|
||||
|
||||
# Bug 981195 - Small leak in the parser. m4
|
||||
leak:TypeCompartment::fixObjectGroup
|
||||
leak:ObjectGroup::fixPlainObjectGroup
|
||||
|
||||
# Bug 982111 - WebM is leaking. m1
|
||||
leak:nestegg_read_packet
|
||||
|
|
|
@ -3078,8 +3078,14 @@ nsGlobalWindow::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
|||
gEntropyCollector->RandomUpdate((void*)&(aVisitor.mEvent->time),
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
} else if (msg == NS_RESIZE_EVENT) {
|
||||
mIsHandlingResizeEvent = true;
|
||||
} else if (msg == NS_RESIZE_EVENT && aVisitor.mEvent->mFlags.mIsTrusted) {
|
||||
// QIing to window so that we can keep the old behavior also in case
|
||||
// a child window is handling resize.
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(aVisitor.mEvent->originalTarget);
|
||||
if (window) {
|
||||
mIsHandlingResizeEvent = true;
|
||||
}
|
||||
} else if (msg == NS_MOUSE_BUTTON_DOWN &&
|
||||
aVisitor.mEvent->mFlags.mIsTrusted) {
|
||||
gMouseDown = true;
|
||||
|
@ -7259,7 +7265,7 @@ nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll,
|
|||
NS_IMETHODIMP
|
||||
nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif)
|
||||
{
|
||||
ScrollBy(aXScrollDif, aYScrollDif);
|
||||
ScrollBy(double(aXScrollDif), double(aYScrollDif));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -11018,6 +11024,10 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
|||
return ContinueSlowScriptAndKeepNotifying;
|
||||
}
|
||||
|
||||
// Reached only on non-e10s - once per slow script dialog.
|
||||
// On e10s - we probe once at ProcessHangsMonitor.jsm
|
||||
Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
|
||||
|
||||
// Get the nsIPrompt interface from the docshell
|
||||
nsCOMPtr<nsIDocShell> ds = GetDocShell();
|
||||
NS_ENSURE_TRUE(ds, KillSlowScript);
|
||||
|
|
|
@ -37,7 +37,7 @@ interface nsIFrame;
|
|||
* interface to mirror this interface when changing it.
|
||||
*/
|
||||
|
||||
[scriptable, builtinclass, uuid(ce098f6c-baca-4178-a9aa-266e8bfe509b)]
|
||||
[scriptable, builtinclass, uuid(5794d12b-3195-4526-a814-a2181f6c71fe)]
|
||||
interface nsIImageLoadingContent : imgINotificationObserver
|
||||
{
|
||||
/**
|
||||
|
@ -170,9 +170,17 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
|
||||
/**
|
||||
* A visible count is stored, if it is non-zero then this image is considered
|
||||
* visible. These methods increment, decrement, or return the visible coount.
|
||||
* visible. These methods increment, decrement, or return the visible count.
|
||||
*
|
||||
* @param aNonvisibleAction What to do if the image's visibility count is now
|
||||
* zero. If ON_NONVISIBLE_NO_ACTION, nothing will be
|
||||
* done. If ON_NONVISIBLE_REQUEST_DISCARD, the image
|
||||
* will be asked to discard its surfaces if possible.
|
||||
*/
|
||||
[noscript, notxpcom] void IncrementVisibleCount();
|
||||
[noscript, notxpcom] void DecrementVisibleCount();
|
||||
[noscript, notxpcom] void DecrementVisibleCount(in uint32_t aNonvisibleAction);
|
||||
[noscript, notxpcom] uint32_t GetVisibleCount();
|
||||
|
||||
const long ON_NONVISIBLE_NO_ACTION = 0;
|
||||
const long ON_NONVISIBLE_REQUEST_DISCARD = 1;
|
||||
};
|
||||
|
|
|
@ -105,8 +105,8 @@ nsImageLoadingContent::DestroyImageLoadingContent()
|
|||
{
|
||||
// Cancel our requests so they won't hold stale refs to us
|
||||
// NB: Don't ask to discard the images here.
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, 0);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, 0);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, ON_NONVISIBLE_NO_ACTION);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, ON_NONVISIBLE_NO_ACTION);
|
||||
}
|
||||
|
||||
nsImageLoadingContent::~nsImageLoadingContent()
|
||||
|
@ -554,7 +554,7 @@ nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame)
|
|||
if (aFrame->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
|
||||
// We assume all images in popups are visible, so this decrement balances
|
||||
// out the increment in FrameCreated above.
|
||||
DecrementVisibleCount();
|
||||
DecrementVisibleCount(ON_NONVISIBLE_NO_ACTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -777,14 +777,14 @@ nsImageLoadingContent::IncrementVisibleCount()
|
|||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::DecrementVisibleCount()
|
||||
nsImageLoadingContent::DecrementVisibleCount(uint32_t aNonvisibleAction)
|
||||
{
|
||||
NS_ASSERTION(mVisibleCount > 0, "visible count should be positive here");
|
||||
mVisibleCount--;
|
||||
|
||||
if (mVisibleCount == 0) {
|
||||
UntrackImage(mCurrentRequest);
|
||||
UntrackImage(mPendingRequest);
|
||||
UntrackImage(mCurrentRequest, aNonvisibleAction);
|
||||
UntrackImage(mPendingRequest, aNonvisibleAction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1096,8 +1096,8 @@ void
|
|||
nsImageLoadingContent::CancelImageRequests(bool aNotify)
|
||||
{
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1109,8 +1109,8 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgRequestProxy* aRequest,
|
|||
AutoStateChanger changer(this, aNotify);
|
||||
|
||||
// Get rid if our existing images
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, REQUEST_DISCARD);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED, ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED, ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
|
||||
// Clone the request we were given.
|
||||
nsRefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
|
||||
|
@ -1227,7 +1227,7 @@ nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
|
|||
// reason "image source changed". However, apparently there's some abuse
|
||||
// over in nsImageFrame where the displaying of the "broken" icon for the
|
||||
// next image depends on the cancel reason of the previous image. ugh.
|
||||
ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED, REQUEST_DISCARD);
|
||||
ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED, ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
|
||||
// For the blocked case, we only want to cancel the existing current request
|
||||
// if size is not available. bz says the web depends on this behavior.
|
||||
|
@ -1235,7 +1235,7 @@ nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
|
|||
|
||||
mImageBlockingStatus = aContentDecision;
|
||||
uint32_t keepFlags = mCurrentRequestFlags & REQUEST_IS_IMAGESET;
|
||||
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED, REQUEST_DISCARD);
|
||||
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED, ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
|
||||
// We still want to remember what URI we were and if it was an imageset,
|
||||
// despite not having an actual request. These are both cleared as part of
|
||||
|
@ -1253,7 +1253,8 @@ nsImageLoadingContent::PrepareCurrentRequest(ImageLoadType aImageLoadType)
|
|||
mImageBlockingStatus = nsIContentPolicy::ACCEPT;
|
||||
|
||||
// Get rid of anything that was there previously.
|
||||
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED, REQUEST_DISCARD);
|
||||
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED,
|
||||
ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
|
||||
if (mNewRequestsWillNeedAnimationReset) {
|
||||
mCurrentRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET;
|
||||
|
@ -1271,7 +1272,8 @@ nsRefPtr<imgRequestProxy>&
|
|||
nsImageLoadingContent::PreparePendingRequest(ImageLoadType aImageLoadType)
|
||||
{
|
||||
// Get rid of anything that was there previously.
|
||||
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED, REQUEST_DISCARD);
|
||||
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED,
|
||||
ON_NONVISIBLE_REQUEST_DISCARD);
|
||||
|
||||
if (mNewRequestsWillNeedAnimationReset) {
|
||||
mPendingRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET;
|
||||
|
@ -1336,7 +1338,7 @@ nsImageLoadingContent::MakePendingRequestCurrent()
|
|||
|
||||
void
|
||||
nsImageLoadingContent::ClearCurrentRequest(nsresult aReason,
|
||||
uint32_t aFlags)
|
||||
uint32_t aNonvisibleAction)
|
||||
{
|
||||
if (!mCurrentRequest) {
|
||||
// Even if we didn't have a current request, we might have been keeping
|
||||
|
@ -1354,7 +1356,7 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason,
|
|||
&mCurrentRequestRegistered);
|
||||
|
||||
// Clean up the request.
|
||||
UntrackImage(mCurrentRequest, aFlags);
|
||||
UntrackImage(mCurrentRequest, aNonvisibleAction);
|
||||
mCurrentRequest->CancelAndForgetObserver(aReason);
|
||||
mCurrentRequest = nullptr;
|
||||
mCurrentRequestFlags = 0;
|
||||
|
@ -1362,7 +1364,7 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason,
|
|||
|
||||
void
|
||||
nsImageLoadingContent::ClearPendingRequest(nsresult aReason,
|
||||
uint32_t aFlags)
|
||||
uint32_t aNonvisibleAction)
|
||||
{
|
||||
if (!mPendingRequest)
|
||||
return;
|
||||
|
@ -1372,7 +1374,7 @@ nsImageLoadingContent::ClearPendingRequest(nsresult aReason,
|
|||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
|
||||
UntrackImage(mPendingRequest, aFlags);
|
||||
UntrackImage(mPendingRequest, aNonvisibleAction);
|
||||
mPendingRequest->CancelAndForgetObserver(aReason);
|
||||
mPendingRequest = nullptr;
|
||||
mPendingRequestFlags = 0;
|
||||
|
@ -1472,7 +1474,9 @@ nsImageLoadingContent::TrackImage(imgIRequest* aImage)
|
|||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::UntrackImage(imgIRequest* aImage, uint32_t aFlags /* = 0 */)
|
||||
nsImageLoadingContent::UntrackImage(imgIRequest* aImage,
|
||||
uint32_t aNonvisibleAction
|
||||
/* = ON_NONVISIBLE_NO_ACTION */)
|
||||
{
|
||||
if (!aImage)
|
||||
return;
|
||||
|
@ -1489,9 +1493,10 @@ nsImageLoadingContent::UntrackImage(imgIRequest* aImage, uint32_t aFlags /* = 0
|
|||
if (doc && (mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
|
||||
mCurrentRequestFlags &= ~REQUEST_IS_TRACKED;
|
||||
doc->RemoveImage(mCurrentRequest,
|
||||
(aFlags & REQUEST_DISCARD) ? nsIDocument::REQUEST_DISCARD : 0);
|
||||
}
|
||||
else if (aFlags & REQUEST_DISCARD) {
|
||||
(aNonvisibleAction == ON_NONVISIBLE_REQUEST_DISCARD)
|
||||
? nsIDocument::REQUEST_DISCARD
|
||||
: 0);
|
||||
} else if (aNonvisibleAction == ON_NONVISIBLE_REQUEST_DISCARD) {
|
||||
// If we're not in the document we may still need to be discarded.
|
||||
aImage->RequestDiscard();
|
||||
}
|
||||
|
@ -1500,9 +1505,10 @@ nsImageLoadingContent::UntrackImage(imgIRequest* aImage, uint32_t aFlags /* = 0
|
|||
if (doc && (mPendingRequestFlags & REQUEST_IS_TRACKED)) {
|
||||
mPendingRequestFlags &= ~REQUEST_IS_TRACKED;
|
||||
doc->RemoveImage(mPendingRequest,
|
||||
(aFlags & REQUEST_DISCARD) ? nsIDocument::REQUEST_DISCARD : 0);
|
||||
}
|
||||
else if (aFlags & REQUEST_DISCARD) {
|
||||
(aNonvisibleAction == ON_NONVISIBLE_REQUEST_DISCARD)
|
||||
? nsIDocument::REQUEST_DISCARD
|
||||
: 0);
|
||||
} else if (aNonvisibleAction == ON_NONVISIBLE_REQUEST_DISCARD) {
|
||||
// If we're not in the document we may still need to be discarded.
|
||||
aImage->RequestDiscard();
|
||||
}
|
||||
|
|
|
@ -316,9 +316,12 @@ protected:
|
|||
|
||||
/**
|
||||
* Cancels and nulls-out the "current" and "pending" requests if they exist.
|
||||
*
|
||||
* @param aNonvisibleAction An action to take if the image is no longer
|
||||
* visible as a result; see |UntrackImage|.
|
||||
*/
|
||||
void ClearCurrentRequest(nsresult aReason, uint32_t aFlags);
|
||||
void ClearPendingRequest(nsresult aReason, uint32_t aFlags);
|
||||
void ClearCurrentRequest(nsresult aReason, uint32_t aNonvisibleAction);
|
||||
void ClearPendingRequest(nsresult aReason, uint32_t aNonvisibleAction);
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to the 'registered with the refresh driver' flag for
|
||||
|
@ -347,14 +350,14 @@ protected:
|
|||
*
|
||||
* No-op if aImage is null.
|
||||
*
|
||||
* REQUEST_DISCARD passed to UntrackImage means we request the discard of the
|
||||
* decoded data of the image.
|
||||
* @param aNonvisibleAction What to do if the image's visibility count is now
|
||||
* zero. If ON_NONVISIBLE_NO_ACTION, nothing will be
|
||||
* done. If ON_NONVISIBLE_REQUEST_DISCARD, the image
|
||||
* will be asked to discard its surfaces if possible.
|
||||
*/
|
||||
void TrackImage(imgIRequest* aImage);
|
||||
enum {
|
||||
REQUEST_DISCARD = 0x1
|
||||
};
|
||||
void UntrackImage(imgIRequest* aImage, uint32_t aFlags = 0);
|
||||
void UntrackImage(imgIRequest* aImage,
|
||||
uint32_t aNonvisibleAction = ON_NONVISIBLE_NO_ACTION);
|
||||
|
||||
/* MEMBERS */
|
||||
nsRefPtr<imgRequestProxy> mCurrentRequest;
|
||||
|
|
|
@ -772,4 +772,6 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
|
|||
[test_window_define_nonconfigurable.html]
|
||||
skip-if = true # bug 1107443 - code for newly-added test was disabled
|
||||
[test_root_iframe.html]
|
||||
[test_performance_user_timing.html]
|
||||
[test_performance_user_timing.html]
|
||||
[test_bug1126851.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g'
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1126851
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1126851</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1126851 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTest() {
|
||||
win = window.open("about:blank", "");
|
||||
win.onload = function() {
|
||||
win.onunload = function() {
|
||||
ok(true, "got unload");
|
||||
win.close();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
win.onresize = function() {
|
||||
win.location.reload();
|
||||
}
|
||||
win.document.dispatchEvent(new win.Event("resize", { bubbles: true }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="runTest()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1126851">Mozilla Bug 1126851</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -195,13 +195,13 @@ private:
|
|||
ErrorResult& mRv;
|
||||
};
|
||||
|
||||
class PostMessageRunnable MOZ_FINAL : public nsICancelableRunnable
|
||||
class BCPostMessageRunnable MOZ_FINAL : public nsICancelableRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
PostMessageRunnable(BroadcastChannelChild* aActor,
|
||||
BroadcastChannelMessage* aData)
|
||||
BCPostMessageRunnable(BroadcastChannelChild* aActor,
|
||||
BroadcastChannelMessage* aData)
|
||||
: mActor(aActor)
|
||||
, mData(aData)
|
||||
{
|
||||
|
@ -249,13 +249,13 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
~PostMessageRunnable() {}
|
||||
~BCPostMessageRunnable() {}
|
||||
|
||||
nsRefPtr<BroadcastChannelChild> mActor;
|
||||
nsRefPtr<BroadcastChannelMessage> mData;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(PostMessageRunnable, nsICancelableRunnable, nsIRunnable)
|
||||
NS_IMPL_ISUPPORTS(BCPostMessageRunnable, nsICancelableRunnable, nsIRunnable)
|
||||
|
||||
class CloseRunnable MOZ_FINAL : public nsICancelableRunnable
|
||||
{
|
||||
|
@ -559,8 +559,8 @@ void
|
|||
BroadcastChannel::PostMessageData(BroadcastChannelMessage* aData)
|
||||
{
|
||||
if (mActor) {
|
||||
nsRefPtr<PostMessageRunnable> runnable =
|
||||
new PostMessageRunnable(mActor, aData);
|
||||
nsRefPtr<BCPostMessageRunnable> runnable =
|
||||
new BCPostMessageRunnable(mActor, aData);
|
||||
|
||||
if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
|
||||
NS_WARNING("Failed to dispatch to the current thread!");
|
||||
|
|
|
@ -8,7 +8,7 @@ EXPORTS.mozilla.dom += [
|
|||
'BroadcastChannel.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
UNIFIED_SOURCES += [
|
||||
'BroadcastChannel.cpp',
|
||||
'BroadcastChannelChild.cpp',
|
||||
'BroadcastChannelParent.cpp',
|
||||
|
|
|
@ -109,7 +109,10 @@ function test3(e) {
|
|||
numPendingChildTests++;
|
||||
|
||||
onTryAgain();
|
||||
waitForPendingTests(function() { test4(); });
|
||||
waitForPendingTests(function() {
|
||||
mm.removeMessageListener('test-try-again', onTryAgain);
|
||||
test4();
|
||||
});
|
||||
}
|
||||
|
||||
function test4() {
|
||||
|
@ -240,7 +243,10 @@ function test6f() {
|
|||
numPendingChildTests++;
|
||||
|
||||
onTryAgain();
|
||||
waitForPendingTests(test6g);
|
||||
waitForPendingTests(function() {
|
||||
mm.removeMessageListener('test-try-again', onTryAgain);
|
||||
test6g();
|
||||
});
|
||||
}
|
||||
|
||||
function test6g() {
|
||||
|
@ -269,7 +275,10 @@ function test6g() {
|
|||
numPendingChildTests++;
|
||||
|
||||
onTryAgain();
|
||||
waitForPendingTests(test6h);
|
||||
waitForPendingTests(function() {
|
||||
mm.removeMessageListener('test-try-again', onTryAgain);
|
||||
test6h();
|
||||
});
|
||||
}
|
||||
|
||||
function test6h() {
|
||||
|
|
|
@ -505,7 +505,7 @@ IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature)
|
|||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||
bool requireCompatProfile, WebGLContext* webgl)
|
||||
WebGLContext* webgl)
|
||||
{
|
||||
if (!forceEnabled &&
|
||||
IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL))
|
||||
|
@ -515,7 +515,7 @@ CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateHeadless(requireCompatProfile);
|
||||
nsRefPtr<GLContext> gl = gl::GLContextProvider::CreateHeadless();
|
||||
if (!gl) {
|
||||
webgl->GenerateWarning("Error during native OpenGL init.");
|
||||
return nullptr;
|
||||
|
@ -530,7 +530,7 @@ CreateHeadlessNativeGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
// Eventually, we want to be able to pick ANGLE-EGL or native EGL.
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||
bool requireCompatProfile, WebGLContext* webgl)
|
||||
WebGLContext* webgl)
|
||||
{
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
|
@ -543,7 +543,7 @@ CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless(requireCompatProfile);
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless();
|
||||
if (!gl) {
|
||||
webgl->GenerateWarning("Error during ANGLE OpenGL init.");
|
||||
return nullptr;
|
||||
|
@ -555,13 +555,13 @@ CreateHeadlessANGLE(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
}
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadlessEGL(bool forceEnabled, bool requireCompatProfile,
|
||||
CreateHeadlessEGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
||||
WebGLContext* webgl)
|
||||
{
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
#ifdef ANDROID
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless(requireCompatProfile);
|
||||
gl = gl::GLContextProviderEGL::CreateHeadless();
|
||||
if (!gl) {
|
||||
webgl->GenerateWarning("Error during EGL OpenGL init.");
|
||||
return nullptr;
|
||||
|
@ -583,22 +583,16 @@ CreateHeadlessGL(bool forceEnabled, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
|
|||
if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
|
||||
disableANGLE = true;
|
||||
|
||||
bool requireCompatProfile = webgl->IsWebGL2() ? false : true;
|
||||
|
||||
nsRefPtr<GLContext> gl;
|
||||
|
||||
if (preferEGL)
|
||||
gl = CreateHeadlessEGL(forceEnabled, requireCompatProfile, webgl);
|
||||
gl = CreateHeadlessEGL(forceEnabled, gfxInfo, webgl);
|
||||
|
||||
if (!gl && !disableANGLE) {
|
||||
gl = CreateHeadlessANGLE(forceEnabled, gfxInfo, requireCompatProfile,
|
||||
webgl);
|
||||
}
|
||||
if (!gl && !disableANGLE)
|
||||
gl = CreateHeadlessANGLE(forceEnabled, gfxInfo, webgl);
|
||||
|
||||
if (!gl) {
|
||||
gl = CreateHeadlessNativeGL(forceEnabled, gfxInfo,
|
||||
requireCompatProfile, webgl);
|
||||
}
|
||||
if (!gl)
|
||||
gl = CreateHeadlessNativeGL(forceEnabled, gfxInfo, webgl);
|
||||
|
||||
return gl.forget();
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче