зеркало из https://github.com/mozilla/gecko-dev.git
merge fx-team to mozilla-central a=merge
This commit is contained in:
Коммит
fc4b2033ce
|
@ -30,6 +30,7 @@ var TrackingProtection = {
|
|||
gNavigatorBundle.getString("trackingProtection.icon.disabledTooltip");
|
||||
|
||||
this.enabledHistogramAdd(this.enabledGlobally);
|
||||
this.disabledPBMHistogramAdd(!this.enabledInPrivateWindows);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
|
@ -62,6 +63,13 @@ var TrackingProtection = {
|
|||
Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED").add(value);
|
||||
},
|
||||
|
||||
disabledPBMHistogramAdd(value) {
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
return;
|
||||
}
|
||||
Services.telemetry.getHistogramById("TRACKING_PROTECTION_PBM_DISABLED").add(value);
|
||||
},
|
||||
|
||||
eventsHistogramAdd(value) {
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window)) {
|
||||
return;
|
||||
|
|
|
@ -52,7 +52,7 @@ var gGrid = {
|
|||
this._createSiteFragment();
|
||||
|
||||
gLinks.populateCache(() => {
|
||||
this.refresh();
|
||||
this._refreshGrid();
|
||||
this._ready = true;
|
||||
|
||||
// If fetching links took longer than loading the page itself then
|
||||
|
@ -108,10 +108,21 @@ var gGrid = {
|
|||
this.node.removeAttribute("locked");
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders and resizes the gird. _resizeGrid() call is needed to ensure
|
||||
* that scrollbar disappears when the bottom row becomes empty following
|
||||
* the block action, or tile display is turmed off via cog menu
|
||||
*/
|
||||
|
||||
refresh() {
|
||||
this._refreshGrid();
|
||||
this._resizeGrid();
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the grid, including cells and sites.
|
||||
*/
|
||||
refresh() {
|
||||
_refreshGrid() {
|
||||
let cell = document.createElementNS(HTML_NAMESPACE, "div");
|
||||
cell.classList.add("newtab-cell");
|
||||
|
||||
|
|
|
@ -50,13 +50,19 @@ Site.prototype = {
|
|||
/**
|
||||
* Pins the site on its current or a given index.
|
||||
* @param aIndex The pinned index (optional).
|
||||
* @return true if link changed type after pin
|
||||
*/
|
||||
pin: function Site_pin(aIndex) {
|
||||
if (typeof aIndex == "undefined")
|
||||
aIndex = this.cell.index;
|
||||
|
||||
this._updateAttributes(true);
|
||||
gPinnedLinks.pin(this._link, aIndex);
|
||||
let changed = gPinnedLinks.pin(this._link, aIndex);
|
||||
if (changed) {
|
||||
// render site again to remove suggested/sponsored tags
|
||||
this._render();
|
||||
}
|
||||
return changed;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -180,6 +186,10 @@ Site.prototype = {
|
|||
titleNode.style.backgroundColor = this.link.titleBgColor;
|
||||
}
|
||||
|
||||
// remove "suggested" attribute to avoid showing "suggested" tag
|
||||
// after site was pinned or dropped
|
||||
this.node.removeAttribute("suggested");
|
||||
|
||||
if (this.link.targetedSite) {
|
||||
if (this.node.getAttribute("type") != "sponsored") {
|
||||
this._querySelector(".newtab-sponsored").textContent =
|
||||
|
@ -370,7 +380,10 @@ Site.prototype = {
|
|||
action = "unpin";
|
||||
}
|
||||
else if (!pinned && target.classList.contains("newtab-control-pin")) {
|
||||
this.pin();
|
||||
if (this.pin()) {
|
||||
// suggested link has changed - update rest of the pages
|
||||
gAllPages.update(gPage);
|
||||
}
|
||||
action = "pin";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,11 +464,11 @@ html[dir="rtl"] .settings-menu.dropdown-menu {
|
|||
align-self: center;
|
||||
}
|
||||
|
||||
.feedback-button-container button {
|
||||
.feedback-button-container > button {
|
||||
margin: 0 30px;
|
||||
padding: .5em 2em;
|
||||
border: none;
|
||||
background: #4E92DF;
|
||||
background: #00A9DC;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill-rule="evenodd" clip-rule="evenodd" fill="#4E92DF" d="M32 0C14.3 0 0 12.6 0 28.1c0 7.7 3.6 14.7 9.3 19.8-1 3.5-3 8.3-6.9 12.9.7 1.2 11.7-3 19.4-6.1 3.2.9 6.6 1.5 10.2 1.5 17.7 0 32-12.6 32-28.1S49.7 0 32 0zm9.6 16.9c2.3 0 4.2 1.9 4.2 4.2 0 2.3-1.9 4.2-4.2 4.2-2.3 0-4.2-1.9-4.2-4.2-.1-2.3 1.8-4.2 4.2-4.2zm-19.3 0c2.3 0 4.2 1.9 4.2 4.2 0 2.3-1.9 4.2-4.2 4.2-2.3 0-4.2-1.9-4.2-4.2-.1-2.3 1.8-4.2 4.2-4.2zM32 47.7h-.1-.1c-8.6 0-18.1-5.5-20.3-14.9 5.8 2.7 13.8 3.8 20.4 3.8 6.6 0 14.7-1.2 20.4-3.8-2.2 9.3-11.7 14.9-20.3 14.9z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path fill-rule="evenodd" clip-rule="evenodd" fill="#00A9DC" d="M32 0C14.3 0 0 12.6 0 28.1c0 7.7 3.6 14.7 9.3 19.8-1 3.5-3 8.3-6.9 12.9.7 1.2 11.7-3 19.4-6.1 3.2.9 6.6 1.5 10.2 1.5 17.7 0 32-12.6 32-28.1S49.7 0 32 0zm9.6 16.9c2.3 0 4.2 1.9 4.2 4.2 0 2.3-1.9 4.2-4.2 4.2-2.3 0-4.2-1.9-4.2-4.2-.1-2.3 1.8-4.2 4.2-4.2zm-19.3 0c2.3 0 4.2 1.9 4.2 4.2 0 2.3-1.9 4.2-4.2 4.2-2.3 0-4.2-1.9-4.2-4.2-.1-2.3 1.8-4.2 4.2-4.2zM32 47.7h-.2c-8.6 0-18.1-5.5-20.3-14.9 5.8 2.7 13.8 3.8 20.4 3.8 6.6 0 14.7-1.2 20.4-3.8-2.2 9.3-11.7 14.9-20.3 14.9z"/></svg>
|
До Ширина: | Высота: | Размер: 602 B После Ширина: | Высота: | Размер: 599 B |
|
@ -38,13 +38,9 @@ loop.OTSdkDriver = (function() {
|
|||
|
||||
this.connections = {};
|
||||
|
||||
// Metrics object to keep track of the number of connections we have
|
||||
// Setup the metrics object to keep track of the number of connections we have
|
||||
// and the amount of streams.
|
||||
this._metrics = {
|
||||
connections: 0,
|
||||
sendStreams: 0,
|
||||
recvStreams: 0
|
||||
};
|
||||
this._resetMetrics();
|
||||
|
||||
this.dispatcher.register(this, [
|
||||
"setupStreamElements",
|
||||
|
@ -108,6 +104,17 @@ loop.OTSdkDriver = (function() {
|
|||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets the metrics for the driver.
|
||||
*/
|
||||
_resetMetrics: function() {
|
||||
this._metrics = {
|
||||
connections: 0,
|
||||
sendStreams: 0,
|
||||
recvStreams: 0
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the setupStreamElements action. Saves the required data and
|
||||
* kicks off the initialising of the publisher.
|
||||
|
@ -293,6 +300,9 @@ loop.OTSdkDriver = (function() {
|
|||
delete this.publisher;
|
||||
}
|
||||
|
||||
// Now reset the metrics as well.
|
||||
this._resetMetrics();
|
||||
|
||||
this._noteConnectionLengthIfNeeded(this._getTwoWayMediaStartTime(), performance.now());
|
||||
|
||||
// Also, tidy these variables ready for next time.
|
||||
|
|
|
@ -113,6 +113,19 @@ describe("loop.OTSdkDriver", function () {
|
|||
new loop.OTSdkDriver({dispatcher: dispatcher});
|
||||
}).to.Throw(/sdk/);
|
||||
});
|
||||
|
||||
it("should set the metrics to zero", function() {
|
||||
driver = new loop.OTSdkDriver({
|
||||
dispatcher: dispatcher,
|
||||
sdk: sdk
|
||||
});
|
||||
|
||||
expect(driver._metrics).eql({
|
||||
connections: 0,
|
||||
sendStreams: 0,
|
||||
recvStreams: 0
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setupStreamElements", function() {
|
||||
|
@ -474,6 +487,22 @@ describe("loop.OTSdkDriver", function () {
|
|||
expect(subscribedEvents).eql([]);
|
||||
});
|
||||
|
||||
it("should reset the metrics to zero", function() {
|
||||
driver._metrics = {
|
||||
connections: 1,
|
||||
sendStreams: 2,
|
||||
recvStreams: 3
|
||||
};
|
||||
|
||||
driver.disconnectSession();
|
||||
|
||||
expect(driver._metrics).eql({
|
||||
connections: 0,
|
||||
sendStreams: 0,
|
||||
recvStreams: 0
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch a DataChannelsAvailable action with available = false", function() {
|
||||
driver.disconnectSession();
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
|
||||
var OngoingConversationView = loop.conversationViews.OngoingConversationView;
|
||||
var DirectCallFailureView = loop.conversationViews.DirectCallFailureView;
|
||||
var DesktopRoomEditContextView = loop.roomViews.DesktopRoomEditContextView;
|
||||
var RoomFailureView = loop.roomViews.RoomFailureView;
|
||||
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
|
||||
|
||||
|
@ -1395,6 +1396,23 @@
|
|||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {height: 278.6,
|
||||
onContentsRendered: invitationRoomStore.activeRoomStore.forcedUpdate,
|
||||
summary: "Desktop room Edit Context w/Error",
|
||||
width: 298},
|
||||
React.createElement("div", {className: "fx-embedded room-invitation-overlay"},
|
||||
React.createElement(DesktopRoomEditContextView, {
|
||||
dispatcher: dispatcher,
|
||||
error: {},
|
||||
mozLoop: navigator.mozLoop,
|
||||
onClose: function(){},
|
||||
roomData: {},
|
||||
savingContext: false,
|
||||
show: true}
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {dashed: true,
|
||||
height: 394,
|
||||
onContentsRendered: desktopRoomStoreLoading.activeRoomStore.forcedUpdate,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
|
||||
var OngoingConversationView = loop.conversationViews.OngoingConversationView;
|
||||
var DirectCallFailureView = loop.conversationViews.DirectCallFailureView;
|
||||
var DesktopRoomEditContextView = loop.roomViews.DesktopRoomEditContextView;
|
||||
var RoomFailureView = loop.roomViews.RoomFailureView;
|
||||
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
|
||||
|
||||
|
@ -1395,6 +1396,23 @@
|
|||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample height={278.6}
|
||||
onContentsRendered={invitationRoomStore.activeRoomStore.forcedUpdate}
|
||||
summary="Desktop room Edit Context w/Error"
|
||||
width={298}>
|
||||
<div className="fx-embedded room-invitation-overlay">
|
||||
<DesktopRoomEditContextView
|
||||
dispatcher={dispatcher}
|
||||
error={{}}
|
||||
mozLoop={navigator.mozLoop}
|
||||
onClose={function(){}}
|
||||
roomData={{}}
|
||||
savingContext={false}
|
||||
show={true}
|
||||
/>
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample dashed={true}
|
||||
height={394}
|
||||
onContentsRendered={desktopRoomStoreLoading.activeRoomStore.forcedUpdate}
|
||||
|
|
|
@ -9,6 +9,7 @@ var gContentWindow;
|
|||
|
||||
function test() {
|
||||
UITourTest();
|
||||
requestLongerTimeout(2);
|
||||
}
|
||||
|
||||
function getHeartbeatNotification(aId, aChromeWindow = window) {
|
||||
|
|
|
@ -251,6 +251,7 @@ function UITourTest() {
|
|||
});
|
||||
|
||||
function done() {
|
||||
info("== Done test, doing shared checks before teardown ==");
|
||||
executeSoon(() => {
|
||||
if (gTestTab)
|
||||
gBrowser.removeTab(gTestTab);
|
||||
|
@ -267,12 +268,14 @@ function UITourTest() {
|
|||
isnot(PanelUI.panel.state, "open", "The panel shouldn't be open");
|
||||
is(document.getElementById("PanelUI-menu-button").hasAttribute("open"), false, "Menu button should know that the menu is closed");
|
||||
|
||||
info("Done shared checks");
|
||||
executeSoon(nextTest);
|
||||
});
|
||||
}
|
||||
|
||||
function nextTest() {
|
||||
if (tests.length == 0) {
|
||||
info("finished tests in this file");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,12 @@
|
|||
<!ENTITY performanceUI.bufferStatusFull "The buffer is full. Older samples are now being overwritten.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (performanceUI.loadingNotice): This is the label shown
|
||||
- in the call list view while loading a profile. -->
|
||||
- in the details view while the profiler is unavailable, for example, while
|
||||
- in Private Browsing mode. -->
|
||||
<!ENTITY performanceUI.unavailableNoticePB "Recording a profile is currently unavailable. Please close all private browsing windows and try again.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (performanceUI.loadingNotice): This is the label shown
|
||||
- in the details view while loading a profile. -->
|
||||
<!ENTITY performanceUI.loadingNotice "Loading…">
|
||||
|
||||
<!-- LOCALIZATION NOTE (performanceUI.recordButton): This string is displayed
|
||||
|
|
|
@ -437,9 +437,6 @@
|
|||
currentColor calc(100% - 4px),
|
||||
transparent calc(100% - 4px));
|
||||
opacity: 0.2;
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#TabsToolbar[brighttext] > #tabbrowser-tabs > .tabbrowser-tab::before,
|
||||
|
@ -451,7 +448,8 @@
|
|||
#tabbrowser-tabs[movingtab] > .tabbrowser-tab[beforeselected]:not([last-visible-tab])::after,
|
||||
.tabbrowser-tab:not([visuallyselected]):not([afterselected-visible]):not([afterhovered]):not([first-visible-tab]):not(:hover)::before,
|
||||
#tabbrowser-tabs:not([overflow]) > .tabbrowser-tab[last-visible-tab]:not([visuallyselected]):not([beforehovered]):not(:hover)::after {
|
||||
visibility: visible;
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
/* New tab button */
|
||||
|
|
|
@ -317,10 +317,28 @@ TabTarget.prototype = {
|
|||
return this._form;
|
||||
},
|
||||
|
||||
// Get a promise of the root form returned by a listTabs request. This promise
|
||||
// is cached.
|
||||
get root() {
|
||||
if (!this._root) {
|
||||
this._root = this._getRoot();
|
||||
}
|
||||
return this._root;
|
||||
},
|
||||
|
||||
_getRoot: function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client.listTabs(response => {
|
||||
if (response.error) {
|
||||
reject(new Error(response.error + ": " + response.message));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(response);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
get client() {
|
||||
return this._client;
|
||||
},
|
||||
|
|
|
@ -3,12 +3,21 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// This shared-head.js file is used for multiple directories in devtools.
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
const {gDevTools} = Cu.import("resource:///modules/devtools/client/framework/gDevTools.jsm", {});
|
||||
const {console} = Cu.import("resource://gre/modules/devtools/shared/Console.jsm", {});
|
||||
const {ScratchpadManager} = Cu.import("resource:///modules/devtools/client/scratchpad/scratchpad-manager.jsm", {});
|
||||
const {require} = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
|
||||
function scopedCuImport(path) {
|
||||
const scope = {};
|
||||
Cu.import(path, scope);
|
||||
return scope;
|
||||
}
|
||||
|
||||
const {Services} = scopedCuImport("resource://gre/modules/Services.jsm");
|
||||
const {gDevTools} = scopedCuImport("resource:///modules/devtools/client/framework/gDevTools.jsm");
|
||||
const {console} = scopedCuImport("resource://gre/modules/devtools/shared/Console.jsm");
|
||||
const {ScratchpadManager} = scopedCuImport("resource:///modules/devtools/client/scratchpad/scratchpad-manager.jsm");
|
||||
const {require} = scopedCuImport("resource://gre/modules/devtools/shared/Loader.jsm");
|
||||
|
||||
const {TargetFactory} = require("devtools/client/framework/target");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const promise = require("promise");
|
||||
|
@ -69,6 +78,25 @@ function addTab(url) {
|
|||
return def.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given tab.
|
||||
* @param {Object} tab The tab to be removed.
|
||||
* @return Promise<undefined> resolved when the tab is successfully removed.
|
||||
*/
|
||||
function removeTab(tab) {
|
||||
info("Removing tab.");
|
||||
return new Promise(resolve => {
|
||||
let tabContainer = gBrowser.tabContainer;
|
||||
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
|
||||
tabContainer.removeEventListener("TabClose", onClose, false);
|
||||
info("Tab removed and finished closing.");
|
||||
resolve();
|
||||
}, false);
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function synthesizeKeyFromKeyTag(aKeyId, document) {
|
||||
let key = document.getElementById(aKeyId);
|
||||
isnot(key, null, "Successfully retrieved the <key> node");
|
||||
|
|
|
@ -39,32 +39,32 @@ devtools.jar:
|
|||
content/animationinspector/animation-controller.js (animationinspector/animation-controller.js)
|
||||
content/animationinspector/animation-panel.js (animationinspector/animation-panel.js)
|
||||
content/animationinspector/animation-inspector.xhtml (animationinspector/animation-inspector.xhtml)
|
||||
content/sourceeditor/codemirror/codemirror.js (sourceeditor/codemirror/codemirror.js)
|
||||
content/sourceeditor/codemirror/codemirror.css (sourceeditor/codemirror/codemirror.css)
|
||||
content/sourceeditor/codemirror/comment/comment.js (sourceeditor/codemirror/addon/comment/comment.js)
|
||||
content/sourceeditor/codemirror/edit/trailingspace.js (sourceeditor/codemirror/addon/edit/trailingspace.js)
|
||||
content/sourceeditor/codemirror/edit/matchbrackets.js (sourceeditor/codemirror/addon/edit/matchbrackets.js)
|
||||
content/sourceeditor/codemirror/edit/closebrackets.js (sourceeditor/codemirror/addon/edit/closebrackets.js)
|
||||
content/sourceeditor/codemirror/dialog/dialog.js (sourceeditor/codemirror/addon/dialog/dialog.js)
|
||||
content/sourceeditor/codemirror/dialog/dialog.css (sourceeditor/codemirror/addon/dialog/dialog.css)
|
||||
content/sourceeditor/codemirror/fold/foldcode.js (sourceeditor/codemirror/addon/fold/foldcode.js)
|
||||
content/sourceeditor/codemirror/fold/brace-fold.js (sourceeditor/codemirror/addon/fold/brace-fold.js)
|
||||
content/sourceeditor/codemirror/fold/comment-fold.js (sourceeditor/codemirror/addon/fold/comment-fold.js)
|
||||
content/sourceeditor/codemirror/fold/xml-fold.js (sourceeditor/codemirror/addon/fold/xml-fold.js)
|
||||
content/sourceeditor/codemirror/fold/foldgutter.js (sourceeditor/codemirror/addon/fold/foldgutter.js)
|
||||
content/sourceeditor/codemirror/hint/show-hint.js (sourceeditor/codemirror/addon/hint/show-hint.js)
|
||||
content/sourceeditor/codemirror/search/search.js (sourceeditor/codemirror/addon/search/search.js)
|
||||
content/sourceeditor/codemirror/search/searchcursor.js (sourceeditor/codemirror/addon/search/searchcursor.js)
|
||||
content/sourceeditor/codemirror/selection/active-line.js (sourceeditor/codemirror/addon/selection/active-line.js)
|
||||
content/sourceeditor/codemirror/tern/tern.js (sourceeditor/codemirror/addon/tern/tern.js)
|
||||
content/sourceeditor/codemirror/codemirror.js (sourceeditor/codemirror/lib/codemirror.js)
|
||||
content/sourceeditor/codemirror/codemirror.css (sourceeditor/codemirror/lib/codemirror.css)
|
||||
content/sourceeditor/codemirror/mode/javascript.js (sourceeditor/codemirror/mode/javascript.js)
|
||||
content/sourceeditor/codemirror/mode/xml.js (sourceeditor/codemirror/mode/xml.js)
|
||||
content/sourceeditor/codemirror/mode/css.js (sourceeditor/codemirror/mode/css.js)
|
||||
content/sourceeditor/codemirror/mode/htmlmixed.js (sourceeditor/codemirror/mode/htmlmixed.js)
|
||||
content/sourceeditor/codemirror/mode/clike.js (sourceeditor/codemirror/mode/clike.js)
|
||||
content/sourceeditor/codemirror/selection/active-line.js (sourceeditor/codemirror/selection/active-line.js)
|
||||
content/sourceeditor/codemirror/edit/trailingspace.js (sourceeditor/codemirror/edit/trailingspace.js)
|
||||
content/sourceeditor/codemirror/edit/matchbrackets.js (sourceeditor/codemirror/edit/matchbrackets.js)
|
||||
content/sourceeditor/codemirror/edit/closebrackets.js (sourceeditor/codemirror/edit/closebrackets.js)
|
||||
content/sourceeditor/codemirror/comment/comment.js (sourceeditor/codemirror/comment/comment.js)
|
||||
content/sourceeditor/codemirror/search/searchcursor.js (sourceeditor/codemirror/search/searchcursor.js)
|
||||
content/sourceeditor/codemirror/search/search.js (sourceeditor/codemirror/search/search.js)
|
||||
content/sourceeditor/codemirror/dialog/dialog.js (sourceeditor/codemirror/dialog/dialog.js)
|
||||
content/sourceeditor/codemirror/dialog/dialog.css (sourceeditor/codemirror/dialog/dialog.css)
|
||||
content/sourceeditor/codemirror/keymap/emacs.js (sourceeditor/codemirror/keymap/emacs.js)
|
||||
content/sourceeditor/codemirror/keymap/sublime.js (sourceeditor/codemirror/keymap/sublime.js)
|
||||
content/sourceeditor/codemirror/keymap/vim.js (sourceeditor/codemirror/keymap/vim.js)
|
||||
content/sourceeditor/codemirror/fold/foldcode.js (sourceeditor/codemirror/fold/foldcode.js)
|
||||
content/sourceeditor/codemirror/fold/brace-fold.js (sourceeditor/codemirror/fold/brace-fold.js)
|
||||
content/sourceeditor/codemirror/fold/comment-fold.js (sourceeditor/codemirror/fold/comment-fold.js)
|
||||
content/sourceeditor/codemirror/fold/xml-fold.js (sourceeditor/codemirror/fold/xml-fold.js)
|
||||
content/sourceeditor/codemirror/fold/foldgutter.js (sourceeditor/codemirror/fold/foldgutter.js)
|
||||
content/sourceeditor/codemirror/tern/tern.js (sourceeditor/codemirror/tern/tern.js)
|
||||
content/sourceeditor/codemirror/hint/show-hint.js (sourceeditor/codemirror/hint/show-hint.js)
|
||||
content/sourceeditor/codemirror/mozilla.css (sourceeditor/codemirror/mozilla.css)
|
||||
content/debugger/debugger.xul (debugger/debugger.xul)
|
||||
content/debugger/debugger.css (debugger/debugger.css)
|
||||
|
@ -111,7 +111,7 @@ devtools.jar:
|
|||
content/performance/views/optimizations-list.js (performance/views/optimizations-list.js)
|
||||
content/performance/views/recordings.js (performance/views/recordings.js)
|
||||
content/memory/memory.xhtml (memory/memory.xhtml)
|
||||
content/memory/controller.js (memory/controller.js)
|
||||
content/memory/initializer.js (memory/initializer.js)
|
||||
content/promisedebugger/promise-controller.js (promisedebugger/promise-controller.js)
|
||||
content/promisedebugger/promise-panel.js (promisedebugger/promise-panel.js)
|
||||
content/promisedebugger/promise-debugger.xhtml (promisedebugger/promise-debugger.xhtml)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# 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/.
|
||||
|
||||
general=General Notification
|
||||
DevToolsModules(
|
||||
'snapshot.js',
|
||||
)
|
|
@ -0,0 +1,14 @@
|
|||
/* 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 { PROMISE } = require("devtools/client/shared/redux/middleware/promise");
|
||||
const { actions } = require("../constants");
|
||||
|
||||
const takeSnapshot = exports.takeSnapshot = function takeSnapshot (front) {
|
||||
return {
|
||||
type: actions.TAKE_SNAPSHOT,
|
||||
[PROMISE]: front.saveHeapSnapshot()
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
/* 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 actions = exports.actions = {};
|
||||
|
||||
// Fired by UI to request a snapshot from the actor.
|
||||
actions.TAKE_SNAPSHOT = "take-snapshot";
|
|
@ -3,26 +3,26 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
const { loader, require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
const { Heritage, ViewHelpers, WidgetMethods } = require("resource:///modules/devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
const Store = require("./store");
|
||||
|
||||
/**
|
||||
* The current target, toolbox and MemoryFront, set by this tool's host.
|
||||
*/
|
||||
var gToolbox, gTarget, gFront;
|
||||
|
||||
/**
|
||||
* Initializes the profiler controller and views.
|
||||
*/
|
||||
const MemoryController = {
|
||||
initialize: Task.async(function *() {
|
||||
const REDUX_METHODS_TO_PIPE = ["dispatch", "subscribe", "getState"];
|
||||
|
||||
}),
|
||||
|
||||
destroy: Task.async(function *() {
|
||||
|
||||
})
|
||||
const MemoryController = exports.MemoryController = function ({ toolbox, target, front }) {
|
||||
this.store = Store();
|
||||
this.toolbox = toolbox;
|
||||
this.target = target;
|
||||
this.front = front;
|
||||
};
|
||||
|
||||
REDUX_METHODS_TO_PIPE.map(m =>
|
||||
MemoryController.prototype[m] = function (...args) { return this.store[m](...args); });
|
||||
|
||||
MemoryController.prototype.destroy = function () {
|
||||
this.store = this.toolbox = this.target = this.front = null;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* 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 { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
const { require } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
const { MemoryController } = require("devtools/client/memory/controller");
|
||||
|
||||
/**
|
||||
* The current target, toolbox and MemoryFront, set by this tool's host.
|
||||
*/
|
||||
let gToolbox, gTarget, gFront;
|
||||
|
||||
/**
|
||||
* Initializes the profiler controller and views.
|
||||
*/
|
||||
var controller = null;
|
||||
function initialize () {
|
||||
return Task.spawn(function *() {
|
||||
controller = new MemoryController({ toolbox: gToolbox, target: gTarget, front: gFront });
|
||||
});
|
||||
}
|
||||
|
||||
function destroy () {
|
||||
return Task.spawn(function *() {
|
||||
controller.destroy();
|
||||
});
|
||||
}
|
|
@ -12,23 +12,21 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/themes/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/themes/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/themes/memory.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/content/devtools/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/common.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/widgets.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/devtools/memory.css" type="text/css"/>
|
||||
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="controller.js"></script>
|
||||
src="initializer.js"></script>
|
||||
</head>
|
||||
<body class="theme-body">
|
||||
<toolbar class="devtools-toolbar">
|
||||
<toolbarbutton id="snapshot-button" class="devtools-toolbarbutton"
|
||||
tabindex="0"/>
|
||||
<spacer flex="1"></spacer>
|
||||
</toolbar>
|
||||
<splitter class="devtools-horizontal-splitter"/>
|
||||
<div class="devtools-toolbar">
|
||||
<div id="snapshot-button" class="devtools-toolbarbutton" />
|
||||
</div>
|
||||
<div class="devtools-horizontal-splitter"></div>
|
||||
<div id="memory-content"
|
||||
class="devtools-responsive-container"
|
||||
flex="1">
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
*/
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const { L10N } = require("devtools/client/performance/modules/global");
|
||||
const { Heritage } = require("resource:///modules/devtools/client/shared/widgets/ViewHelpers.jsm");
|
||||
const { AbstractTreeItem } = require("resource:///modules/devtools/client/shared/widgets/AbstractTreeItem.jsm");
|
||||
|
||||
|
|
|
@ -4,11 +4,19 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'actions',
|
||||
'modules',
|
||||
'reducers',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'constants.js',
|
||||
'controller.js',
|
||||
'initializer.js',
|
||||
'panel.js',
|
||||
'reducers.js',
|
||||
'store.js',
|
||||
)
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
|
|
|
@ -26,14 +26,19 @@ MemoryPanel.prototype = {
|
|||
|
||||
this.panelWin.gToolbox = this._toolbox;
|
||||
this.panelWin.gTarget = this.target;
|
||||
this.panelWin.gFront = new MemoryFront(this.target.client, this.target.form);
|
||||
|
||||
console.log(this.panelWin, this.panelWin.MemoryController);
|
||||
return this._opening = this.panelWin.MemoryController.initialize().then(() => {
|
||||
const rootForm = yield this.target.root;
|
||||
this.panelWin.gFront = new MemoryFront(this.target.client,
|
||||
this.target.form,
|
||||
rootForm);
|
||||
|
||||
yield this.panelWin.gFront.attach();
|
||||
return this._opening = this.panelWin.initialize().then(() => {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
});
|
||||
return this._opening;
|
||||
}),
|
||||
|
||||
// DevToolPanel API
|
||||
|
@ -42,19 +47,21 @@ MemoryPanel.prototype = {
|
|||
return this._toolbox.target;
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
destroy: Task.async(function *() {
|
||||
// Make sure this panel is not already destroyed.
|
||||
if (this._destroyer) {
|
||||
return this._destroyer;
|
||||
}
|
||||
|
||||
return this._destroyer = this.panelWin.MemoryController.destroy().then(() => {
|
||||
yield this.panelWin.gFront.detach();
|
||||
return this._destroyer = this.panelWin.destroy().then(() => {
|
||||
// Destroy front to ensure packet handler is removed from client
|
||||
this.panelWin.gFront.destroy();
|
||||
this.panelWin = null;
|
||||
this.emit("destroyed");
|
||||
return this;
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
exports.MemoryPanel = MemoryPanel;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
exports.snapshots = require("./reducers/snapshot");
|
|
@ -0,0 +1,8 @@
|
|||
# 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/.
|
||||
|
||||
DevToolsModules(
|
||||
'snapshot.js',
|
||||
)
|
|
@ -0,0 +1,37 @@
|
|||
const { actions } = require("../constants");
|
||||
const { PROMISE } = require("devtools/client/shared/redux/middleware/promise");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
function handleTakeSnapshot (state, action) {
|
||||
switch (action.status) {
|
||||
|
||||
case "start":
|
||||
return [...state, {
|
||||
id: action.seqId,
|
||||
status: action.status
|
||||
}];
|
||||
|
||||
case "done":
|
||||
let snapshot = state.find(s => s.id === action.seqId);
|
||||
if (!snapshot) {
|
||||
DevToolsUtils.reportException(`No snapshot with id "${action.seqId}" for TAKE_SNAPSHOT`);
|
||||
break;
|
||||
}
|
||||
snapshot.status = "done";
|
||||
snapshot.snapshotId = action.value;
|
||||
return [...state];
|
||||
|
||||
case "error":
|
||||
DevToolsUtils.reportException(`No async state found for ${action.type}`);
|
||||
}
|
||||
return [...state];
|
||||
}
|
||||
|
||||
module.exports = function (state=[], action) {
|
||||
switch (action.type) {
|
||||
case actions.TAKE_SNAPSHOT:
|
||||
return handleTakeSnapshot(state, action);
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
const { combineReducers } = require("../shared/vendor/redux");
|
||||
const createStore = require("../shared/redux/create-store");
|
||||
const reducers = require("./reducers");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
|
||||
module.exports = function () {
|
||||
return createStore({ log: DevToolsUtils.testing })(combineReducers(reducers), {});
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_memory_transferHeapSnapshot_e10s_01.js]
|
|
@ -0,0 +1,28 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that we can save a heap snapshot and transfer it over the RDP in e10s
|
||||
// where the child process is sandboxed and so we have to use
|
||||
// HeapSnapshotFileActor to get the heap snapshot file.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URL = "data:text/html,<html><body></body></html>";
|
||||
|
||||
this.test = makeMemoryTest(TEST_URL, function* ({ tab, panel }) {
|
||||
const memoryFront = panel.panelWin.gFront;
|
||||
ok(memoryFront, "Should get the MemoryFront");
|
||||
|
||||
const snapshotFilePath = yield memoryFront.saveHeapSnapshot({
|
||||
// Force a copy so that we go through the HeapSnapshotFileActor's
|
||||
// transferHeapSnapshot request and exercise this code path on e10s.
|
||||
forceCopy: true
|
||||
});
|
||||
|
||||
ok(!!(yield OS.File.stat(snapshotFilePath)),
|
||||
"Should have the heap snapshot file");
|
||||
|
||||
const snapshot = ChromeUtils.readHeapSnapshot(snapshotFilePath);
|
||||
ok(snapshot instanceof HeapSnapshot,
|
||||
"And we should be able to read a HeapSnapshot instance from the file");
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Load the shared test helpers into this compartment.
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
|
||||
this);
|
||||
|
||||
Services.prefs.setBoolPref("devtools.memory.enabled", true);
|
||||
|
||||
/**
|
||||
* Open the memory panel for the given tab.
|
||||
*/
|
||||
this.openMemoryPanel = Task.async(function* (tab) {
|
||||
info("Opening memory panel.");
|
||||
const target = TargetFactory.forTab(tab);
|
||||
const toolbox = yield gDevTools.showToolbox(target, "memory");
|
||||
info("Memory panel shown successfully.");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
return { tab, panel };
|
||||
});
|
||||
|
||||
/**
|
||||
* Close the memory panel for the given tab.
|
||||
*/
|
||||
this.closeMemoryPanel = Task.async(function* (tab) {
|
||||
info("Closing memory panel.");
|
||||
const target = TargetFactory.forTab(tab);
|
||||
const toolbox = gDevTools.getToolbox(target);
|
||||
yield toolbox.destroy();
|
||||
info("Closed memory panel successfully.");
|
||||
});
|
||||
|
||||
/**
|
||||
* Return a test function that adds a tab with the given url, opens the memory
|
||||
* panel, runs the given generator, closes the memory panel, removes the tab,
|
||||
* and finishes.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* this.test = makeMemoryTest(TEST_URL, function* ({ tab, panel }) {
|
||||
* // Your tests go here...
|
||||
* });
|
||||
*/
|
||||
function makeMemoryTest(url, generator) {
|
||||
return Task.async(function* () {
|
||||
waitForExplicitFinish();
|
||||
|
||||
const tab = yield addTab(url);
|
||||
const results = yield openMemoryPanel(tab);
|
||||
|
||||
try {
|
||||
yield* generator(results);
|
||||
} catch (err) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(err));
|
||||
}
|
||||
|
||||
yield closeMemoryPanel(tab);
|
||||
yield removeTab(tab);
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
|
@ -9,4 +9,4 @@ const Cu = Components.utils;
|
|||
const Cr = Components.results;
|
||||
const CC = Components.Constructor;
|
||||
|
||||
const { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
const { require } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
|
|
|
@ -7,11 +7,11 @@ Bug 1067491 - Test taking a census over the RDP.
|
|||
<meta charset="utf-8">
|
||||
<title>Census Tree 01</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link href="chrome://devtools/content/shared/widgets/widgets.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/light-theme.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/common.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/widgets.css" type="text/css" />
|
||||
<link href="chrome://devtools/skin/themes/memory.css" type="text/css" />
|
||||
<link href="chrome://browser/content/devtools/widgets.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/light-theme.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/common.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/widgets.css" type="text/css" />
|
||||
<link href="chrome://browser/skin/devtools/memory.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<ul id="container" style="width:100%;height:300px;"></ul>
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
var { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
var { gDevTools } = Cu.import("resource:///modules/devtools/client/framework/gDevTools.jsm", {});
|
||||
var { console } = Cu.import("resource://gre/modules/devtools/shared/Console.jsm", {});
|
||||
var { require } = Cu.import("resource://gre/modules/devtools/shared/Loader.jsm", {});
|
||||
var { TargetFactory } = require("devtools/client/framework/target");
|
||||
var DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
var promise = require("promise");
|
||||
var { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
var { MemoryController } = require("devtools/client/memory/controller");
|
||||
var { expectState } = require("devtools/server/actors/common");
|
||||
var HeapSnapshotFileUtils = require("devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
var { addDebuggerToGlobal } = require("resource://gre/modules/jsdebugger.jsm");
|
||||
var SYSTEM_PRINCIPAL = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
|
||||
var { setTimeout } = require("sdk/timers");
|
||||
|
||||
DevToolsUtils.testing = true;
|
||||
|
||||
function initDebugger () {
|
||||
let global = new Cu.Sandbox(SYSTEM_PRINCIPAL, { freshZone: true });
|
||||
addDebuggerToGlobal(global);
|
||||
return new global.Debugger();
|
||||
}
|
||||
|
||||
function StubbedMemoryFront () {
|
||||
this.dbg = initDebugger();
|
||||
}
|
||||
|
||||
StubbedMemoryFront.prototype.attach = Task.async(function *() {
|
||||
this.state = "attached";
|
||||
});
|
||||
|
||||
StubbedMemoryFront.prototype.detach = Task.async(function *() {
|
||||
this.state = "detached";
|
||||
});
|
||||
|
||||
StubbedMemoryFront.prototype.saveHeapSnapshot = expectState("attached", Task.async(function *() {
|
||||
let path = ThreadSafeChromeUtils.saveHeapSnapshot({ debugger: this.dbg });
|
||||
return HeapSnapshotFileUtils.getSnapshotIdFromPath(path);
|
||||
}), "saveHeapSnapshot");
|
||||
|
||||
function waitUntilState (store, predicate) {
|
||||
let deferred = promise.defer();
|
||||
let unsubscribe = store.subscribe(() => {
|
||||
if (predicate(store.getState())) {
|
||||
unsubscribe();
|
||||
deferred.resolve()
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests the async action creator `takeSnapshot(front)`
|
||||
*/
|
||||
|
||||
let actions = require("devtools/client/memory/actions/snapshot");
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_task(function *() {
|
||||
let front = new StubbedMemoryFront();
|
||||
yield front.attach();
|
||||
let controller = new MemoryController({ toolbox: {}, target: {}, front });
|
||||
|
||||
let unsubscribe = controller.subscribe(checkState);
|
||||
|
||||
let foundPendingState = false;
|
||||
let foundDoneState = false;
|
||||
|
||||
function checkState () {
|
||||
let state = controller.getState();
|
||||
if (state.snapshots.length === 1 && state.snapshots[0].status === "start") {
|
||||
foundPendingState = true;
|
||||
ok(foundPendingState, "Got state change for pending heap snapshot request");
|
||||
ok(!(state.snapshots[0].snapshotId), "Snapshot does not yet have a snapshotId");
|
||||
}
|
||||
if (state.snapshots.length === 1 && state.snapshots[0].status === "done") {
|
||||
foundDoneState = true;
|
||||
ok(foundDoneState, "Got state change for completed heap snapshot request");
|
||||
ok(state.snapshots[0].snapshotId, "Snapshot fetched with a snapshotId");
|
||||
}
|
||||
if (state.snapshots.lenght === 1 && state.snapshots[0].status === "error") {
|
||||
ok(false, "takeSnapshot's promise returned with an error");
|
||||
}
|
||||
}
|
||||
|
||||
controller.dispatch(actions.takeSnapshot(front));
|
||||
yield waitUntilState(controller, () => foundPendingState && foundDoneState);
|
||||
|
||||
unsubscribe();
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
head = head.js
|
||||
tail =
|
||||
firefox-appdir = browser
|
||||
skip-if = toolkit == 'android' || toolkit == 'gonk'
|
||||
|
||||
[test_action-take-snapshot.js]
|
|
@ -30,6 +30,9 @@ module.exports = {
|
|||
// When a new recording is being tracked in the panel.
|
||||
NEW_RECORDING: "Performance:NewRecording",
|
||||
|
||||
// When a new recording can't be successfully created when started.
|
||||
NEW_RECORDING_FAILED: "Performance:NewRecordingFailed",
|
||||
|
||||
// When a recording is started or stopped or stopping via the PerformanceController
|
||||
RECORDING_STATE_CHANGE: "Performance:RecordingStateChange",
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ var gToolbox, gTarget, gFront;
|
|||
var startupPerformance = Task.async(function*() {
|
||||
yield PerformanceController.initialize();
|
||||
yield PerformanceView.initialize();
|
||||
PerformanceController.enableFrontEventListeners();
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -97,6 +98,7 @@ var startupPerformance = Task.async(function*() {
|
|||
var shutdownPerformance = Task.async(function*() {
|
||||
yield PerformanceController.destroy();
|
||||
yield PerformanceView.destroy();
|
||||
PerformanceController.disableFrontEventListeners();
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -131,7 +133,6 @@ var PerformanceController = {
|
|||
this._prefs = require("devtools/client/performance/modules/global").PREFS;
|
||||
this._prefs.on("pref-changed", this._onPrefChanged);
|
||||
|
||||
gFront.on("*", this._onFrontEvent);
|
||||
ToolbarView.on(EVENTS.PREF_CHANGED, this._onPrefChanged);
|
||||
PerformanceView.on(EVENTS.UI_START_RECORDING, this.startRecording);
|
||||
PerformanceView.on(EVENTS.UI_STOP_RECORDING, this.stopRecording);
|
||||
|
@ -151,7 +152,6 @@ var PerformanceController = {
|
|||
this._telemetry.destroy();
|
||||
this._prefs.off("pref-changed", this._onPrefChanged);
|
||||
|
||||
gFront.off("*", this._onFrontEvent);
|
||||
ToolbarView.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
|
||||
PerformanceView.off(EVENTS.UI_START_RECORDING, this.startRecording);
|
||||
PerformanceView.off(EVENTS.UI_STOP_RECORDING, this.stopRecording);
|
||||
|
@ -164,6 +164,27 @@ var PerformanceController = {
|
|||
gDevTools.off("pref-changed", this._onThemeChanged);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables front event listeners.
|
||||
*
|
||||
* The rationale behind this is given by the async intialization of all the
|
||||
* frontend components. Even though the panel is considered "open" only after
|
||||
* both the controller and the view are created, and even though their
|
||||
* initialization is sequential (controller, then view), the controller might
|
||||
* start handling backend events before the view finishes if the event
|
||||
* listeners are added too soon.
|
||||
*/
|
||||
enableFrontEventListeners: function() {
|
||||
gFront.on("*", this._onFrontEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Disables front event listeners.
|
||||
*/
|
||||
disableFrontEventListeners: function() {
|
||||
gFront.off("*", this._onFrontEvent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the current devtools theme.
|
||||
*/
|
||||
|
@ -205,6 +226,27 @@ var PerformanceController = {
|
|||
this._prefs[prefName] = prefValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether or not a new recording is supported by the PerformanceFront.
|
||||
* @return Promise:boolean
|
||||
*/
|
||||
canCurrentlyRecord: Task.async(function*() {
|
||||
// If we're testing the legacy front, the performance actor will exist,
|
||||
// with `canCurrentlyRecord` method; this ensures we test the legacy path.
|
||||
if (gFront.LEGACY_FRONT) {
|
||||
return true;
|
||||
}
|
||||
let hasActor = yield gTarget.hasActor("performance");
|
||||
if (!hasActor) {
|
||||
return true;
|
||||
}
|
||||
let actorCanCheck = yield gTarget.actorHasMethod("performance", "canCurrentlyRecord");
|
||||
if (!actorCanCheck) {
|
||||
return true;
|
||||
}
|
||||
return (yield gFront.canCurrentlyRecord()).success;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Starts recording with the PerformanceFront.
|
||||
*/
|
||||
|
@ -221,7 +263,13 @@ var PerformanceController = {
|
|||
sampleFrequency: this.getPref("profiler-sample-frequency")
|
||||
};
|
||||
|
||||
yield gFront.startRecording(options);
|
||||
// In some cases, like when the target has a private browsing tab,
|
||||
// recording is not currently supported because of the profiler module.
|
||||
// Present a notification in this case alerting the user of this issue.
|
||||
if (!(yield gFront.startRecording(options))) {
|
||||
this.emit(EVENTS.NEW_RECORDING_FAILED);
|
||||
PerformanceView.setState("unavailable");
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,27 +14,30 @@ var PerformanceView = {
|
|||
// that the server has support for determining buffer status.
|
||||
_bufferStatusSupported: false,
|
||||
|
||||
// Mapping of state to selectors for different panes
|
||||
// of the main profiler view. Used in `PerformanceView.setState()`
|
||||
// Mapping of state to selectors for different properties and their values,
|
||||
// from the main profiler view. Used in `PerformanceView.setState()`
|
||||
states: {
|
||||
empty: [
|
||||
{ deck: "#performance-view", pane: "#empty-notice" }
|
||||
"unavailable": [
|
||||
{ sel: "#performance-view", opt: "selectedPanel", val: () => $("#unavailable-notice") },
|
||||
],
|
||||
recording: [
|
||||
{ deck: "#performance-view", pane: "#performance-view-content" },
|
||||
{ deck: "#details-pane-container", pane: "#recording-notice" }
|
||||
"empty": [
|
||||
{ sel: "#performance-view", opt: "selectedPanel", val: () => $("#empty-notice") }
|
||||
],
|
||||
"recording": [
|
||||
{ sel: "#performance-view", opt: "selectedPanel", val: () => $("#performance-view-content") },
|
||||
{ sel: "#details-pane-container", opt: "selectedPanel", val: () => $("#recording-notice") }
|
||||
],
|
||||
"console-recording": [
|
||||
{ deck: "#performance-view", pane: "#performance-view-content" },
|
||||
{ deck: "#details-pane-container", pane: "#console-recording-notice" }
|
||||
{ sel: "#performance-view", opt: "selectedPanel", val: () => $("#performance-view-content") },
|
||||
{ sel: "#details-pane-container", opt: "selectedPanel", val: () => $("#console-recording-notice") }
|
||||
],
|
||||
recorded: [
|
||||
{ deck: "#performance-view", pane: "#performance-view-content" },
|
||||
{ deck: "#details-pane-container", pane: "#details-pane" }
|
||||
"recorded": [
|
||||
{ sel: "#performance-view", opt: "selectedPanel", val: () => $("#performance-view-content") },
|
||||
{ sel: "#details-pane-container", opt: "selectedPanel", val: () => $("#details-pane") }
|
||||
],
|
||||
loading: [
|
||||
{ deck: "#performance-view", pane: "#performance-view-content" },
|
||||
{ deck: "#details-pane-container", pane: "#loading-notice" }
|
||||
"loading": [
|
||||
{ sel: "#performance-view", opt: "selectedPanel", val: () => $("#performance-view-content") },
|
||||
{ sel: "#details-pane-container", opt: "selectedPanel", val: () => $("#loading-notice") }
|
||||
]
|
||||
},
|
||||
|
||||
|
@ -52,6 +55,7 @@ var PerformanceView = {
|
|||
this._onRecordingSelected = this._onRecordingSelected.bind(this);
|
||||
this._onProfilerStatusUpdated = this._onProfilerStatusUpdated.bind(this);
|
||||
this._onRecordingStateChange = this._onRecordingStateChange.bind(this);
|
||||
this._onNewRecordingFailed = this._onNewRecordingFailed.bind(this);
|
||||
|
||||
for (let button of $$(".record-button")) {
|
||||
button.addEventListener("click", this._onRecordButtonClick);
|
||||
|
@ -64,8 +68,13 @@ var PerformanceView = {
|
|||
PerformanceController.on(EVENTS.PROFILER_STATUS_UPDATED, this._onProfilerStatusUpdated);
|
||||
PerformanceController.on(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
|
||||
PerformanceController.on(EVENTS.NEW_RECORDING, this._onRecordingStateChange);
|
||||
PerformanceController.on(EVENTS.NEW_RECORDING_FAILED, this._onNewRecordingFailed);
|
||||
|
||||
this.setState("empty");
|
||||
if (yield PerformanceController.canCurrentlyRecord()) {
|
||||
this.setState("empty");
|
||||
} else {
|
||||
this.setState("unavailable");
|
||||
}
|
||||
|
||||
// Initialize the ToolbarView first, because other views may need access
|
||||
// to the OptionsView via the controller, to read prefs.
|
||||
|
@ -89,6 +98,7 @@ var PerformanceView = {
|
|||
PerformanceController.off(EVENTS.PROFILER_STATUS_UPDATED, this._onProfilerStatusUpdated);
|
||||
PerformanceController.off(EVENTS.RECORDING_STATE_CHANGE, this._onRecordingStateChange);
|
||||
PerformanceController.off(EVENTS.NEW_RECORDING, this._onRecordingStateChange);
|
||||
PerformanceController.off(EVENTS.NEW_RECORDING_FAILED, this._onNewRecordingFailed);
|
||||
|
||||
yield ToolbarView.destroy();
|
||||
yield RecordingsView.destroy();
|
||||
|
@ -97,16 +107,18 @@ var PerformanceView = {
|
|||
}),
|
||||
|
||||
/**
|
||||
* Sets the state of the profiler view. Possible options are "empty",
|
||||
* "recording", "console-recording", "recorded".
|
||||
* Sets the state of the profiler view. Possible options are "unavailable",
|
||||
* "empty", "recording", "console-recording", "recorded".
|
||||
*/
|
||||
setState: function (state) {
|
||||
let viewConfig = this.states[state];
|
||||
if (!viewConfig) {
|
||||
throw new Error(`Invalid state for PerformanceView: ${state}`);
|
||||
}
|
||||
for (let { deck, pane } of viewConfig) {
|
||||
$(deck).selectedPanel = $(pane);
|
||||
for (let { sel, opt, val } of viewConfig) {
|
||||
for (let el of $$(sel)) {
|
||||
el[opt] = val();
|
||||
}
|
||||
}
|
||||
|
||||
this._state = state;
|
||||
|
@ -114,6 +126,7 @@ var PerformanceView = {
|
|||
if (state === "console-recording") {
|
||||
let recording = PerformanceController.getCurrentRecording();
|
||||
let label = recording.getLabel() || "";
|
||||
|
||||
// Wrap the label in quotes if it exists for the commands.
|
||||
label = label ? `"${label}"` : "";
|
||||
|
||||
|
@ -192,7 +205,7 @@ var PerformanceView = {
|
|||
*
|
||||
* @param {boolean} activate
|
||||
*/
|
||||
_activateRecordButtons: function (activate) {
|
||||
_toggleRecordButtons: function (activate) {
|
||||
for (let button of $$(".record-button")) {
|
||||
if (activate) {
|
||||
button.setAttribute("checked", "true");
|
||||
|
@ -209,7 +222,7 @@ var PerformanceView = {
|
|||
let currentRecording = PerformanceController.getCurrentRecording();
|
||||
let recordings = PerformanceController.getRecordings();
|
||||
|
||||
this._activateRecordButtons(recordings.find(r => !r.isConsole() && r.isRecording()));
|
||||
this._toggleRecordButtons(recordings.find(r => !r.isConsole() && r.isRecording()));
|
||||
this._lockRecordButtons(recordings.find(r => !r.isConsole() && r.isFinalizing()));
|
||||
|
||||
if (currentRecording && currentRecording.isFinalizing()) {
|
||||
|
@ -223,6 +236,14 @@ var PerformanceView = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When starting a recording has failed.
|
||||
*/
|
||||
_onNewRecordingFailed: function (e) {
|
||||
this._lockRecordButtons(false);
|
||||
this._toggleRecordButtons(false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handler for clicking the clear button.
|
||||
*/
|
||||
|
@ -238,7 +259,7 @@ var PerformanceView = {
|
|||
this.emit(EVENTS.UI_STOP_RECORDING);
|
||||
} else {
|
||||
this._lockRecordButtons(true);
|
||||
this._activateRecordButtons(true);
|
||||
this._toggleRecordButtons(true);
|
||||
this.emit(EVENTS.UI_START_RECORDING);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -157,6 +157,30 @@
|
|||
<!-- Recording contents and general notice messages -->
|
||||
<deck id="performance-view" flex="1">
|
||||
|
||||
<!-- A default notice, shown while initially opening the tool.
|
||||
Keep this element the first child of #performance-view. -->
|
||||
<hbox id="tool-loading-notice"
|
||||
class="notice-container"
|
||||
flex="1">
|
||||
</hbox>
|
||||
|
||||
<!-- "Unavailable" notice, shown when the entire tool is disabled,
|
||||
for example, when in private browsing mode. -->
|
||||
<vbox id="unavailable-notice"
|
||||
class="notice-container"
|
||||
align="center"
|
||||
pack="center"
|
||||
flex="1">
|
||||
<hbox class="devtools-toolbarbutton-group"
|
||||
pack="center">
|
||||
<toolbarbutton class="devtools-toolbarbutton record-button"
|
||||
label="&performanceUI.startRecording;"
|
||||
standalone="true"/>
|
||||
</hbox>
|
||||
<label class="tool-disabled-message"
|
||||
value="&performanceUI.unavailableNoticePB;"/>
|
||||
</vbox>
|
||||
|
||||
<!-- "Empty" notice, shown when there's no recordings available -->
|
||||
<hbox id="empty-notice"
|
||||
class="notice-container"
|
||||
|
|
|
@ -8,9 +8,6 @@ support-files =
|
|||
doc_simple-test.html
|
||||
head.js
|
||||
|
||||
# Commented out tests are profiler tests
|
||||
# that need to be moved over to performance tool
|
||||
|
||||
[browser_aaa-run-first-leaktest.js]
|
||||
[browser_perf-categories-js-calltree.js]
|
||||
[browser_perf-clear-01.js]
|
||||
|
@ -81,6 +78,7 @@ skip-if = os == 'linux' # bug 1186322
|
|||
[browser_perf-overview-selection-02.js]
|
||||
[browser_perf-overview-selection-03.js]
|
||||
[browser_perf-overview-time-interval.js]
|
||||
[browser_perf-private-browsing.js]
|
||||
[browser_perf-states.js]
|
||||
skip-if = debug # bug 1203888
|
||||
[browser_perf-refresh.js]
|
||||
|
|
|
@ -22,7 +22,7 @@ function* spawnTest() {
|
|||
yield profileEnd;
|
||||
|
||||
yield gDevTools.showToolbox(target, "performance");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let panel = yield toolbox.getCurrentPanel().open();
|
||||
let { panelWin: { PerformanceController, RecordingsView }} = panel;
|
||||
|
||||
let recordings = PerformanceController.getRecordings();
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
* when it is opened.
|
||||
*/
|
||||
|
||||
var WAIT_TIME = 10;
|
||||
|
||||
function* spawnTest() {
|
||||
let { target, toolbox, console } = yield initConsole(SIMPLE_URL);
|
||||
let front = toolbox.performance;
|
||||
|
@ -15,12 +13,13 @@ function* spawnTest() {
|
|||
let profileStart = once(front, "recording-started");
|
||||
console.profile("rust");
|
||||
yield profileStart;
|
||||
|
||||
profileStart = once(front, "recording-started");
|
||||
console.profile("rust2");
|
||||
yield profileStart;
|
||||
|
||||
yield gDevTools.showToolbox(target, "performance");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let panel = yield toolbox.getCurrentPanel().open();
|
||||
let { panelWin: { PerformanceController, RecordingsView }} = panel;
|
||||
|
||||
yield waitUntil(() => PerformanceController.getRecordings().length === 2);
|
||||
|
@ -39,6 +38,7 @@ function* spawnTest() {
|
|||
let profileEnd = once(front, "recording-stopped");
|
||||
console.profileEnd("rust");
|
||||
yield profileEnd;
|
||||
|
||||
profileEnd = once(front, "recording-stopped");
|
||||
console.profileEnd("rust2");
|
||||
yield profileEnd;
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
* also console recordings that have finished before it was opened.
|
||||
*/
|
||||
|
||||
var WAIT_TIME = 10;
|
||||
|
||||
function* spawnTest() {
|
||||
let { target, toolbox, console } = yield initConsole(SIMPLE_URL);
|
||||
let front = toolbox.performance;
|
||||
|
@ -25,7 +23,7 @@ function* spawnTest() {
|
|||
yield profileStart;
|
||||
|
||||
yield gDevTools.showToolbox(target, "performance");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let panel = yield toolbox.getCurrentPanel().open();
|
||||
let { panelWin: { PerformanceController, RecordingsView }} = panel;
|
||||
|
||||
yield waitUntil(() => PerformanceController.getRecordings().length === 2);
|
||||
|
|
|
@ -28,7 +28,7 @@ function* spawnTest() {
|
|||
"performance tab is no longer highlighted when console.profile recording finishes");
|
||||
|
||||
yield gDevTools.showToolbox(target, "performance");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let panel = yield toolbox.getCurrentPanel().open();
|
||||
let { panelWin: { PerformanceController, RecordingsView }} = panel;
|
||||
|
||||
yield startRecording(panel);
|
||||
|
|
|
@ -20,7 +20,7 @@ function* spawnTest() {
|
|||
yield profileStart;
|
||||
|
||||
yield gDevTools.showToolbox(target, "performance");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let panel = yield toolbox.getCurrentPanel().open();
|
||||
let { panelWin: { PerformanceController, RecordingsView }} = panel;
|
||||
|
||||
yield waitUntil(() => PerformanceController.getRecordings().length === 2);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that disables the frontend when in private browsing mode.
|
||||
*/
|
||||
|
||||
let gPanelWinTuples = [];
|
||||
|
||||
function* spawnTest() {
|
||||
yield testNormalWindow();
|
||||
yield testPrivateWindow();
|
||||
yield testRecordingFailingInWindow(0);
|
||||
yield testRecordingFailingInWindow(1);
|
||||
yield teardownPerfInWindow(1);
|
||||
yield testRecordingSucceedingInWindow(0);
|
||||
yield teardownPerfInWindow(0);
|
||||
|
||||
gPanelWinTuples = null;
|
||||
finish();
|
||||
}
|
||||
|
||||
function* createPanelInWindow(options) {
|
||||
let win = yield addWindow(options);
|
||||
let tab = yield addTab(SIMPLE_URL, win);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
yield target.makeRemote();
|
||||
|
||||
let toolbox = yield gDevTools.showToolbox(target, "performance");
|
||||
yield toolbox.initPerformance();
|
||||
|
||||
let panel = yield toolbox.getCurrentPanel().open();
|
||||
gPanelWinTuples.push({ panel, win });
|
||||
|
||||
return { panel, win };
|
||||
}
|
||||
|
||||
function* testNormalWindow() {
|
||||
let { panel } = yield createPanelInWindow({ private: false });
|
||||
let { PerformanceView } = panel.panelWin;
|
||||
|
||||
is(PerformanceView.getState(), "empty",
|
||||
"The initial state of the performance panel view is correct (1).");
|
||||
}
|
||||
|
||||
function* testPrivateWindow() {
|
||||
let { panel } = yield createPanelInWindow({ private: true });
|
||||
let { PerformanceView } = panel.panelWin;
|
||||
|
||||
is(PerformanceView.getState(), "unavailable",
|
||||
"The initial state of the performance panel view is correct (2).");
|
||||
}
|
||||
|
||||
function* testRecordingFailingInWindow(index) {
|
||||
let { panel } = gPanelWinTuples[index];
|
||||
let { EVENTS, PerformanceController } = panel.panelWin;
|
||||
|
||||
let onRecordingStarted = () => {
|
||||
ok(false, "Recording should not start while a private window is present.");
|
||||
};
|
||||
|
||||
PerformanceController.on(EVENTS.RECORDING_STARTED, onRecordingStarted);
|
||||
|
||||
let whenFailed = once(PerformanceController, EVENTS.NEW_RECORDING_FAILED);
|
||||
PerformanceController.startRecording();
|
||||
yield whenFailed;
|
||||
ok(true, "Recording has failed.");
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_STARTED, onRecordingStarted);
|
||||
}
|
||||
|
||||
function* testRecordingSucceedingInWindow(index) {
|
||||
let { panel } = gPanelWinTuples[index];
|
||||
let { EVENTS, PerformanceController } = panel.panelWin;
|
||||
|
||||
let onRecordingFailed = () => {
|
||||
ok(false, "Recording should start while now private windows are present.");
|
||||
};
|
||||
|
||||
PerformanceController.on(EVENTS.NEW_RECORDING_FAILED, onRecordingFailed);
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
ok(true, "Recording has succeeded.");
|
||||
|
||||
PerformanceController.off(EVENTS.RECORDING_STARTED, onRecordingFailed);
|
||||
}
|
||||
|
||||
function* teardownPerfInWindow(index) {
|
||||
let { panel, win } = gPanelWinTuples[index];
|
||||
yield teardown(panel, win);
|
||||
win.close();
|
||||
}
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
|
||||
function* spawnTest() {
|
||||
// This test seems to take a long time to cleanup on Ubuntu VMs.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let { target, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, $$, EVENTS, PerformanceController, OverviewView, WaterfallView, DetailsView } = panel.panelWin;
|
||||
let { WATERFALL_MARKER_SIDEBAR_SAFE_BOUNDS } = require("devtools/client/performance/modules/widgets/marker-view");
|
||||
|
|
|
@ -105,6 +105,29 @@ registerCleanupFunction(() => {
|
|||
Cu.forceGC();
|
||||
});
|
||||
|
||||
|
||||
function whenDelayedStartupFinished(aWindow, aCallback) {
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
if (aWindow == aSubject) {
|
||||
Services.obs.removeObserver(observer, aTopic);
|
||||
executeSoon(aCallback);
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
}
|
||||
|
||||
function addWindow(windowOptions) {
|
||||
let deferred = Promise.defer();
|
||||
let win = OpenBrowserWindow(windowOptions);
|
||||
|
||||
whenDelayedStartupFinished(win, () => {
|
||||
executeSoon(() => {
|
||||
deferred.resolve(win);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function addTab(aUrl, aWindow) {
|
||||
info("Adding tab: " + aUrl);
|
||||
|
||||
|
@ -233,6 +256,8 @@ function initPerformance(aUrl, tool="performance", targetOps={}) {
|
|||
// Wait for the performance tool to be spun up
|
||||
yield toolbox.initPerformance();
|
||||
|
||||
// Panel is already initialized after `showToolbox` and `initPerformance`,
|
||||
// no need to wait for `open` here.
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
return { target, panel, toolbox };
|
||||
});
|
||||
|
@ -276,12 +301,12 @@ function consoleExecute (console, method, val) {
|
|||
return promise;
|
||||
}
|
||||
|
||||
function* teardown(panel) {
|
||||
function* teardown(panel, win = window) {
|
||||
info("Destroying the performance tool.");
|
||||
|
||||
let tab = panel.target.tab;
|
||||
yield panel._toolbox.destroy();
|
||||
yield removeTab(tab);
|
||||
yield removeTab(tab, win);
|
||||
}
|
||||
|
||||
function idleWait(time) {
|
||||
|
|
|
@ -7,6 +7,7 @@ const { createStore, applyMiddleware } = require("devtools/client/shared/vendor/
|
|||
const { thunk } = require("./middleware/thunk");
|
||||
const { waitUntilService } = require("./middleware/wait-service");
|
||||
const { log } = require("./middleware/log");
|
||||
const { promise } = require("./middleware/promise");
|
||||
|
||||
/**
|
||||
* This creates a dispatcher with all the standard middleware in place
|
||||
|
@ -20,7 +21,8 @@ const { log } = require("./middleware/log");
|
|||
module.exports = (opts={}) => {
|
||||
const middleware = [
|
||||
thunk,
|
||||
waitUntilService
|
||||
waitUntilService,
|
||||
promise,
|
||||
];
|
||||
|
||||
if (opts.log) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
DevToolsModules(
|
||||
'log.js',
|
||||
'promise.js',
|
||||
'thunk.js',
|
||||
'wait-service.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* 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 uuidgen = require("sdk/util/uuid").uuid;
|
||||
const {
|
||||
entries, toObject, reportException, executeSoon
|
||||
} = require("devtools/shared/DevToolsUtils");
|
||||
const PROMISE = exports.PROMISE = "@@dispatch/promise";
|
||||
|
||||
function promiseMiddleware ({ dispatch, getState }) {
|
||||
return next => action => {
|
||||
if (!(PROMISE in action)) {
|
||||
return next(action);
|
||||
}
|
||||
|
||||
const promise = action[PROMISE];
|
||||
const seqId = uuidgen().toString();
|
||||
|
||||
// Create a new action that doesn't have the promise field and has
|
||||
// the `seqId` field that represents the sequence id
|
||||
action = Object.assign(
|
||||
toObject(entries(action).filter(pair => pair[0] !== PROMISE)), { seqId }
|
||||
);
|
||||
|
||||
dispatch(Object.assign({}, action, { status: "start" }));
|
||||
|
||||
promise.then(value => {
|
||||
executeSoon(() => {
|
||||
dispatch(Object.assign({}, action, {
|
||||
status: "done",
|
||||
value: value
|
||||
}));
|
||||
});
|
||||
}).catch(error => {
|
||||
executeSoon(() => {
|
||||
dispatch(Object.assign({}, action, {
|
||||
status: "error",
|
||||
error
|
||||
}));
|
||||
});
|
||||
reportException(`@@redux/middleware/promise#${action.type}`, error);
|
||||
});
|
||||
|
||||
// Return the promise so action creators can still compose if they
|
||||
// want to.
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
exports.promise = promiseMiddleware;
|
|
@ -2,26 +2,27 @@
|
|||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
cm_comment_test.js
|
||||
cm_doc_test.js
|
||||
cm_driver.js
|
||||
cm_emacs_test.js
|
||||
cm_mode_test.css
|
||||
cm_mode_test.js
|
||||
cm_multi_test.js
|
||||
cm_mode_ruby.js
|
||||
cm_script_injection_test.js
|
||||
cm_search_test.js
|
||||
cm_sublime_test.js
|
||||
cm_test.js
|
||||
cm_vim_test.js
|
||||
codemirror.html
|
||||
codemirror/comment_test.js
|
||||
codemirror/doc_test.js
|
||||
codemirror/driver.js
|
||||
codemirror/emacs_test.js
|
||||
codemirror/mode_test.css
|
||||
codemirror/mode_test.js
|
||||
codemirror/multi_test.js
|
||||
codemirror/search_test.js
|
||||
codemirror/sublime_test.js
|
||||
codemirror/test.js
|
||||
codemirror/vim_test.js
|
||||
codemirror/codemirror.html
|
||||
codemirror/vimemacs.html
|
||||
codemirror/mode/javascript/test.js
|
||||
css_statemachine_testcases.css
|
||||
css_statemachine_tests.json
|
||||
css_autocompletion_tests.json
|
||||
vimemacs.html
|
||||
head.js
|
||||
helper_codemirror_runner.js
|
||||
cm_mode_ruby.js
|
||||
cm_script_injection_test.js
|
||||
|
||||
[browser_editor_autocomplete_basic.js]
|
||||
[browser_editor_autocomplete_events.js]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const URI = "chrome://mochitests/content/browser/devtools/client/sourceeditor/test/codemirror.html";
|
||||
const URI = "chrome://mochitests/content/browser/devtools/client/sourceeditor/test/codemirror/codemirror.html";
|
||||
loadHelperScript("helper_codemirror_runner.js");
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const URI = "chrome://mochitests/content/browser/devtools/client/sourceeditor/test/vimemacs.html";
|
||||
const URI = "chrome://mochitests/content/browser/devtools/client/sourceeditor/test/codemirror/vimemacs.html";
|
||||
loadHelperScript("helper_codemirror_runner.js");
|
||||
|
||||
function test() {
|
||||
|
|
|
@ -58,16 +58,16 @@
|
|||
|
||||
<div id=testground></div>
|
||||
|
||||
<script src="cm_driver.js"></script>
|
||||
<script src="cm_test.js"></script>
|
||||
<script src="cm_comment_test.js"></script>
|
||||
<script src="cm_doc_test.js"></script>
|
||||
<script src="cm_driver.js"></script>
|
||||
<script src="cm_emacs_test.js"></script>
|
||||
<script src="cm_mode_test.js"></script>
|
||||
<script src="cm_mode_javascript_test.js"></script>
|
||||
<script src="cm_multi_test.js"></script>
|
||||
<script src="cm_search_test.js"></script>
|
||||
<script src="driver.js"></script>
|
||||
<script src="test.js"></script>
|
||||
<script src="comment_test.js"></script>
|
||||
<script src="doc_test.js"></script>
|
||||
<script src="driver.js"></script>
|
||||
<script src="emacs_test.js"></script>
|
||||
<script src="mode_test.js"></script>
|
||||
<script src="mode/javascript/test.js"></script>
|
||||
<script src="multi_test.js"></script>
|
||||
<script src="search_test.js"></script>
|
||||
|
||||
<!-- VIM and Emacs mode tests are in vimemacs.html
|
||||
<script src="cm_sublime_test.js"></script>
|
|
@ -58,10 +58,10 @@
|
|||
|
||||
<div id=testground></div>
|
||||
|
||||
<script src="cm_driver.js"></script>
|
||||
<script src="cm_sublime_test.js"></script>
|
||||
<script src="cm_vim_test.js"></script>
|
||||
<script src="cm_emacs_test.js"></script>
|
||||
<script src="driver.js"></script>
|
||||
<script src="sublime_test.js"></script>
|
||||
<script src="vim_test.js"></script>
|
||||
<script src="emacs_test.js"></script>
|
||||
|
||||
<!-- Basic tests are in codemirror.html
|
||||
<script src="cm_driver.js"></script>
|
|
@ -0,0 +1,74 @@
|
|||
/* 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 protocol = require("devtools/server/protocol");
|
||||
const { method, Arg } = protocol;
|
||||
const Services = require("Services");
|
||||
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils",
|
||||
"devtools/shared/DevToolsUtils");
|
||||
loader.lazyRequireGetter(this, "OS", "resource://gre/modules/osfile.jsm", true);
|
||||
loader.lazyRequireGetter(this, "Task", "resource://gre/modules/Task.jsm", true);
|
||||
loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
|
||||
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
|
||||
/**
|
||||
* The HeapSnapshotFileActor handles transferring heap snapshot files from the
|
||||
* server to the client. This has to be a global actor in the parent process
|
||||
* because child processes are sandboxed and do not have access to the file
|
||||
* system.
|
||||
*/
|
||||
exports.HeapSnapshotFileActor = protocol.ActorClass({
|
||||
typeName: "heapSnapshotFile",
|
||||
|
||||
initialize: function (conn, parent) {
|
||||
if (Services.appInfo &&
|
||||
(Services.appInfo.processType !==
|
||||
Services.appInfo.PROCESS_TYPE_DEFAULT)) {
|
||||
const err = new Error("Attempt to create a HeapSnapshotFileActor in a " +
|
||||
"child process! The HeapSnapshotFileActor *MUST* " +
|
||||
"be in the parent process!");
|
||||
DevToolsUtils.reportException(
|
||||
"HeapSnapshotFileActor.prototype.initialize", err);
|
||||
return;
|
||||
}
|
||||
|
||||
protocol.Actor.prototype.initialize.call(this, conn, parent);
|
||||
},
|
||||
|
||||
/**
|
||||
* @see MemoryFront.prototype.transferHeapSnapshot
|
||||
*/
|
||||
transferHeapSnapshot: method(Task.async(function* (snapshotId) {
|
||||
const snapshotFilePath =
|
||||
HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId);
|
||||
if (!snapshotFilePath) {
|
||||
throw new Error(`No heap snapshot with id: ${snapshotId}`);
|
||||
}
|
||||
|
||||
const streamPromise = DevToolsUtils.openFileStream(snapshotFilePath);
|
||||
|
||||
const { size } = yield OS.File.stat(snapshotFilePath);
|
||||
const bulkPromise = this.conn.startBulkSend({
|
||||
actor: this.actorID,
|
||||
type: "heap-snapshot",
|
||||
length: size
|
||||
});
|
||||
|
||||
const [bulk, stream] = yield Promise.all([bulkPromise, streamPromise]);
|
||||
|
||||
try {
|
||||
yield bulk.copyFrom(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}), {
|
||||
request: {
|
||||
snapshotId: Arg(0, "string")
|
||||
}
|
||||
}),
|
||||
|
||||
});
|
|
@ -5,7 +5,6 @@
|
|||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, components } = require("chrome");
|
||||
const { openFileStream } = require("devtools/shared/DevToolsUtils");
|
||||
const protocol = require("devtools/server/protocol");
|
||||
const { method, RetVal, Arg, types } = protocol;
|
||||
const { Memory } = require("devtools/shared/shared/memory");
|
||||
|
@ -17,7 +16,6 @@ loader.lazyRequireGetter(this, "FileUtils",
|
|||
"resource://gre/modules/FileUtils.jsm", true);
|
||||
loader.lazyRequireGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm", true);
|
||||
loader.lazyRequireGetter(this, "Task", "resource://gre/modules/Task.jsm", true);
|
||||
loader.lazyRequireGetter(this, "OS", "resource://gre/modules/osfile.jsm", true);
|
||||
loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
|
||||
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
|
||||
loader.lazyRequireGetter(this, "ThreadSafeChromeUtils");
|
||||
|
@ -115,35 +113,6 @@ var MemoryActor = exports.MemoryActor = protocol.ActorClass({
|
|||
}
|
||||
}),
|
||||
|
||||
transferHeapSnapshot: method(Task.async(function* (snapshotId) {
|
||||
const snapshotFilePath =
|
||||
HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId);
|
||||
if (!snapshotFilePath) {
|
||||
throw new Error(`No heap snapshot with id: ${snapshotId}`);
|
||||
}
|
||||
|
||||
const streamPromise = openFileStream(snapshotFilePath);
|
||||
|
||||
const { size } = yield OS.File.stat(snapshotFilePath);
|
||||
const bulkPromise = this.conn.startBulkSend({
|
||||
actor: this.actorID,
|
||||
type: "heap-snapshot",
|
||||
length: size
|
||||
});
|
||||
|
||||
const [bulk, stream] = yield Promise.all([bulkPromise, streamPromise]);
|
||||
|
||||
try {
|
||||
yield bulk.copyFrom(stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}), {
|
||||
request: {
|
||||
snapshotId: Arg(0, "string")
|
||||
}
|
||||
}),
|
||||
|
||||
takeCensus: actorBridge("takeCensus", {
|
||||
request: {},
|
||||
response: RetVal("json")
|
||||
|
@ -213,10 +182,13 @@ var MemoryActor = exports.MemoryActor = protocol.ActorClass({
|
|||
});
|
||||
|
||||
exports.MemoryFront = protocol.FrontClass(MemoryActor, {
|
||||
initialize: function(client, form) {
|
||||
initialize: function(client, form, rootForm = null) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
this._client = client;
|
||||
this.actorID = form.memoryActor;
|
||||
this.heapSnapshotFileActorID = rootForm
|
||||
? rootForm.heapSnapshotFileActor
|
||||
: null;
|
||||
this.manage(this);
|
||||
},
|
||||
|
||||
|
@ -225,9 +197,8 @@ exports.MemoryFront = protocol.FrontClass(MemoryActor, {
|
|||
* server and client do not share a file system, and return the local file
|
||||
* path to the heap snapshot.
|
||||
*
|
||||
* NB: This will not work with sandboxed child processes, as they do not have
|
||||
* access to the filesystem and the hep snapshot APIs do not support that use
|
||||
* case yet.
|
||||
* Note that this is safe to call for actors inside sandoxed child processes,
|
||||
* as we jump through the correct IPDL hoops.
|
||||
*
|
||||
* @params Boolean options.forceCopy
|
||||
* Always force a bulk data copy of the saved heap snapshot, even when
|
||||
|
@ -258,8 +229,12 @@ exports.MemoryFront = protocol.FrontClass(MemoryActor, {
|
|||
* @returns Promise<String>
|
||||
*/
|
||||
transferHeapSnapshot: protocol.custom(function (snapshotId) {
|
||||
if (!this.heapSnapshotFileActorID) {
|
||||
throw new Error("MemoryFront initialized without a rootForm");
|
||||
}
|
||||
|
||||
const request = this._client.request({
|
||||
to: this.actorID,
|
||||
to: this.heapSnapshotFileActorID,
|
||||
type: "transferHeapSnapshot",
|
||||
snapshotId
|
||||
});
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче