changes.js (3686B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { Actor } = require("resource://devtools/shared/protocol.js"); 8 const { changesSpec } = require("resource://devtools/shared/specs/changes.js"); 9 10 /** 11 * The ChangesActor stores a stack of changes made by devtools on 12 * the document in the associated tab. 13 */ 14 class ChangesActor extends Actor { 15 /** 16 * Create a ChangesActor. 17 * 18 * @param {DevToolsServerConnection} conn 19 * The server connection. 20 * @param {TargetActor} targetActor 21 * The top-level Actor for this tab. 22 */ 23 constructor(conn, targetActor) { 24 super(conn, changesSpec); 25 this.targetActor = targetActor; 26 27 this.onTrackChange = this.pushChange.bind(this); 28 this.onWillNavigate = this.onWillNavigate.bind(this); 29 30 this.targetActor.on("track-css-change", this.onTrackChange); 31 this.targetActor.on("will-navigate", this.onWillNavigate); 32 33 this.changes = []; 34 } 35 36 destroy() { 37 // Stop trying to emit RDP event on destruction. 38 this._changesHaveBeenRequested = false; 39 this.clearChanges(); 40 this.targetActor.off("will-navigate", this.onWillNavigate); 41 this.targetActor.off("track-css-change", this.onTrackChange); 42 super.destroy(); 43 } 44 45 start() { 46 /** 47 * This function currently does nothing and returns nothing. It exists only 48 * so that the client can trigger the creation of the ChangesActor through 49 * the front, without triggering side effects, and with a sensible semantic 50 * meaning. 51 */ 52 } 53 54 changeCount() { 55 return this.changes.length; 56 } 57 58 change(index) { 59 if (index >= 0 && index < this.changes.length) { 60 // Return a copy of the change at index. 61 return Object.assign({}, this.changes[index]); 62 } 63 // No change at that index -- return undefined. 64 return undefined; 65 } 66 67 allChanges() { 68 /** 69 * This function is called by all change event consumers on the client 70 * to get their initial state synchronized with the ChangesActor. We 71 * set a flag when this function is called so we know that it's worthwhile 72 * to send events. 73 */ 74 this._changesHaveBeenRequested = true; 75 return this.changes.slice(); 76 } 77 78 /** 79 * Handler for "will-navigate" event from the browsing context. The event is fired for 80 * the host page and any nested resources, like iframes. The list of changes should be 81 * cleared only when the host page navigates, ignoring any of its iframes. 82 * 83 * TODO: Clear changes made within sources in iframes when they navigate. Bug 1513940 84 * 85 * @param {object} eventData 86 * Event data with these properties: 87 * { 88 * window: Object // Window DOM object of the event source page 89 * isTopLevel: Boolean // true if the host page will navigate 90 * newURI: String // URI towards which the page will navigate 91 * request: Object // Request data. 92 * } 93 */ 94 onWillNavigate(eventData) { 95 if (eventData.isTopLevel) { 96 this.clearChanges(); 97 } 98 } 99 100 pushChange(change) { 101 this.changes.push(change); 102 if (this._changesHaveBeenRequested) { 103 this.emit("add-change", change); 104 } 105 } 106 107 popChange() { 108 const change = this.changes.pop(); 109 if (this._changesHaveBeenRequested) { 110 this.emit("remove-change", change); 111 } 112 return change; 113 } 114 115 clearChanges() { 116 this.changes.length = 0; 117 if (this._changesHaveBeenRequested) { 118 this.emit("clear-changes"); 119 } 120 } 121 } 122 123 exports.ChangesActor = ChangesActor;