summaryrefslogtreecommitdiffstats
path: root/devtools/server/actors/changes.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/server/actors/changes.js')
-rw-r--r--devtools/server/actors/changes.js125
1 files changed, 125 insertions, 0 deletions
diff --git a/devtools/server/actors/changes.js b/devtools/server/actors/changes.js
new file mode 100644
index 0000000000..16e24cb2e7
--- /dev/null
+++ b/devtools/server/actors/changes.js
@@ -0,0 +1,125 @@
+/* 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 { Actor } = require("resource://devtools/shared/protocol.js");
+const { changesSpec } = require("resource://devtools/shared/specs/changes.js");
+
+const TrackChangeEmitter = require("resource://devtools/server/actors/utils/track-change-emitter.js");
+
+/**
+ * The ChangesActor stores a stack of changes made by devtools on
+ * the document in the associated tab.
+ */
+class ChangesActor extends Actor {
+ /**
+ * Create a ChangesActor.
+ *
+ * @param {DevToolsServerConnection} conn
+ * The server connection.
+ * @param {TargetActor} targetActor
+ * The top-level Actor for this tab.
+ */
+ constructor(conn, targetActor) {
+ super(conn, changesSpec);
+ 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() {
+ // Stop trying to emit RDP event on destruction.
+ this._changesHaveBeenRequested = false;
+ this.clearChanges();
+ this.targetActor.off("will-navigate", this.onWillNavigate);
+ TrackChangeEmitter.off("track-change", this.onTrackChange);
+ super.destroy();
+ }
+
+ start() {
+ /**
+ * 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() {
+ return this.changes.length;
+ }
+
+ change(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() {
+ /**
+ * 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(eventData) {
+ if (eventData.isTopLevel) {
+ this.clearChanges();
+ }
+ }
+
+ pushChange(change) {
+ this.changes.push(change);
+ if (this._changesHaveBeenRequested) {
+ this.emit("add-change", change);
+ }
+ }
+
+ popChange() {
+ const change = this.changes.pop();
+ if (this._changesHaveBeenRequested) {
+ this.emit("remove-change", change);
+ }
+ return change;
+ }
+
+ clearChanges() {
+ this.changes.length = 0;
+ if (this._changesHaveBeenRequested) {
+ this.emit("clear-changes");
+ }
+ }
+}
+
+exports.ChangesActor = ChangesActor;