diff options
Diffstat (limited to 'devtools/server/actors/changes.js')
-rw-r--r-- | devtools/server/actors/changes.js | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/devtools/server/actors/changes.js b/devtools/server/actors/changes.js new file mode 100644 index 0000000000..bcc145038f --- /dev/null +++ b/devtools/server/actors/changes.js @@ -0,0 +1,122 @@ +/* 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/shared/protocol"); +const { changesSpec } = require("devtools/shared/specs/changes"); +const TrackChangeEmitter = require("devtools/server/actors/utils/track-change-emitter"); + +/** + * The ChangesActor stores a stack of changes made by devtools on + * the document in the associated tab. + */ +const ChangesActor = protocol.ActorClassWithSpec(changesSpec, { + /** + * Create a ChangesActor. + * + * @param {DevToolsServerConnection} conn + * The server connection. + * @param {TargetActor} targetActor + * The top-level Actor for this tab. + */ + initialize: function(conn, targetActor) { + protocol.Actor.prototype.initialize.call(this, conn); + this.targetActor = targetActor; + + this.onTrackChange = this.pushChange.bind(this); + this.onWillNavigate = this.onWillNavigate.bind(this); + + TrackChangeEmitter.on("track-change", this.onTrackChange); + this.targetActor.on("will-navigate", this.onWillNavigate); + + this.changes = []; + }, + + destroy: function() { + this.clearChanges(); + this.targetActor.off("will-navigate", this.onWillNavigate); + TrackChangeEmitter.off("track-change", this.onTrackChange); + protocol.Actor.prototype.destroy.call(this); + }, + + start: function() { + /** + * This function currently does nothing and returns nothing. It exists only + * so that the client can trigger the creation of the ChangesActor through + * the front, without triggering side effects, and with a sensible semantic + * meaning. + */ + }, + + changeCount: function() { + return this.changes.length; + }, + + change: function(index) { + if (index >= 0 && index < this.changes.length) { + // Return a copy of the change at index. + return Object.assign({}, this.changes[index]); + } + // No change at that index -- return undefined. + return undefined; + }, + + allChanges: function() { + /** + * This function is called by all change event consumers on the client + * to get their initial state synchronized with the ChangesActor. We + * set a flag when this function is called so we know that it's worthwhile + * to send events. + */ + this._changesHaveBeenRequested = true; + return this.changes.slice(); + }, + + /** + * Handler for "will-navigate" event from the browsing context. The event is fired for + * the host page and any nested resources, like iframes. The list of changes should be + * cleared only when the host page navigates, ignoring any of its iframes. + * + * TODO: Clear changes made within sources in iframes when they navigate. Bug 1513940 + * + * @param {Object} eventData + * Event data with these properties: + * { + * window: Object // Window DOM object of the event source page + * isTopLevel: Boolean // true if the host page will navigate + * newURI: String // URI towards which the page will navigate + * request: Object // Request data. + * } + */ + onWillNavigate: function(eventData) { + if (eventData.isTopLevel) { + this.clearChanges(); + } + }, + + pushChange: function(change) { + this.changes.push(change); + if (this._changesHaveBeenRequested) { + this.emit("add-change", change); + } + }, + + popChange: function() { + const change = this.changes.pop(); + if (this._changesHaveBeenRequested) { + this.emit("remove-change", change); + } + return change; + }, + + clearChanges: function() { + this.changes.length = 0; + if (this._changesHaveBeenRequested) { + this.emit("clear-changes"); + } + }, +}); + +exports.ChangesActor = ChangesActor; |