DevTools - style editor - StyleSheetsActor should use the parent tabActor to retrieve the list of windows and react to new/removed windows

https://github.com/MoonchildProductions/moebius/pull/124
This commit is contained in:
janekptacijarabaci 2018-03-01 13:13:33 +01:00 committed by Roy Tam
commit 7177b5926a
6 changed files with 212 additions and 65 deletions

View file

@ -72,10 +72,18 @@ function StyleEditorUI(debuggee, target, panelDoc, cssProperties) {
this.editors = [];
this.selectedEditor = null;
this.savedLocations = {};
this._seenSheets = new Map();
// Don't add any style sheets that might arrive via events, until
// the call to initialize. Style sheets can arrive from the server
// at any time, for example if a new style sheet was added, or if
// the style sheet actor was just created and is walking the style
// sheets for the first time. In any case, in |initialize| we're
// going to fetch the list of sheets anyway.
this._suppressAdd = true;
this._onOptionsPopupShowing = this._onOptionsPopupShowing.bind(this);
this._onOptionsPopupHiding = this._onOptionsPopupHiding.bind(this);
this._onStyleSheetCreated = this._onStyleSheetCreated.bind(this);
this._onNewDocument = this._onNewDocument.bind(this);
this._onMediaPrefChanged = this._onMediaPrefChanged.bind(this);
this._updateMediaList = this._updateMediaList.bind(this);
@ -83,10 +91,13 @@ function StyleEditorUI(debuggee, target, panelDoc, cssProperties) {
this._onError = this._onError.bind(this);
this._updateOpenLinkItem = this._updateOpenLinkItem.bind(this);
this._openLinkNewTab = this._openLinkNewTab.bind(this);
this._addStyleSheet = this._addStyleSheet.bind(this);
this._prefObserver = new PrefObserver("devtools.styleeditor.");
this._prefObserver.on(PREF_ORIG_SOURCES, this._onNewDocument);
this._prefObserver.on(PREF_MEDIA_SIDEBAR, this._onMediaPrefChanged);
this._debuggee.on("stylesheet-added", this._addStyleSheet);
}
this.StyleEditorUI = StyleEditorUI;
@ -165,7 +176,7 @@ StyleEditorUI.prototype = {
this._view = new SplitView(viewRoot);
wire(this._view.rootElement, ".style-editor-newButton", () =>{
this._debuggee.addStyleSheet(null).then(this._onStyleSheetCreated);
this._debuggee.addStyleSheet(null);
});
wire(this._view.rootElement, ".style-editor-importButton", ()=> {
@ -233,6 +244,7 @@ StyleEditorUI.prototype = {
* StyleSheet object for new sheet
*/
_onNewDocument: function () {
this._suppressAdd = true;
this._debuggee.getStyleSheets().then((styleSheets) => {
return this._resetStyleSheetList(styleSheets);
}).then(null, e => console.error(e));
@ -246,6 +258,7 @@ StyleEditorUI.prototype = {
*/
_resetStyleSheetList: Task.async(function* (styleSheets) {
this._clear();
this._suppressAdd = false;
for (let sheet of styleSheets) {
try {
@ -288,6 +301,10 @@ StyleEditorUI.prototype = {
this._view.removeAll();
this.selectedEditor = null;
// Here the keys are style sheet actors, and the values are
// promises that resolve to the sheet's editor. See |_addStyleSheet|.
this._seenSheets = new Map();
this._suppressAdd = true;
this._root.classList.add("loading");
},
@ -298,46 +315,67 @@ StyleEditorUI.prototype = {
*
* @param {StyleSheetFront} styleSheet
* Style sheet to add to style editor
* @param {Boolean} isNew
* True if this style sheet was created by a call to the
* style sheets actor's @see addStyleSheet method.
* @return {Promise}
* A promise that resolves to the style sheet's editor when the style sheet has
* been fully loaded. If the style sheet has a source map, and source mapping
* is enabled, then the promise resolves to null.
*/
_addStyleSheet: Task.async(function* (styleSheet) {
let editor = yield this._addStyleSheetEditor(styleSheet);
if (!Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
return;
_addStyleSheet: function (styleSheet, isNew) {
if (this._suppressAdd) {
return null;
}
let sources = yield styleSheet.getOriginalSources();
if (sources && sources.length) {
let parentEditorName = editor.friendlyName;
this._removeStyleSheetEditor(editor);
if (!this._seenSheets.has(styleSheet)) {
let promise = (async () => {
let editor = await this._addStyleSheetEditor(styleSheet, isNew);
for (let source of sources) {
// set so the first sheet will be selected, even if it's a source
source.styleSheetIndex = styleSheet.styleSheetIndex;
source.relatedStyleSheet = styleSheet;
source.relatedEditorName = parentEditorName;
yield this._addStyleSheetEditor(source);
}
if (!Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
return editor;
}
let sources = await styleSheet.getOriginalSources();
// A single generated sheet might map to multiple original
// sheets, so make editors for each of them.
if (sources && sources.length) {
let parentEditorName = editor.friendlyName;
this._removeStyleSheetEditor(editor);
editor = null;
for (let source of sources) {
// set so the first sheet will be selected, even if it's a source
source.styleSheetIndex = styleSheet.styleSheetIndex;
source.relatedStyleSheet = styleSheet;
source.relatedEditorName = parentEditorName;
await this._addStyleSheetEditor(source);
}
}
return editor;
})();
this._seenSheets.set(styleSheet, promise);
}
}),
return this._seenSheets.get(styleSheet);
},
/**
* Add a new editor to the UI for a source.
*
* @param {StyleSheet} styleSheet
* Object representing stylesheet
* @param {nsIfile} file
* Optional file object that sheet was imported from
* @param {Boolean} isNew
* Optional if stylesheet is a new sheet created by user
* @return {Promise} that is resolved with the created StyleSheetEditor when
* the editor is fully initialized or rejected on error.
*/
_addStyleSheetEditor: Task.async(function* (styleSheet, file, isNew) {
_addStyleSheetEditor: Task.async(function* (styleSheet, isNew) {
// recall location of saved file for this sheet after page reload
let file = null;
let identifier = this.getStyleSheetIdentifier(styleSheet);
let savedFile = this.savedLocations[identifier];
if (savedFile && !file) {
if (savedFile) {
file = savedFile;
}
@ -388,8 +426,16 @@ StyleEditorUI.prototype = {
NetUtil.readInputStreamToString(stream, stream.available());
stream.close();
this._suppressAdd = true;
this._debuggee.addStyleSheet(source).then((styleSheet) => {
this._onStyleSheetCreated(styleSheet, selectedFile);
this._suppressAdd = false;
this._addStyleSheet(styleSheet, true).then(editor => {
if (editor) {
editor.savedFile = selectedFile;
}
// Just for testing purposes.
this.emit("test:editor-updated", editor);
});
});
});
};
@ -397,14 +443,6 @@ StyleEditorUI.prototype = {
showFilePicker(file, false, parentWindow, onFileSelected);
},
/**
* When a new or imported stylesheet has been added to the document.
* Add an editor for it.
*/
_onStyleSheetCreated: function (styleSheet, file) {
this._addStyleSheetEditor(styleSheet, file, true);
},
/**
* Forward any error from a stylesheet.
*
@ -1013,6 +1051,9 @@ StyleEditorUI.prototype = {
this._clearStyleSheetEditors();
this._seenSheets = null;
this._suppressAdd = false;
let sidebar = this._panelDoc.querySelector(".splitview-controller");
let sidebarWidth = sidebar.getAttribute("width");
Services.prefs.setIntPref(PREF_NAV_WIDTH, sidebarWidth);
@ -1025,5 +1066,7 @@ StyleEditorUI.prototype = {
this._prefObserver.off(PREF_ORIG_SOURCES, this._onNewDocument);
this._prefObserver.off(PREF_MEDIA_SIDEBAR, this._onMediaPrefChanged);
this._prefObserver.destroy();
this._debuggee.off("stylesheet-added", this._addStyleSheet);
}
};

View file

@ -60,6 +60,7 @@ support-files =
!/devtools/client/shared/test/test-actor-registry.js
!/devtools/client/shared/test/test-actor.js
[browser_styleeditor_add_stylesheet.js]
[browser_styleeditor_autocomplete.js]
[browser_styleeditor_autocomplete-disabled.js]
[browser_styleeditor_bom.js]

View file

@ -0,0 +1,37 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that a newly-added style sheet shows up in the style editor.
const TESTCASE_URI = TEST_BASE_HTTPS + "simple.html";
add_task(function* () {
let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
is(ui.editors.length, 2, "Two sheets present after load.");
// We have to wait for the length to change, because we might still
// be seeing events from the initial open.
let added = new Promise(resolve => {
let handler = () => {
if (ui.editors.length === 3) {
ui.off("editor-added", handler);
resolve();
}
};
ui.on("editor-added", handler);
});
info("Adding a style sheet");
yield ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
let document = content.document;
const style = document.createElement("style");
style.appendChild(document.createTextNode("div { background: #f06; }"));
document.head.appendChild(style);
});
yield added;
is(ui.editors.length, 3, "Three sheets present after new style sheet");
});

View file

@ -18,7 +18,7 @@ const SOURCE = "body{background:red;}";
add_task(function* () {
let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
let added = ui.once("editor-added");
let added = ui.once("test:editor-updated");
importSheet(ui, panel.panelWindow);
info("Waiting for editor to be added for the imported sheet.");