Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebView port mapping not working under Remote SSH #102449

Closed
renkun-ken opened this issue Jul 14, 2020 · 31 comments · Fixed by #105531
Closed

WebView port mapping not working under Remote SSH #102449

renkun-ken opened this issue Jul 14, 2020 · 31 comments · Fixed by #105531
Assignees
Labels
author-verification-requested Issues potentially verifiable by issue author bug Issue identified by VS Code Team member as probable bug electron Issues and items related to Electron upstream-issue-linked This is an upstream issue that has been reported upstream verified Verification succeeded webview Webview issues
Milestone

Comments

@renkun-ken
Copy link

renkun-ken commented Jul 14, 2020

  • VSCode Version: 1.47.0, 1.48.0-insider
  • OS Version: macOS 10.15.5
  • Remote SSH: Ubuntu 18.04

Steps to Reproduce:

  1. Install vscode-R extension.
  2. Set r.sessionWatcher to true, and reload vscode.
  3. Use Remote-SSH to connect to remote Linux server (where R is installed).
  4. Install vscode-R extension to remote server.
  5. Create R terminal and an R session is started
  6. Run ?get

It starts an http server that provides the R documentation, and a VSCode
WebView should show up by the following extension code.

function showBrowser(url: string, title: string, viewer: string | boolean) {
    console.info(`[showBrowser] uri: ${url}, viewer: ${viewer}`);
    if (viewer === false) {
        env.openExternal(Uri.parse(url));
    } else {
        const port = parseInt(new URL(url).port);
        const panel = window.createWebviewPanel(
            'browser',
            title,
            {
                preserveFocus: true,
                viewColumn: ViewColumn[String(viewer)],
            },
            {
                enableScripts: true,
                retainContextWhenHidden: true,
                portMapping: [
                    {
                        extensionHostPort: port,
                        webviewPort: port,
                    },
                ],
            });
        panel.webview.html = getBrowserHtml(url);
    }
    console.info('[showBrowser] Done');
}

function getBrowserHtml(url: string) {
    return `
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html, body {
        height: 100%;
        padding: 0;
        overflow: hidden;
    }
  </style>
</head>
<body>
    <iframe src="${url}" width="100%" height="100%" frameborder="0" />
</body>
</html>
`;
}

When viewer="Active", the WebView cannot be shown properly with the latest release and insider of VSCode. The iframe content is empty.

<iframe src="http://127.0.0.1:22784/library/base/html/get.html" width="100%" height="100%" frameborder="0">
</body>
</html>
</iframe>

However, if I run the following in R

.vsc.browser("http://127.0.0.1:22784/library/base/html/get.html", viewer = FALSE)

which basically calls showBrowser with viewer=false, then a local web browser is open by env.openExternal(Uri.parse(url)); the web page is properly shown. Only after this, I call ?get, or equivalently

.vsc.browser("http://127.0.0.1:22784/library/base/html/get.html", viewer = "Active")

The WebView could be properly shown.

I guess the port mapping of WebView via Remote SSH somehow is not working and it works with the port mapping enabled by env.openExternal(Uri.parse(url)). Everything works well if the same is done locally.

Related: REditorSupport/vscode-R#380.

Does this issue occur when all extensions are disabled?: Yes

@renkun-ken
Copy link
Author

Any updates on this? It looks like extensions that rely on WebView port mapping are completely broken.

@mjbvz mjbvz added this to the July 2020 milestone Jul 23, 2020
@mjbvz mjbvz added bug Issue identified by VS Code Team member as probable bug webview Webview issues labels Jul 24, 2020
@mjbvz mjbvz closed this as completed in 4600d36 Jul 28, 2020
@renkun-ken
Copy link
Author

renkun-ken commented Jul 30, 2020

@mjbvz I'm testing with the latest insider on both macOS and Ubuntu

Version: 1.48.0-insider
Commit: 15ada625f20086007e2c4aa0d760234360cd648f
Date: 2020-07-30T14:46:01.621Z (1 hr ago)
Electron: 9.1.0
Chrome: 83.0.4103.122
Node.js: 12.14.1
V8: 8.3.110.13-electron.0
OS: Darwin x64 19.6.0

which seems to include your commit to fix this issue (?). But the port mapping still does not work. Am I missing something?

The WebView still does not work

image

while the vscode.openExternal works:

image

@mjbvz mjbvz reopened this Jul 31, 2020
@mjbvz
Copy link
Collaborator

mjbvz commented Jul 31, 2020

Hm, just tested this with a simple extension and R specifically and it seems to be working for me:

Screen Shot 2020-07-30 at 10 03 14 PM

What is your server version? This can be found by running code-insiders --status

Also can you try putting together a minimal example that shows it not working?

@renkun-ken
Copy link
Author

I'm currently working on Ubuntu via Remote-SSH and the latest insider does not work. Following is code-insiders --status:

➜  ~ code-insiders --status
[190429:0731/133506.897875:ERROR:edid_parser.cc(102)] Too short EDID data: manufacturer id
[190429:0731/133506.898027:ERROR:edid_parser.cc(102)] Too short EDID data: manufacturer id
[190461:0731/133506.942076:ERROR:appcenter_api.cc(52)] expecting appcenter url prefix
[190461:0731/133507.036018:ERROR:sandbox_linux.cc(374)] InitializeSandbox() called with multiple threads in process gpu-process.
[190475:0731/133507.062317:ERROR:appcenter_api.cc(52)] expecting appcenter url prefix
Version:          Code - Insiders 1.48.0-insider (15ada625f20086007e2c4aa0d760234360cd648f, 2020-07-30T14:47:02.372Z)
OS Version:       Linux x64 5.4.0-42-generic
CPUs:             Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (8 x 3747)
Memory (System):  31.25GB (13.55GB free)
Load (avg):       1, 1, 1
VM:               0%
Screen Reader:    no
Process Argv:     --no-sandbox --unity-launch --crash-reporter-id 4dbf6963-fd26-4e66-8ece-6c1073059066
GPU Status:       2d_canvas:                  enabled
                  flash_3d:                   enabled
                  flash_stage3d:              enabled
                  flash_stage3d_baseline:     enabled
                  gpu_compositing:            enabled
                  multiple_raster_threads:    enabled_on
                  oop_rasterization:          disabled_off
                  opengl:                     enabled_on
                  protected_video_decode:     unavailable_off
                  rasterization:              disabled_software
                  skia_renderer:              enabled_on
                  video_decode:               unavailable_off
                  vulkan:                     disabled_off
                  webgl:                      enabled
                  webgl2:                     enabled

The minimal example is just like what you tried:

?get

and the WebView is blank. If this works then everything should work normally.

Maybe the fix somehow works for dev container but not for SSH?

@renkun-ken
Copy link
Author

I also tried with a dev container and it does not work either.

➜  ~ code-insiders --status                          
[216022:0731/141053.420434:ERROR:edid_parser.cc(102)] Too short EDID data: manufacturer id
[216022:0731/141053.420628:ERROR:edid_parser.cc(102)] Too short EDID data: manufacturer id
[216054:0731/141053.449849:ERROR:appcenter_api.cc(52)] expecting appcenter url prefix
[216054:0731/141053.520260:ERROR:sandbox_linux.cc(374)] InitializeSandbox() called with multiple threads in process gpu-process.
[216076:0731/141053.541967:ERROR:appcenter_api.cc(52)] expecting appcenter url prefix
Version:          Code - Insiders 1.48.0-insider (15ada625f20086007e2c4aa0d760234360cd648f, 2020-07-30T14:47:02.372Z)
OS Version:       Linux x64 5.4.0-42-generic
CPUs:             Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (8 x 3886)
Memory (System):  31.25GB (12.40GB free)
Load (avg):       1, 2, 2
VM:               0%
Screen Reader:    no
Process Argv:     --no-sandbox --unity-launch --crash-reporter-id 4dbf6963-fd26-4e66-8ece-6c1073059066
GPU Status:       2d_canvas:                  enabled
                  flash_3d:                   enabled
                  flash_stage3d:              enabled
                  flash_stage3d_baseline:     enabled
                  gpu_compositing:            enabled
                  multiple_raster_threads:    enabled_on
                  oop_rasterization:          disabled_off
                  opengl:                     enabled_on
                  protected_video_decode:     unavailable_off
                  rasterization:              disabled_software
                  skia_renderer:              enabled_on
                  video_decode:               unavailable_off
                  vulkan:                     disabled_off
                  webgl:                      enabled
                  webgl2:                     enabled

CPU %	Mem MB	   PID	Process
    0	   128	202630	code-insiders main
    0	    32	202634	   zygote
    0	    96	202660	     gpu-process
    0	    32	202635	   zygote
    0	    32	215755	     window (undefined)
    0	    32	202679	   utility
    0	    96	202781	   shared-process
    0	     0	216120	     /bin/sh -c /bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=
    0	     0	216121	       /bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=
    0	   192	212408	   window (http://127.0.0.1:15957/library/base/html/get.html - test [Container rocker/r-ubuntu:20.04 (/bold_…] - Visual Studio Code - Insiders)
    0	    96	212558	     extensionHost
    0	    32	212697	       docker exec -i -u root -e VSCODE_REMOTE_CONTAINERS_SESSION=7ce5fb12-4cfa-41ce-a4c1-8fc32da3ad931596175676186 39ef1c5453efd827ad898619584556d6c7ff2d3b4547af2855d36e671655af26 /bin/sh
    0	    32	212789	       docker exec -i -u root -e REMOTE_CONTAINERS_SOCKETS=["/tmp/vscode-ssh-auth-fb6b21a14410e43eccf3972e1b0ce491f92c0369.sock","/root/.gnupg/S.gpg-agent"] -e REMOTE_CONTAINERS_IPC=/tmp/vscode-remote-containers-ipc-fb6b21a14410e43eccf3972e1b0ce491f92c0369.sock 39ef1c5453efd827ad898619584556d6c7ff2d3b4547af2855d36e671655af26 /root/.vscode-server-insiders/bin/15ada625f20086007e2c4aa0d760234360cd648f/node /tmp/vscode-remote-containers-server-fb6b21a14410e43eccf3972e1b0ce491f92c0369.js
    0	    32	213010	       docker exec -i -u root -e VSCODE_REMOTE_CONTAINERS_SESSION=7ce5fb12-4cfa-41ce-a4c1-8fc32da3ad931596175676186 39ef1c5453efd827ad898619584556d6c7ff2d3b4547af2855d36e671655af26 /root/.vscode-server-insiders/bin/15ada625f20086007e2c4aa0d760234360cd648f/node -e  ....const net = require('net'); ....process.stdin.pause(); ....const client = net.createConnection({ port: 37963 }, () => { .....client.pipe(process.stdout); .....process.stdin.pipe(client); ....}); ....client.on('close', function (hadError) { .....process.exit(hadError ? 1 : 0); ....}); ....client.on('error', function (err) { .....process.stderr.write(err && (err.stack || err.message) || String(err)); ....}); ...
    0	    32	213027	       docker exec -i -u root -e VSCODE_REMOTE_CONTAINERS_SESSION=7ce5fb12-4cfa-41ce-a4c1-8fc32da3ad931596175676186 39ef1c5453efd827ad898619584556d6c7ff2d3b4547af2855d36e671655af26 /root/.vscode-server-insiders/bin/15ada625f20086007e2c4aa0d760234360cd648f/node -e  ....const net = require('net'); ....process.stdin.pause(); ....const client = net.createConnection({ port: 37963 }, () => { .....client.pipe(process.stdout); .....process.stdin.pipe(client); ....}); ....client.on('close', function (hadError) { .....process.exit(hadError ? 1 : 0); ....}); ....client.on('error', function (err) { .....process.stderr.write(err && (err.stack || err.message) || String(err)); ....}); ...
    0	    32	215173	       electron_node settings.js settings.js 
    0	    32	215277	       docker exec -i -u root -w /root/.vscode-server-insiders/extensions 39ef1c5453efd827ad898619584556d6c7ff2d3b4547af2855d36e671655af26 /bin/sh -c # Watch installed extensions ...trap "exit 0" 16 ...old=`ls -A --full-time` ...counter=0 ...while [ $counter -lt 60 ] ...do ....sleep 1 ....new=`ls -A --full-time` ....if [ "$new" != "$old" ] ....then .....exit 1 ....fi ....counter=`expr $counter + 1` ...done ..
    0	    64	215723	   window (undefined)



Remote:           Container rocker/r-ubuntu:20.04 (/bold_…
OS Version:       Linux x64 5.4.0-42-generic
CPUs:             Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (8 x 3785)
Memory (System):  31.25GB (12.50GB free)
VM:               0%
CPU %	Mem MB	   PID	Process
    0	    32	    87	remote agent
    0	    32	  1194	   extensionHost
    0	     0	  1392	     /bin/bash
    0	    64	  2752	     /usr/lib/R/bin/exec/R --no-save --no-restore
    0	    32	  1235	   watcherService
    0	     0	  2995	   /bin/sh -c /usr/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=
    0	     0	  2996	     /usr/bin/ps -ax -o pid=,ppid=,pcpu=,pmem=,command=
Folder (test): 2 files
|      File types: Rprofile(1) R(1)
|      Conf files:

@renkun-ken
Copy link
Author

renkun-ken commented Jul 31, 2020

A minimal example is:

  1. Use Remote-SSH or Remote-Container to connect to a server with R installed.
  2. Install vscode-R extension on remote.
  3. Turn on "r.sessionWatcher" in settings and reload vscode.
  4. Run Rscript -e "install.packages('jsonlite')" in terminal
  5. Run vscode command R: Create R terminal and observes that the R: (not attached) status bar item gets a pid.
  6. Run R command ?get which should show up a WebView with a help documentation.

@renkun-ken
Copy link
Author

renkun-ken commented Jul 31, 2020

In both Remote-SSH and Remote-Container environments, I found that the first time I tried ?get on a fresh remote session in vscode-insider, it will work. Close the WebView and try again, it won't work anymore.

The following are more examples to test with:

  1. Install required packages
apt install -y libcurl4-openssl-dev libxml2-dev libssl-dev libssh2-1-dev libsasl2-dev libcsv-dev libfontconfig1-dev libcairo2-dev
  1. Install R packages
Rscript -e "install.packages(c('devtools', 'shiny'))"
  1. Run vscode command "R: Create R terminal" and try the following example and a WebView of interactive shiny app should show up.
shiny::runExample("01_hello")
  1. Ctrl + C to exit the blocking code above. Try again above code and it should still work but current it won't work again.
  2. Install the following package in R:
devtools::install_github("nx10/httpgd@boost-beast")
  1. Run the following R code:
httpgd::httpgd()
plot(rnorm(100))
httpgd::httpgdBrowse()
  1. A WebView should show up with a scatter plot. Currently, it is a blank page, but the following code calls vscode.openExternal and the page will be open in an external web browser and the scatter plot should show up normally.
.vsc.browser(httpgd::httpgdURL(), viewer = FALSE)

@mjbvz
Copy link
Collaborator

mjbvz commented Jul 31, 2020

@deepak1556 The problem is the mapping from the request to the webview. In onBeforeRequest, the first request we see properly has a webcontentsid:

Screen Shot 2020-07-31 at 1 05 47 AM

Subsequent requests do not:

Screen Shot 2020-07-31 at 1 06 25 AM

I will see if I can put together a small electron reproduction.

However instead of using the web contents id at all, it would be nice if we could instead use the requesting origin:
electron/electron#24303 (since this would also support iframe based webviews)

@mjbvz
Copy link
Collaborator

mjbvz commented Aug 3, 2020

Filed electron/electron#24820 to track the electron issue upstream

@deepak1556 Instead of fixing my new issue, I think we should prioritize either:

@mjbvz mjbvz modified the milestones: July 2020, August 2020 Aug 3, 2020
@mjbvz mjbvz added electron Issues and items related to Electron upstream-issue-linked This is an upstream issue that has been reported upstream labels Aug 3, 2020
@deepak1556 deepak1556 self-assigned this Aug 3, 2020
@renkun-ken
Copy link
Author

I'm wondering if there's anything that could be done on our side to walk-around this at the moment? It looks like this cannot be fixed in a short term due to upstream issue.

Is it possible that we take advantage of the mechanism behind env.openExternal(Uri.parse(url)) so that the port mapping is enabled?

@mjbvz
Copy link
Collaborator

mjbvz commented Aug 11, 2020

Yes you should be able to workaround the issue by calling openExternal yourself. Not great but I think it should work

@deepak1556 Let me know if I can help you look into the electron issues/feature requests

@renkun-ken
Copy link
Author

renkun-ken commented Aug 11, 2020

Is it possible to use the port mapping enabled by openExternal or by some other port mapping API (I haven't seen any?) but not literally open an external web browser page?

@deepak1556
Copy link
Collaborator

deepak1556 commented Aug 11, 2020

@mjbvz sorry was looped into other work, I will have a fix for the mentioned electron issues tomorrow or day after.

@mjbvz mjbvz added this to the November 2020 milestone Oct 27, 2020
@renkun-ken
Copy link
Author

In the recent release, the auto port forwarding start to delay significantly so that the WebView is kept blank.

@renkun-ken
Copy link
Author

I switched to vscode.env.asExternalUri in REditorSupport/vscode-R#494 and this problem is no longer relevant.

@tamuratak

This comment has been minimized.

@tamuratak
Copy link
Contributor

We also have switched to vscode.env.asExternalUri in James-Yu/LaTeX-Workshop/pull/2439.

@mjbvz mjbvz modified the milestones: January 2021, February 2021 Jan 16, 2021
@mjbvz mjbvz closed this as completed in 767dd70 Feb 12, 2021
@mjbvz
Copy link
Collaborator

mjbvz commented Feb 12, 2021

I have tried to add a different workaround since it looks like electron/electron#27078 is not being back ported to electron 11.

Please test out the next VS Code insiders build and let me know if this still isn't working

@mjbvz mjbvz added the author-verification-requested Issues potentially verifiable by issue author label Feb 23, 2021
@tamuratak
Copy link
Contributor

It does not work with LaTeX Workshop 8.15.0. No output in the console of Webview Dev Tools. You can try the extension with PDF files without TeX distributions.

スクリーンショット 2021-02-23 12 56 30

Version: 1.54.0-insider
Commit: 11cd760
Date: 2021-02-22T06:44:36.656Z
Electron: 11.2.3
Chrome: 87.0.4280.141
Node.js: 12.18.3
V8: 8.7.220.31-electron.0
OS: Darwin x64 18.7.0

@connor4312 connor4312 reopened this Feb 26, 2021
@mjbvz mjbvz modified the milestones: February 2021, March 2021 Feb 26, 2021
@mjbvz mjbvz modified the milestones: March 2021, April 2021 Mar 22, 2021
@mjbvz
Copy link
Collaborator

mjbvz commented Apr 15, 2021

Please test this again in the latest insiders build. We now use service workers instead of electron to load webview resources, which I'm hoping addresses this

@renkun-ken
Copy link
Author

I tested with the latest insider build and webview port-mapping, but it still does not work.

Version: 1.56.0-insider
Commit: 94d369e27d19f598228961e9feb0413f2edabe5d
Date: 2021-04-14T12:05:02.733Z
Electron: 11.4.2
Chrome: 87.0.4280.141
Node.js: 12.18.3
V8: 8.7.220.31-electron.0
OS: Linux x64 5.8.0-48-generic

@mjbvz
Copy link
Collaborator

mjbvz commented Apr 15, 2021

I just looked more closely at the original issue and see that the original example uses an iframe, which explains why you don't see this working

Previously port forwarding on desktop used electron protocols to intercept and rewrite requests. We originally broke all port mapping when we moved the request intercepting to the main thread instead of being window specific.

Now however we use service workers to load resources inside of webviews, which is how the web version of VS Code has always worked. This fixes port mapping for me, with the exception that service workers currently cannot intercept requests for/from iframes.

@renkun-ken We can't workaround this issue in any reasonable way, so using vscode.env.asExternalUri is the best approach if you are trying to load an iframe inside a remote environment. In the future we could add a more specialized api for this, but it would probably just do the same thing that vscode.env.asExternalUri already does

I'm going to close this issue since as far as I know port mappings now works, except for known limitation related to iframes.

To verify:

  1. In the webview sample extension, apply:
diff --git a/webview-sample/src/extension.ts b/webview-sample/src/extension.ts
index 6349900..5e81aea 100644
--- a/webview-sample/src/extension.ts
+++ b/webview-sample/src/extension.ts
@@ -40,7 +40,10 @@ function getWebviewOptions(extensionUri: vscode.Uri): vscode.WebviewOptions {
 		enableScripts: true,
 
 		// And restrict the webview to only loading content from our extension's `media` directory.
-		localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'media')]
+		localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'media')],
+		portMapping: [
+			{ webviewPort: 8888, extensionHostPort: 9999 }
+		]
 	};
 }
 
@@ -189,24 +192,9 @@ class CatCodingPanel {
 			<head>
 				<meta charset="UTF-8">
 
-				<!--
-					Use a content security policy to only allow loading images from https or from our extension directory,
-					and only allow scripts that have a specific nonce.
-				-->
-				<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; img-src ${webview.cspSource} https:; script-src 'nonce-${nonce}';">
-
-				<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
-				<link href="${stylesResetUri}" rel="stylesheet">
-				<link href="${stylesMainUri}" rel="stylesheet">
-
-				<title>Cat Coding</title>
 			</head>
 			<body>
-				<img src="${catGifPath}" width="300" />
-				<h1 id="lines-of-code-counter">0</h1>
-
-				<script nonce="${nonce}" src="${scriptUri}"></script>
+				<img src="http://localhost:8888/image.png" />
 			</body>
 			</html>`;
 	}
  1. Package the extension
  2. Connect to the remote machine over ssh and install the extension on the remote
  3. On the remote, start up a server on port 9999
  4. Now run the Cat coding: start command
  5. Confirm you see the image inside the webview.

@mjbvz mjbvz closed this as completed Apr 15, 2021
@renkun-ken
Copy link
Author

renkun-ken commented Apr 15, 2021

@mjbvz Thanks for your detailed explanation. vscode.env.asExternalUri works quite nicely for a while.

Thanks again for keep tracking on this. Maybe it is worth mention in the documentation of WebView about the limitation of port mapping inside iframes.

@RMacfarlane RMacfarlane added the verified Verification succeeded label Apr 30, 2021
@github-actions github-actions bot locked and limited conversation to collaborators May 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
author-verification-requested Issues potentially verifiable by issue author bug Issue identified by VS Code Team member as probable bug electron Issues and items related to Electron upstream-issue-linked This is an upstream issue that has been reported upstream verified Verification succeeded webview Webview issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants
@deepak1556 @connor4312 @RMacfarlane @renkun-ken @tamuratak @mjbvz and others