mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
347 lines
9.3 KiB
JavaScript
347 lines
9.3 KiB
JavaScript
/* 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";
|
|
|
|
this.EXPORTED_SYMBOLS = ["StyleEditorDebuggee", "StyleSheet"];
|
|
|
|
const Cc = Components.classes;
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "promise",
|
|
"resource://gre/modules/commonjs/sdk/core/promise.js", "Promise");
|
|
|
|
/**
|
|
* A StyleEditorDebuggee represents the document the style editor is debugging.
|
|
* It maintains a list of StyleSheet objects that represent the stylesheets in
|
|
* the target's document. It wraps remote debugging protocol comunications.
|
|
*
|
|
* It emits these events:
|
|
* 'document-load': debuggee's document is loaded, style sheets are argument
|
|
* 'stylesheets-cleared': The debuggee's stylesheets have been reset (e.g. the
|
|
* page navigated)
|
|
*
|
|
* @param {Target} target
|
|
* The target the debuggee is listening to
|
|
*/
|
|
let StyleEditorDebuggee = function(target) {
|
|
EventEmitter.decorate(this);
|
|
|
|
this.styleSheets = [];
|
|
|
|
this.clear = this.clear.bind(this);
|
|
this._onNewDocument = this._onNewDocument.bind(this);
|
|
this._onDocumentLoad = this._onDocumentLoad.bind(this);
|
|
|
|
this._target = target;
|
|
this._actor = this.target.form.styleEditorActor;
|
|
|
|
this.client.addListener("documentLoad", this._onDocumentLoad);
|
|
this._target.on("navigate", this._onNewDocument);
|
|
|
|
this._onNewDocument();
|
|
}
|
|
|
|
StyleEditorDebuggee.prototype = {
|
|
/**
|
|
* list of StyleSheet objects for this target
|
|
*/
|
|
styleSheets: null,
|
|
|
|
/**
|
|
* baseURIObject for the current document
|
|
*/
|
|
baseURI: null,
|
|
|
|
/**
|
|
* The target we're debugging
|
|
*/
|
|
get target() {
|
|
return this._target;
|
|
},
|
|
|
|
/**
|
|
* Client for communicating with server with remote debug protocol.
|
|
*/
|
|
get client() {
|
|
return this._target.client;
|
|
},
|
|
|
|
/**
|
|
* Get the StyleSheet object with the given href.
|
|
*
|
|
* @param {string} href
|
|
* Url of the stylesheet to find
|
|
* @return {StyleSheet}
|
|
* StyleSheet with the matching href
|
|
*/
|
|
styleSheetFromHref: function(href) {
|
|
for (let sheet of this.styleSheets) {
|
|
if (sheet.href == href) {
|
|
return sheet;
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
/**
|
|
* Clear stylesheets and state.
|
|
*/
|
|
clear: function() {
|
|
this.baseURI = null;
|
|
this.clearStyleSheets();
|
|
},
|
|
|
|
/**
|
|
* Clear stylesheets.
|
|
*/
|
|
clearStyleSheets: function() {
|
|
for (let stylesheet of this.styleSheets) {
|
|
stylesheet.destroy();
|
|
}
|
|
this.styleSheets = [];
|
|
this.emit("stylesheets-cleared");
|
|
},
|
|
|
|
/**
|
|
* Called when target is created or has navigated.
|
|
* Clear previous sheets and request new document's
|
|
*/
|
|
_onNewDocument: function() {
|
|
this.clear();
|
|
|
|
this._getBaseURI();
|
|
|
|
let message = { type: "newDocument" };
|
|
this._sendRequest(message);
|
|
},
|
|
|
|
/**
|
|
* request baseURIObject information from the document
|
|
*/
|
|
_getBaseURI: function() {
|
|
let message = { type: "getBaseURI" };
|
|
this._sendRequest(message, (response) => {
|
|
this.baseURI = Services.io.newURI(response.baseURI, null, null);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Handler for document load, forward event with
|
|
* all the stylesheets available on load.
|
|
*
|
|
* @param {string} type
|
|
* Event type
|
|
* @param {object} request
|
|
* Object with 'styleSheets' array of actor forms
|
|
*/
|
|
_onDocumentLoad: function(type, request) {
|
|
if (this.styleSheets.length > 0) {
|
|
this.clearStyleSheets();
|
|
}
|
|
let sheets = [];
|
|
for (let form of request.styleSheets) {
|
|
let sheet = this._addStyleSheet(form);
|
|
sheets.push(sheet);
|
|
}
|
|
this.emit("document-load", sheets);
|
|
},
|
|
|
|
/**
|
|
* Create a new StyleSheet object from the form
|
|
* and add to our stylesheet list.
|
|
*
|
|
* @param {object} form
|
|
* Initial properties of the stylesheet
|
|
*/
|
|
_addStyleSheet: function(form) {
|
|
let sheet = new StyleSheet(form, this);
|
|
this.styleSheets.push(sheet);
|
|
return sheet;
|
|
},
|
|
|
|
/**
|
|
* Create a new stylesheet with the given text
|
|
* and attach it to the document.
|
|
*
|
|
* @param {string} text
|
|
* Initial text of the stylesheet
|
|
* @param {function} callback
|
|
* Function to call when the stylesheet has been added to the document
|
|
*/
|
|
createStyleSheet: function(text, callback) {
|
|
let message = { type: "newStyleSheet", text: text };
|
|
this._sendRequest(message, (response) => {
|
|
let sheet = this._addStyleSheet(response.styleSheet);
|
|
callback(sheet);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Send a request to our actor on the server
|
|
*
|
|
* @param {object} message
|
|
* Message to send to the actor
|
|
* @param {function} callback
|
|
* Function to call with reponse from actor
|
|
*/
|
|
_sendRequest: function(message, callback) {
|
|
message.to = this._actor;
|
|
this.client.request(message, callback);
|
|
},
|
|
|
|
/**
|
|
* Clean up and remove listeners
|
|
*/
|
|
destroy: function() {
|
|
this.clear();
|
|
|
|
this._target.off("navigate", this._onNewDocument);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A StyleSheet object represents a stylesheet on the debuggee. It wraps
|
|
* communication with a complimentary StyleSheetActor on the server.
|
|
*
|
|
* It emits these events:
|
|
* 'source-load' - The full text source of the stylesheet has been fetched
|
|
* 'property-change' - Any property (e.g 'disabled') has changed
|
|
* 'style-applied' - A change has been applied to the live stylesheet on the server
|
|
* 'error' - An error occured when loading or saving stylesheet
|
|
*
|
|
* @param {object} form
|
|
* Initial properties of the stylesheet
|
|
* @param {StyleEditorDebuggee} debuggee
|
|
* Owner of the stylesheet
|
|
*/
|
|
let StyleSheet = function(form, debuggee) {
|
|
EventEmitter.decorate(this);
|
|
|
|
this.debuggee = debuggee;
|
|
this._client = debuggee.client;
|
|
this._actor = form.actor;
|
|
|
|
this._onSourceLoad = this._onSourceLoad.bind(this);
|
|
this._onPropertyChange = this._onPropertyChange.bind(this);
|
|
this._onStyleApplied = this._onStyleApplied.bind(this);
|
|
|
|
this._client.addListener("sourceLoad", this._onSourceLoad);
|
|
this._client.addListener("propertyChange", this._onPropertyChange);
|
|
this._client.addListener("styleApplied", this._onStyleApplied);
|
|
|
|
// Backwards compatibility
|
|
this._client.addListener("sourceLoad-" + this._actor, this._onSourceLoad);
|
|
this._client.addListener("propertyChange-" + this._actor, this._onPropertyChange);
|
|
this._client.addListener("styleApplied-" + this._actor, this._onStyleApplied);
|
|
|
|
|
|
// set initial property values
|
|
for (let attr in form) {
|
|
this[attr] = form[attr];
|
|
}
|
|
}
|
|
|
|
StyleSheet.prototype = {
|
|
/**
|
|
* Toggle the disabled attribute of the stylesheet
|
|
*/
|
|
toggleDisabled: function() {
|
|
let message = { type: "toggleDisabled" };
|
|
this._sendRequest(message);
|
|
},
|
|
|
|
/**
|
|
* Request that the source of the stylesheet be fetched.
|
|
* 'source-load' event will be fired when it's been fetched.
|
|
*/
|
|
fetchSource: function() {
|
|
let message = { type: "fetchSource" };
|
|
this._sendRequest(message);
|
|
},
|
|
|
|
/**
|
|
* Update the stylesheet in place with the given full source.
|
|
*
|
|
* @param {string} sheetText
|
|
* Full text to update the stylesheet with
|
|
*/
|
|
update: function(sheetText) {
|
|
let message = { type: "update", text: sheetText, transition: true };
|
|
this._sendRequest(message);
|
|
},
|
|
|
|
/**
|
|
* Handle source load event from the client.
|
|
*
|
|
* @param {string} type
|
|
* Event type
|
|
* @param {object} request
|
|
* Event details
|
|
*/
|
|
_onSourceLoad: function(type, request) {
|
|
if (request.from == this._actor) {
|
|
if (request.error) {
|
|
return this.emit("error", request.error);
|
|
}
|
|
this.emit("source-load", request.source);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handle a property change on the stylesheet
|
|
*
|
|
* @param {string} type
|
|
* Event type
|
|
* @param {object} request
|
|
* Event details
|
|
*/
|
|
_onPropertyChange: function(type, request) {
|
|
if (request.from == this._actor) {
|
|
this[request.property] = request.value;
|
|
this.emit("property-change", request.property);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handle event when update has been successfully applied and propogate it.
|
|
*/
|
|
_onStyleApplied: function(type, request) {
|
|
if (request.from == this._actor) {
|
|
this.emit("style-applied");
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Send a request to our actor on the server
|
|
*
|
|
* @param {object} message
|
|
* Message to send to the actor
|
|
* @param {function} callback
|
|
* Function to call with reponse from actor
|
|
*/
|
|
_sendRequest: function(message, callback) {
|
|
message.to = this._actor;
|
|
this._client.request(message, callback);
|
|
},
|
|
|
|
/**
|
|
* Clean up and remove event listeners
|
|
*/
|
|
destroy: function() {
|
|
this._client.removeListener("sourceLoad", this._onSourceLoad);
|
|
this._client.removeListener("propertyChange", this._onPropertyChange);
|
|
this._client.removeListener("styleApplied", this._onStyleApplied);
|
|
|
|
this._client.removeListener("sourceLoad-" + this._actor, this._onSourceLoad);
|
|
this._client.removeListener("propertyChange-" + this._actor, this._onPropertyChange);
|
|
this._client.removeListener("styleApplied-" + this._actor, this._onStyleApplied);
|
|
}
|
|
}
|