eae5d8c807
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
155 lines
5.0 KiB
TypeScript
155 lines
5.0 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as vscode from 'vscode';
|
|
import * as nls from 'vscode-nls';
|
|
import { Disposable } from './dispose';
|
|
|
|
const localize = nls.loadMessageBundle();
|
|
|
|
export interface ShowOptions {
|
|
readonly preserveFocus?: boolean;
|
|
readonly viewColumn?: vscode.ViewColumn;
|
|
}
|
|
|
|
export class SimpleBrowserView extends Disposable {
|
|
|
|
public static readonly viewType = 'simpleBrowser.view';
|
|
private static readonly title = localize('view.title', "Simple Browser");
|
|
|
|
private readonly _webviewPanel: vscode.WebviewPanel;
|
|
|
|
private readonly _onDidDispose = this._register(new vscode.EventEmitter<void>());
|
|
public readonly onDispose = this._onDidDispose.event;
|
|
|
|
constructor(
|
|
private readonly extensionUri: vscode.Uri,
|
|
url: string,
|
|
showOptions?: ShowOptions
|
|
) {
|
|
super();
|
|
|
|
this._webviewPanel = this._register(vscode.window.createWebviewPanel(SimpleBrowserView.viewType, SimpleBrowserView.title, {
|
|
viewColumn: showOptions?.viewColumn ?? vscode.ViewColumn.Active,
|
|
preserveFocus: showOptions?.preserveFocus
|
|
}, {
|
|
enableScripts: true,
|
|
retainContextWhenHidden: true,
|
|
}));
|
|
|
|
this._register(this._webviewPanel.webview.onDidReceiveMessage(e => {
|
|
switch (e.type) {
|
|
case 'openExternal':
|
|
try {
|
|
const url = vscode.Uri.parse(e.url);
|
|
vscode.env.openExternal(url);
|
|
} catch {
|
|
// Noop
|
|
}
|
|
break;
|
|
}
|
|
}));
|
|
|
|
this._register(this._webviewPanel.onDidDispose(() => {
|
|
this.dispose();
|
|
}));
|
|
|
|
this._register(vscode.workspace.onDidChangeConfiguration(e => {
|
|
if (e.affectsConfiguration('simpleBrowser.focusLockIndicator.enabled')) {
|
|
const configuration = vscode.workspace.getConfiguration('simpleBrowser');
|
|
this._webviewPanel.webview.postMessage({
|
|
type: 'didChangeFocusLockIndicatorEnabled',
|
|
focusLockEnabled: configuration.get<boolean>('focusLockIndicator.enabled', true)
|
|
});
|
|
}
|
|
}));
|
|
|
|
this.show(url);
|
|
}
|
|
|
|
public dispose() {
|
|
this._onDidDispose.fire();
|
|
super.dispose();
|
|
}
|
|
|
|
public show(url: string, options?: ShowOptions) {
|
|
this._webviewPanel.webview.html = this.getHtml(url);
|
|
this._webviewPanel.reveal(options?.viewColumn, options?.preserveFocus);
|
|
}
|
|
|
|
private getHtml(url: string) {
|
|
const configuration = vscode.workspace.getConfiguration('simpleBrowser');
|
|
|
|
const nonce = new Date().getTime() + '' + new Date().getMilliseconds();
|
|
|
|
const mainJs = this.extensionResourceUrl('media', 'index.js');
|
|
const mainCss = this.extensionResourceUrl('media', 'main.css');
|
|
const codiconsUri = this.extensionResourceUrl('node_modules', 'vscode-codicons', 'dist', 'codicon.css');
|
|
const codiconsFontUri = this.extensionResourceUrl('node_modules', 'vscode-codicons', 'dist', 'codicon.ttf');
|
|
|
|
return /* html */ `<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
|
|
|
|
<meta http-equiv="Content-Security-Policy" content="
|
|
default-src 'none';
|
|
font-src ${codiconsFontUri};
|
|
style-src ${this._webviewPanel.webview.cspSource};
|
|
script-src 'nonce-${nonce}';
|
|
frame-src *;
|
|
">
|
|
|
|
<meta id="simple-browser-settings" data-settings="${escapeAttribute(JSON.stringify({
|
|
url: url,
|
|
focusLockEnabled: configuration.get<boolean>('focusLockIndicator.enabled', true)
|
|
}))}">
|
|
|
|
<link rel="stylesheet" type="text/css" href="${mainCss}">
|
|
<link rel="stylesheet" type="text/css" href="${codiconsUri}">
|
|
</head>
|
|
<body>
|
|
<header class="header">
|
|
<nav class="controls">
|
|
<button
|
|
title="${localize('control.back.title', "Back")}"
|
|
class="back-button icon"><i class="codicon codicon-arrow-left"></i></button>
|
|
|
|
<button
|
|
title="${localize('control.forward.title', "Forward")}"
|
|
class="forward-button icon"><i class="codicon codicon-arrow-right"></i></button>
|
|
|
|
<button
|
|
title="${localize('control.reload.title', "Reload")}"
|
|
class="reload-button icon"><i class="codicon codicon-refresh"></i></button>
|
|
</nav>
|
|
|
|
<input class="url-input" type="text" value=${url}>
|
|
|
|
<nav class="controls">
|
|
<button
|
|
title="${localize('control.openExternal.title', "Open in browser")}"
|
|
class="open-external-button icon"><i class="codicon codicon-link-external"></i></button>
|
|
</nav>
|
|
</header>
|
|
<div class="content">
|
|
<div class="iframe-focused-alert">${localize('view.iframe-focused', "Focus Lock")}</div>
|
|
<iframe sandbox="allow-scripts allow-forms allow-same-origin"></iframe>
|
|
</div>
|
|
|
|
<script src="${mainJs}" nonce="${nonce}"></script>
|
|
</body>
|
|
</html>`;
|
|
}
|
|
|
|
private extensionResourceUrl(...parts: string[]): vscode.Uri {
|
|
return this._webviewPanel.webview.asWebviewUri(vscode.Uri.joinPath(this.extensionUri, ...parts));
|
|
}
|
|
}
|
|
|
|
function escapeAttribute(value: string | vscode.Uri): string {
|
|
return value.toString().replace(/"/g, '"');
|
|
}
|