/* 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 promise = require("devtools/shared/deprecated-sync-thenables");
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
const eventSource = require("devtools/shared/client/event-source");
const {arg, DebuggerClient} = require("devtools/shared/client/debugger-client");
loader.lazyRequireGetter(this, "ThreadClient", "devtools/shared/client/thread-client");
const noop = () => {};
/**
* Creates a tab client for the remote debugging protocol server. This client
* is a front to the tab actor created in the server side, hiding the protocol
* details in a traditional JavaScript API.
*
* @param client DebuggerClient
* The debugger client parent.
* @param form object
* The protocol form for this tab.
*/
function TabClient(client, form) {
this.client = client;
this._actor = form.from;
this._threadActor = form.threadActor;
this.javascriptEnabled = form.javascriptEnabled;
this.cacheDisabled = form.cacheDisabled;
this.thread = null;
this.request = this.client.request;
this.traits = form.traits || {};
this.events = ["workerListChanged"];
}
TabClient.prototype = {
get actor() {
return this._actor;
},
get _transport() {
return this.client._transport;
},
/**
* Attach to a thread actor.
*
* @param object options
* Configuration options.
* - useSourceMaps: whether to use source maps or not.
* @param function onResponse
* Called with the response packet and a ThreadClient
* (which will be undefined on error).
*/
attachThread: function (options = {}, onResponse = noop) {
if (this.thread) {
DevToolsUtils.executeSoon(() => onResponse({}, this.thread));
return promise.resolve([{}, this.thread]);
}
let packet = {
to: this._threadActor,
type: "attach",
options,
};
return this.request(packet).then(response => {
if (!response.error) {
this.thread = new ThreadClient(this, this._threadActor);
this.client.registerClient(this.thread);
}
onResponse(response, this.thread);
return [response, this.thread];
});
},
/**
* Detach the client from the tab actor.
*
* @param function onResponse
* Called with the response packet.
*/
detach: DebuggerClient.requester({
type: "detach"
}, {
before: function (packet) {
if (this.thread) {
this.thread.detach();
}
return packet;
},
after: function (response) {
this.client.unregisterClient(this);
return response;
},
}),
/**
* Bring the window to the front.
*/
focus: DebuggerClient.requester({
type: "focus"
}, {}),
/**
* Reload the page in this tab.
*
* @param [optional] object options
* An object with a `force` property indicating whether or not
* this reload should skip the cache
*/
reload: function (options = { force: false }) {
return this._reload(options);
},
_reload: DebuggerClient.requester({
type: "reload",
options: arg(0)
}),
/**
* Navigate to another URL.
*
* @param string url
* The URL to navigate to.
*/
navigateTo: DebuggerClient.requester({
type: "navigateTo",
url: arg(0)
}),
/**
* Reconfigure the tab actor.
*
* @param object options
* A dictionary object of the new options to use in the tab actor.
* @param function onResponse
* Called with the response packet.
*/
reconfigure: DebuggerClient.requester({
type: "reconfigure",
options: arg(0)
}),
listWorkers: DebuggerClient.requester({
type: "listWorkers"
}),
attachWorker: function (workerActor, onResponse) {
return this.client.attachWorker(workerActor, onResponse);
},
};
eventSource(TabClient.prototype);
module.exports = TabClient;