-
Notifications
You must be signed in to change notification settings - Fork 111
Support webview in dedicate container #947
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2020 Red Hat, Inc. | ||
* | ||
* This program and the accompanying materials are made | ||
* available under the terms of the Eclipse Public License 2.0 | ||
* which is available at https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
***********************************************************************/ | ||
|
||
import * as theia from '@theia/plugin'; | ||
|
||
import { WebviewImpl, WebviewsExtImpl } from '@theia/plugin-ext/lib/plugin/webviews'; | ||
|
||
import { Plugin } from '@theia/plugin-ext/src/common/plugin-api-rpc'; | ||
import { Uri } from '@theia/plugin'; | ||
import { overrideUri } from './che-content-aware-utils'; | ||
|
||
export class RemoteWebview extends WebviewImpl {} | ||
|
||
export class WebviewsContentAware { | ||
static makeWebviewsContentAware(webviewExt: WebviewsExtImpl): void { | ||
const webviewsContentAware = new WebviewsContentAware(); | ||
webviewsContentAware.overrideVSCodeResourceScheme(webviewExt); | ||
} | ||
|
||
overrideVSCodeResourceScheme(webviewExt: WebviewsExtImpl): void { | ||
this.rebind$createWebview(webviewExt); | ||
} | ||
|
||
// Modify WebviewOptions#localResourceRoots by setting remote side car scheme instead of default file | ||
// during webview panel create step. This method activates only when plugin call theia.createWebview | ||
// method from remote sidecar. Normally from theia sidecar this method should not be executed. | ||
// | ||
// localResourceRoots provides paths where extension hosts own resources, styles, scripts, fonts, etc. | ||
private rebind$createWebview(webviewExt: WebviewsExtImpl): void { | ||
const original$createWebview = webviewExt.createWebview.bind(webviewExt); | ||
webviewExt.createWebview = ( | ||
viewType: string, | ||
title: string, | ||
showOptions: theia.ViewColumn | theia.WebviewPanelShowOptions, | ||
options: theia.WebviewPanelOptions & theia.WebviewOptions, | ||
plugin: Plugin | ||
) => { | ||
const webviewPanel: theia.WebviewPanel = original$createWebview( | ||
viewType, | ||
title, | ||
showOptions, | ||
options.localResourceRoots | ||
? ({ | ||
enableFindWidget: options.enableFindWidget, | ||
retainContextWhenHidden: options.retainContextWhenHidden, | ||
enableScripts: options.enableScripts, | ||
enableCommandUris: options.enableCommandUris, | ||
localResourceRoots: (() => options.localResourceRoots.map(root => overrideUri(root)))(), | ||
portMapping: options.portMapping, | ||
} as theia.WebviewPanelOptions & theia.WebviewOptions) | ||
: options, | ||
plugin | ||
); | ||
|
||
this.rebind$asWebviewUri(webviewPanel.webview); | ||
this.rebind$_htmlSetter(webviewPanel.webview); | ||
|
||
return webviewPanel; | ||
}; | ||
} | ||
|
||
// Method theia.Webview#asWebviewUri is being called from theia container. | ||
// In default flow method returns the path like: /webview/theia-resource/file:///path/to/directory | ||
// with https scheme and authority | ||
private rebind$asWebviewUri(webview: theia.Webview): void { | ||
const original$asWebviewUri = webview.asWebviewUri.bind(webview); | ||
webview.asWebviewUri = (resource: Uri) => original$asWebviewUri(overrideUri(resource)); | ||
} | ||
|
||
// Browser part perform preprocess initial html content by replacing vscode-resource:/path/to/file | ||
// to https://authority/webview/theia-resource/file/path/to/file. To be able to operate with custom | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can't for example just patch webview/normalizeRequestUri https://github.com/eclipse-theia/theia/blob/fd0a8ce093273011ecf4500d673a982854af9e55/packages/plugin-ext/src/main/browser/webview/webview.ts ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried this solution, but it seems, that this won't work. The problem is extending the WebviewWidget won't get a proper effect, because this code is run on browser part on Theia sidecar and we need to provide the container name from environment variable on the sidecar from plugin. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
sorry @vzhukovs but it's not clear to me if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried. The main problem here is that rebound class will be executing on Theia's container where we don't have any sidecar specific information. As far as rebound class will execute from the browser part we also don't have ability to get environment information. So it better to intercept this method's calls from server side on sidecar directly: VS Code extension (sidecar server side) > Method intercept and link modification (sidecar server side) > Plugin Ext (sidecar server side > theia browser side) > Theia (theia browser side). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can't only rebind only in sidecar usecase ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From what I saw, I couldn't get this worked |
||
// provided scheme, we can perform replacing the initial html by appending remote sidecar scheme, so | ||
// we will get links look like vscode-resource://scheme/path/to/file. Webview.html organized via | ||
// getter and setter, so we cant really bind method, instead of this, we redefine setter property. | ||
// We need to leave backward compatibility with vscode resources that loads remotely. | ||
private rebind$_htmlSetter(webview: theia.Webview): void { | ||
Object.defineProperty(webview, '_html', { | ||
get: function () { | ||
// @ts-ignore | ||
return this._html; | ||
}.bind(this), | ||
set: function (value: string) { | ||
const sideCarScheme = `file-sidecar-${process.env.CHE_MACHINE_NAME}`; | ||
// @ts-ignore | ||
this._html = value.replace( | ||
/(["'])(vscode|theia)-resource:(\/\/([^\s\/'"]+?)(?=\/))?([^\s'"]+?)(["'])/gi, | ||
(_, startQuote, resourceType, _1, scheme, path, endQuote) => { | ||
if (scheme) { | ||
return _; | ||
} | ||
return `${startQuote}${resourceType}-resource://${sideCarScheme}${path}${endQuote}`; | ||
} | ||
); | ||
}.bind(this), | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably will need to spend some times on bringing DI in upstream for the plug-in host
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to digg into this thing and from what I saw, this requires some refactoring in plugin initializing mechanism. Am I right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eclipse-theia/theia#5761