Skip to content

Commit

Permalink
fix webview on local html files by sending the HTML files content via…
Browse files Browse the repository at this point in the history
… TCP
  • Loading branch information
Tal Hadad committed Aug 4, 2023
1 parent 9f300ee commit db53c60
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 22 deletions.
26 changes: 24 additions & 2 deletions R/session/vsc.R
Original file line number Diff line number Diff line change
Expand Up @@ -878,8 +878,30 @@ show_webview <- function(url, title, ..., viewer) {
request_browser(url = url, title = title, ..., viewer = FALSE)
} else if (file.exists(url)) {
file <- normalizePath(url, "/", mustWork = TRUE)
# TODO: On TCP connection, need to send file content via TCP and display it
request("webview", file = file, title = title, viewer = viewer, ...)
file_basename <- basename(file)
dir <- dirname(file)
lib_dir <- file.path(dir, "lib")
if (!is.na(request_tcp_connection) && file_basename == "index.html" && file.exists(lib_dir)) {
# pass detailed content via TCP, instead of just give a path to HTML
lib_dir_absolute <- normalizePath(path.expand(lib_dir), "/", mustWork = TRUE)
lib_files_path_relative <- file.path(
"lib",
list.files(lib_dir_absolute, all.files = TRUE, recursive = TRUE)
)
files_path_relative <- c(lib_files_path_relative, file_basename)

files_content_base64 <- setNames(
lapply(files_path_relative, function(file_path) {
raw_content <- readr::read_file_raw(file.path(dir, file_path))
jsonlite::base64_enc(raw_content)
}),
files_path_relative
)
request("webview", file = file_basename, files_content_base64 = files_content_base64,
title = title, viewer = viewer, ...)
} else {
request("webview", file = file, title = title, viewer = viewer, ...)
}
} else {
stop("File not exists")
}
Expand Down
3 changes: 2 additions & 1 deletion src/liveShare/shareSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export type IRequest = {
type?: string;
title?: string;
file?: string;
files_content_base64?: Record<string, string>;
viewer?: string;
plot?: string;
format?: string;
Expand Down Expand Up @@ -152,7 +153,7 @@ export async function updateGuestRequest(file: string, force: boolean = false):
}
case 'webview': {
if (request.file && request.title && request.viewer !== undefined) {
await showWebView(request.file, request.title, request.viewer);
await showWebView(request.file, request.files_content_base64, request.title, request.viewer);
}
break;
}
Expand Down
40 changes: 22 additions & 18 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ import * as fs from 'fs-extra';
import * as os from 'os';
import * as path from 'path';
import { Agent } from 'http';
import * as tmp from 'tmp';
import { AddressInfo, Server, Socket } from 'node:net';
import { PromiseSocket } from 'promise-socket';
import fetch from 'node-fetch';
import { commands, StatusBarItem, Uri, ViewColumn, Webview, window, workspace, env, WebviewPanelOnDidChangeViewStateEvent, WebviewPanel } from 'vscode';

import { runTextInTerm } from './rTerminal';
import { FSWatcher } from 'fs-extra';
import { config, createWaiterForInvoker, readContent, setContext, UriIcon } from './util';
import { config, createTempDir2, createTempFile, createWaiterForInvoker, readContent, setContext, UriIcon } from './util';
import { purgeAddinPickerItems, dispatchRStudioAPICall } from './rstudioapi';

import { IRequest } from './liveShare/shareSession';
Expand Down Expand Up @@ -383,12 +382,29 @@ export function openExternalBrowser(): void {
}
}

export async function showWebView(file: string, title: string, viewer: string | boolean): Promise<void> {
export async function showWebView(file: string, files_content_base64: Record<string, string> | undefined,
title: string, viewer: string | boolean): Promise<void> {
console.info(`[showWebView] file: ${file}, viewer: ${viewer.toString()}`);
if (viewer === false) {
void env.openExternal(Uri.file(file));
} else {
const dir = path.dirname(file);
let dir: string;
if (files_content_base64 !== undefined) {
dir = (await createTempDir2()).path;
const subdirs = new Set(Object.keys(files_content_base64).map((relativePath) => path.dirname(relativePath)));
subdirs.delete('');
subdirs.delete('.');
await Promise.all(
Array.from(subdirs).map((subdir) => fs.mkdir(path.join(dir, subdir), { recursive: true }))
);
await Promise.all(Object.entries(files_content_base64).map(async ([realtivePath, contentBase64]) => {
const arrayData = Buffer.from(contentBase64, 'base64');
return fs.writeFile(path.join(dir, realtivePath), arrayData);
}));
file = path.join(dir, file);
} else {
dir = path.dirname(file);
}
const webviewDir = extensionContext.asAbsolutePath('html/session/webview/');
const panel = window.createWebviewPanel('webview', title,
{
Expand Down Expand Up @@ -945,18 +961,6 @@ function startIncomingRequestServer(sessionStatusBarItem: StatusBarItem) {
return server;
}

const create_tmp_file: (options: tmp.FileOptions) => Promise<{ name: string, fd: number, removeCallback: () => void }> =
(options) => new Promise((resolve, reject) => {
tmp.file(options, (err, name, fd, removeCallback) => {
if (err) {
reject(err);
} else {
resolve({ name, fd, removeCallback });
}
});
}
);

export async function processRequest(request: ISessionRequest, socket: Socket | null, sessionStatusBarItem: StatusBarItem) {
switch (request.command) {
case 'help': {
Expand Down Expand Up @@ -1033,7 +1037,7 @@ export async function processRequest(request: ISessionRequest, socket: Socket |
}
case 'webview': {
if (request.file && request.title && request.viewer !== undefined) {
await showWebView(request.file, request.title, request.viewer);
await showWebView(request.file, request.files_content_base64, request.title, request.viewer);
}
break;
}
Expand All @@ -1051,7 +1055,7 @@ export async function processRequest(request: ISessionRequest, socket: Socket |
}

if (request.plot_base64) {
const { name: filePath, fd } = await create_tmp_file({ postfix: '.png' });
const { name: filePath, fd } = await createTempFile({ postfix: '.png' });
const arrayData = Buffer.from(request.plot_base64, 'base64');
await fs.writeFile(fd, arrayData);
showPlot(filePath);
Expand Down
27 changes: 26 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { existsSync, PathLike, readFile } from 'fs-extra';
import * as fs from 'fs';
import * as tmp from 'tmp';
import winreg = require('winreg');
import * as path from 'path';
import * as vscode from 'vscode';
Expand Down Expand Up @@ -663,4 +664,28 @@ export function createWaiterForInvoker() {
});

return { invoker, waiter };
}
}

export const createTempFile: (options: tmp.FileOptions) => Promise<{ name: string, fd: number, removeCallback: () => void }> =
(options) => new Promise((resolve, reject) => {
tmp.file(options, (err, name, fd, removeCallback) => {
if (err) {
reject(err);
} else {
resolve({ name, fd, removeCallback });
}
});
}
);

export const createTempDir2: () => Promise<{ path: string, removeCallback: () => void }> =
() => new Promise((resolve, reject) => {
tmp.dir((err, path, removeCallback) => {
if (err) {
reject(err);
} else {
resolve({ path, removeCallback });
}
});
}
);

0 comments on commit db53c60

Please sign in to comment.