blob: 26e90980d40353126ddfc6652dbc83eeeb4c7e61 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Keeps the websocket connection and allows sending messages
*/
const Connection = {
async getUrl() {
let url = document.querySelector("#url").value;
if (url) {
return [url, ""];
}
try {
let response = await fetch(location.origin + "/discover.json");
if (!response.ok) {
return [
"",
`Unexpected server error=${response.status} ${response.statusText}`,
];
} else {
let discover_json = await response.json();
if (discover_json.error) {
// Error message from the python server
return ["", discover_json.error];
}
// Success
return [discover_json.webSocketDebuggerUrl, ""];
}
} catch (e) {
request_error =
"Visual Debugger local server is inaccessible. \n" +
"Please launch the server with command:\n " +
" ./launchdebugger {app_port} {remote_port} \n" +
" remote_port defaults to 7777 \n" +
" corresponds to the chromium command line\n " +
" --remote-debugging-port=7777 \n" +
" app_port defaults to 8777. Currently app_port=" +
location.port;
return ["", request_error];
}
},
async startConnection() {
const loop_interval = 3000;
const connect_info = await this.getUrl();
if (connect_info[1] != "") {
window.alert(connect_info[1]);
return;
}
url = connect_info[0];
// Create WebSocket connection.
this.socket = new WebSocket(url);
const status = document.querySelector('#connection-status');
const connect = document.querySelector('#connect');
const disconnect = document.querySelector('#disconnect');
this.next_command_id = 1;
this.socket.addEventListener('error', (event) => {
document.getElementById('autoconnect').checked = false;
window.alert("Websocket could not connect.\n You may need to add: \n " +
"--remote-allow-origins=* \n to your chromium launch flags.");
});
// Connection opened
this.socket.addEventListener('open', (event) => {
const message = {};
message['method'] = 'VisualDebugger.startStream';
this.sendMessage(message)
connect.setAttribute('disabled', true);
disconnect.removeAttribute('disabled');
status.classList.remove('disconnected');
});
// Listen for messages
this.socket.addEventListener('message', (event) => {
const json = JSON.parse(event.data);
// We now use devtool events so our frame data is packed
// into the args of the method.
if (json.method === "VisualDebugger.frameResponse") {
const frame_json = json.params.frameData;
if (frame_json.connection == "ok") {
Filter.sendStreamFilters();
} else if (frame_json.frame && frame_json.drawcalls) {
processIncomingFrame(frame_json);
}
}
else if (json.error) {
window.alert("Visual Debugger could not start stream.\n " +
"please add 'use_viz_debugger=true' to args.gn");
console.log(json.error);
this.socket.close();
}
});
this.socket.addEventListener('close', () => {
connect.removeAttribute('disabled');
disconnect.setAttribute('disabled', true);
status.classList.add('disconnected');
// Checks if connection can be made every
// loop_interval number of milliseconds.
let retryAfterDelay = () => {
setTimeout(() => {
if (!document.getElementById("autoconnect").checked) {
// Keep this setTimeout loop alive in case the user re-checks the
// box.
retryAfterDelay();
return;
}
console.log("Attempting autoconnect...");
Connection.getUrl().then((test_connect) => {
if (test_connect[0] != "") {
Connection.startConnection();
} else {
// Failure, queue a retry.
retryAfterDelay();
}
});
}, loop_interval);
};
retryAfterDelay();
});
disconnect.addEventListener('click', () => {
const message = {};
message['method'] = 'VisualDebugger.stopStream';
this.sendMessage(message);
document.getElementById('autoconnect').checked = false;
this.socket.close();
});
},
initialize() {
const connect = document.querySelector('#connect');
connect.addEventListener('click', () => {
this.startConnection();
});
},
sendMessage(message) {
if (!this.socket)
return;
message['id'] = this.next_command_id++;
this.socket.send(JSON.stringify(message));
}
};