blob: ca55518a8d6d6a8d5d14bcf4240ace588d47bb24 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @unrestricted
*/
Terminal.TerminalWidget = class extends UI.VBox {
constructor() {
super(false);
this.registerRequiredCSS('terminal/xterm.js/build/xterm.css');
this.registerRequiredCSS('terminal/terminal.css');
this.element.classList.add('terminal-root');
this.element.addEventListener('mousemove', this._mouseMove.bind(this), false);
this._init();
this._linkifier = new Components.Linkifier();
this._linkifyFunction = this._linkifyURL.bind(this);
}
_init() {
Services.serviceManager.createRemoteService('Terminal').then(this._initialized.bind(this));
}
/**
* @param {?Services.ServiceManager.Service} backend
*/
_initialized(backend) {
if (!backend) {
if (!this._unavailableLabel) {
this._unavailableLabel = this.element.createChild('div', 'terminal-error-message fill');
this._unavailableLabel.createChild('div').textContent =
Common.UIString('Terminal service is not available');
}
if (this.isShowing())
setTimeout(this._init.bind(this), 2000);
return;
}
if (this._unavailableLabel) {
this._unavailableLabel.remove();
delete this._unavailableLabel;
}
this._backend = backend;
if (!this._term) {
this._term = new Terminal({cursorBlink: true});
this._term.open(this.contentElement);
this._term.on('data', data => {
this._backend.send('write', {data: data});
});
this._term.fit();
this._term.on('resize', size => {
this._backend.send('resize', {cols: size.cols, rows: size.rows});
});
}
this._backend.send('init', {cols: this._term.cols, rows: this._term.rows});
this._backend.on('data', result => {
this._term.write(result.data);
this._linkifyUpToDate = false;
});
this._backend.on('disposed', this._disposed.bind(this));
}
_mouseMove() {
if (this._linkifyUpToDate)
return;
if (this._term)
this._linkify();
this._linkifyUpToDate = true;
}
/**
* @override
*/
onResize() {
if (this._term)
this._term.fit();
}
_disposed() {
this._initialized(null);
}
/**
* @override
*/
wasDetachedFromHierarchy() {
if (this._backend)
this._backend.dispose();
}
_linkify() {
if (!this._term)
return;
this._linkifier.reset();
var rows = this._term.rowContainer.children;
for (var i = 0; i < rows.length; i++)
this._linkifyTerminalLine(rows[i]);
}
/**
* @param {!Node} line
*/
_linkifyTerminalLine(line) {
var node = line.firstChild;
while (node) {
if (node.nodeType !== Node.TEXT_NODE) {
node = node.nextSibling;
continue;
}
var nextNode = node.nextSibling;
node.remove();
var linkified = Components.linkifyStringAsFragmentWithCustomLinkifier(node.textContent, this._linkifyFunction);
line.insertBefore(linkified, nextNode);
node = nextNode;
}
}
/**
* @param {string} title
* @param {string} url
* @param {number=} lineNumber
* @param {number=} columnNumber
*/
_linkifyURL(title, url, lineNumber, columnNumber) {
return this._linkifier.linkifyScriptLocation(null, null, url, lineNumber || 0, columnNumber || 0);
}
};