/* 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 { Ci } = require("chrome"); const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm"); loader.lazyRequireGetter(this, "WorkerActor", "devtools/server/actors/worker", true); loader.lazyRequireGetter(this, "ServiceWorkerRegistrationActor", "devtools/server/actors/worker", true); XPCOMUtils.defineLazyServiceGetter( this, "wdm", "@mozilla.org/dom/workers/workerdebuggermanager;1", "nsIWorkerDebuggerManager" ); XPCOMUtils.defineLazyServiceGetter( this, "swm", "@mozilla.org/serviceworkers/manager;1", "nsIServiceWorkerManager" ); function matchWorkerDebugger(dbg, options) { if ("type" in options && dbg.type !== options.type) { return false; } if ("window" in options) { let window = dbg.window; while (window !== null && window.parent !== window) { window = window.parent; } if (window !== options.window) { return false; } } return true; } function WorkerActorList(conn, options) { this._conn = conn; this._options = options; this._actors = new Map(); this._onListChanged = null; this._mustNotify = false; this.onRegister = this.onRegister.bind(this); this.onUnregister = this.onUnregister.bind(this); } WorkerActorList.prototype = { getList() { // Create a set of debuggers. let dbgs = new Set(); let e = wdm.getWorkerDebuggerEnumerator(); while (e.hasMoreElements()) { let dbg = e.getNext().QueryInterface(Ci.nsIWorkerDebugger); if (matchWorkerDebugger(dbg, this._options)) { dbgs.add(dbg); } } // Delete each actor for which we don't have a debugger. for (let [dbg, ] of this._actors) { if (!dbgs.has(dbg)) { this._actors.delete(dbg); } } // Create an actor for each debugger for which we don't have one. for (let dbg of dbgs) { if (!this._actors.has(dbg)) { this._actors.set(dbg, new WorkerActor(this._conn, dbg)); } } let actors = []; for (let [, actor] of this._actors) { actors.push(actor); } if (!this._mustNotify) { if (this._onListChanged !== null) { wdm.addListener(this); } this._mustNotify = true; } return Promise.resolve(actors); }, get onListChanged() { return this._onListChanged; }, set onListChanged(onListChanged) { if (typeof onListChanged !== "function" && onListChanged !== null) { throw new Error("onListChanged must be either a function or null."); } if (onListChanged === this._onListChanged) { return; } if (this._mustNotify) { if (this._onListChanged === null && onListChanged !== null) { wdm.addListener(this); } if (this._onListChanged !== null && onListChanged === null) { wdm.removeListener(this); } } this._onListChanged = onListChanged; }, _notifyListChanged() { this._onListChanged(); if (this._onListChanged !== null) { wdm.removeListener(this); } this._mustNotify = false; }, onRegister(dbg) { if (matchWorkerDebugger(dbg, this._options)) { this._notifyListChanged(); } }, onUnregister(dbg) { if (matchWorkerDebugger(dbg, this._options)) { this._notifyListChanged(); } } }; exports.WorkerActorList = WorkerActorList; function ServiceWorkerRegistrationActorList(conn) { this._conn = conn; this._actors = new Map(); this._onListChanged = null; this._mustNotify = false; this.onRegister = this.onRegister.bind(this); this.onUnregister = this.onUnregister.bind(this); } ServiceWorkerRegistrationActorList.prototype = { getList() { // Create a set of registrations. let registrations = new Set(); let array = swm.getAllRegistrations(); for (let index = 0; index < array.length; ++index) { registrations.add( array.queryElementAt(index, Ci.nsIServiceWorkerRegistrationInfo)); } // Delete each actor for which we don't have a registration. for (let [registration, ] of this._actors) { if (!registrations.has(registration)) { this._actors.delete(registration); } } // Create an actor for each registration for which we don't have one. for (let registration of registrations) { if (!this._actors.has(registration)) { this._actors.set(registration, new ServiceWorkerRegistrationActor(this._conn, registration)); } } if (!this._mustNotify) { if (this._onListChanged !== null) { swm.addListener(this); } this._mustNotify = true; } let actors = []; for (let [, actor] of this._actors) { actors.push(actor); } return Promise.resolve(actors); }, get onListchanged() { return this._onListchanged; }, set onListChanged(onListChanged) { if (typeof onListChanged !== "function" && onListChanged !== null) { throw new Error("onListChanged must be either a function or null."); } if (this._mustNotify) { if (this._onListChanged === null && onListChanged !== null) { swm.addListener(this); } if (this._onListChanged !== null && onListChanged === null) { swm.removeListener(this); } } this._onListChanged = onListChanged; }, _notifyListChanged() { this._onListChanged(); if (this._onListChanged !== null) { swm.removeListener(this); } this._mustNotify = false; }, onRegister(registration) { this._notifyListChanged(); }, onUnregister(registration) { this._notifyListChanged(); } }; exports.ServiceWorkerRegistrationActorList = ServiceWorkerRegistrationActorList;