mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode bead496a613e475819f89f08e9e882b841bc1fe8 (#14883)
* Merge from vscode bead496a613e475819f89f08e9e882b841bc1fe8 * Bump distro * Upgrade GCC to 4.9 due to yarn install errors * Update build image * Fix bootstrap base url * Bump distro * Fix build errors * Update source map file * Disable checkbox for blocking migration issues (#15131) * disable checkbox for blocking issues * wip * disable checkbox fixes * fix strings * Remove duplicate tsec command * Default to off for tab color if settings not present * re-skip failing tests * Fix mocha error * Bump sqlite version & fix notebooks search view * Turn off esbuild warnings * Update esbuild log level * Fix overflowactionbar tests * Fix ts-ignore in dropdown tests * cleanup/fixes * Fix hygiene * Bundle in entire zone.js module * Remove extra constructor param * bump distro for web compile break * bump distro for web compile break v2 * Undo log level change * New distro * Fix integration test scripts * remove the "no yarn.lock changes" workflow * fix scripts v2 * Update unit test scripts * Ensure ads-kerberos2 updates in .vscodeignore * Try fix unit tests * Upload crash reports * remove nogpu * always upload crashes * Use bash script * Consolidate data/ext dir names * Create in tmp directory Co-authored-by: chlafreniere <hichise@gmail.com> Co-authored-by: Christopher Suh <chsuh@microsoft.com> Co-authored-by: chgagnon <chgagnon@microsoft.com>
This commit is contained in:
@@ -9,6 +9,9 @@ import { isUNC } from 'vs/base/common/extpath';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { sep } from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IHeaders } from 'vs/base/parts/request/common/request';
|
||||
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IRemoteConnectionData } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { IRequestService } from 'vs/platform/request/common/request';
|
||||
import { getWebviewContentMimeType } from 'vs/platform/webview/common/mimeTypes';
|
||||
@@ -17,39 +20,99 @@ import { getWebviewContentMimeType } from 'vs/platform/webview/common/mimeTypes'
|
||||
export const webviewPartitionId = 'webview';
|
||||
|
||||
export namespace WebviewResourceResponse {
|
||||
export enum Type { Success, Failed, AccessDenied }
|
||||
export enum Type { Success, Failed, AccessDenied, NotModified }
|
||||
|
||||
export class StreamSuccess {
|
||||
readonly type = Type.Success;
|
||||
|
||||
constructor(
|
||||
public readonly stream: VSBufferReadableStream,
|
||||
public readonly mimeType: string
|
||||
public readonly etag: string | undefined,
|
||||
public readonly mimeType: string,
|
||||
) { }
|
||||
}
|
||||
|
||||
export const Failed = { type: Type.Failed } as const;
|
||||
export const AccessDenied = { type: Type.AccessDenied } as const;
|
||||
|
||||
export type StreamResponse = StreamSuccess | typeof Failed | typeof AccessDenied;
|
||||
export class NotModified {
|
||||
readonly type = Type.NotModified;
|
||||
|
||||
constructor(
|
||||
public readonly mimeType: string,
|
||||
) { }
|
||||
}
|
||||
|
||||
export type StreamResponse = StreamSuccess | typeof Failed | typeof AccessDenied | NotModified;
|
||||
}
|
||||
|
||||
interface FileReader {
|
||||
readFileStream(resource: URI): Promise<VSBufferReadableStream>;
|
||||
export namespace WebviewFileReadResponse {
|
||||
export enum Type { Success, NotModified }
|
||||
|
||||
export class StreamSuccess {
|
||||
readonly type = Type.Success;
|
||||
|
||||
constructor(
|
||||
public readonly stream: VSBufferReadableStream,
|
||||
public readonly etag: string | undefined
|
||||
) { }
|
||||
}
|
||||
|
||||
export const NotModified = { type: Type.NotModified } as const;
|
||||
|
||||
export type Response = StreamSuccess | typeof NotModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a call to `IFileService.readFileStream` and converts the result to a `WebviewFileReadResponse.Response`
|
||||
*/
|
||||
export async function readFileStream(
|
||||
fileService: IFileService,
|
||||
resource: URI,
|
||||
etag: string | undefined,
|
||||
): Promise<WebviewFileReadResponse.Response> {
|
||||
try {
|
||||
const result = await fileService.readFileStream(resource, { etag });
|
||||
return new WebviewFileReadResponse.StreamSuccess(result.value, result.etag);
|
||||
} catch (e) {
|
||||
if (e instanceof FileOperationError) {
|
||||
const result = e.fileOperationResult;
|
||||
|
||||
// NotModified status is expected and can be handled gracefully
|
||||
if (result === FileOperationResult.FILE_NOT_MODIFIED_SINCE) {
|
||||
return WebviewFileReadResponse.NotModified;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise the error is unexpected. Re-throw and let caller handle it
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export interface WebviewResourceFileReader {
|
||||
readFileStream(resource: URI, etag: string | undefined): Promise<WebviewFileReadResponse.Response>;
|
||||
}
|
||||
|
||||
export async function loadLocalResource(
|
||||
requestUri: URI,
|
||||
ifNoneMatch: string | undefined,
|
||||
options: {
|
||||
extensionLocation: URI | undefined;
|
||||
roots: ReadonlyArray<URI>;
|
||||
remoteConnectionData?: IRemoteConnectionData | null;
|
||||
rewriteUri?: (uri: URI) => URI,
|
||||
},
|
||||
fileReader: FileReader,
|
||||
fileReader: WebviewResourceFileReader,
|
||||
requestService: IRequestService,
|
||||
logService: ILogService,
|
||||
token: CancellationToken,
|
||||
): Promise<WebviewResourceResponse.StreamResponse> {
|
||||
logService.debug(`loadLocalResource - being. requestUri=${requestUri}`);
|
||||
|
||||
let resourceToLoad = getResourceToLoad(requestUri, options.roots);
|
||||
|
||||
logService.debug(`loadLocalResource - found resource to load. requestUri=${requestUri}, resourceToLoad=${resourceToLoad}`);
|
||||
|
||||
if (!resourceToLoad) {
|
||||
return WebviewResourceResponse.AccessDenied;
|
||||
}
|
||||
@@ -62,18 +125,43 @@ export async function loadLocalResource(
|
||||
}
|
||||
|
||||
if (resourceToLoad.scheme === Schemas.http || resourceToLoad.scheme === Schemas.https) {
|
||||
const response = await requestService.request({ url: resourceToLoad.toString(true) }, CancellationToken.None);
|
||||
const headers: IHeaders = {};
|
||||
if (ifNoneMatch) {
|
||||
headers['If-None-Match'] = ifNoneMatch;
|
||||
}
|
||||
|
||||
const response = await requestService.request({
|
||||
url: resourceToLoad.toString(true),
|
||||
headers: headers
|
||||
}, token);
|
||||
|
||||
logService.debug(`loadLocalResource - Loaded over http(s). requestUri=${requestUri}, response=${response.res.statusCode}`);
|
||||
|
||||
if (response.res.statusCode === 200) {
|
||||
return new WebviewResourceResponse.StreamSuccess(response.stream, mime);
|
||||
return new WebviewResourceResponse.StreamSuccess(response.stream, response.res.headers['etag'], mime);
|
||||
}
|
||||
return WebviewResourceResponse.Failed;
|
||||
}
|
||||
|
||||
try {
|
||||
const contents = await fileReader.readFileStream(resourceToLoad);
|
||||
return new WebviewResourceResponse.StreamSuccess(contents, mime);
|
||||
const contents = await fileReader.readFileStream(resourceToLoad, ifNoneMatch);
|
||||
logService.debug(`loadLocalResource - Loaded using fileReader. requestUri=${requestUri}`);
|
||||
|
||||
switch (contents.type) {
|
||||
case WebviewFileReadResponse.Type.Success:
|
||||
return new WebviewResourceResponse.StreamSuccess(contents.stream, contents.etag, mime);
|
||||
|
||||
case WebviewFileReadResponse.Type.NotModified:
|
||||
return new WebviewResourceResponse.NotModified(mime);
|
||||
|
||||
default:
|
||||
logService.error(`loadLocalResource - Unknown file read response`);
|
||||
return WebviewResourceResponse.Failed;
|
||||
}
|
||||
} catch (err) {
|
||||
logService.debug(`loadLocalResource - Error using fileReader. requestUri=${requestUri}`);
|
||||
console.log(err);
|
||||
|
||||
return WebviewResourceResponse.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ export interface WebviewWindowId {
|
||||
readonly windowId: number;
|
||||
}
|
||||
|
||||
export type WebviewManagerDidLoadResourceResponse =
|
||||
{ buffer: VSBuffer, etag: string | undefined }
|
||||
| 'not-modified'
|
||||
| 'access-denied'
|
||||
| 'not-found';
|
||||
|
||||
export interface IWebviewManagerService {
|
||||
_serviceBrand: unknown;
|
||||
|
||||
@@ -26,7 +32,7 @@ export interface IWebviewManagerService {
|
||||
unregisterWebview(id: string): Promise<void>;
|
||||
updateWebviewMetadata(id: string, metadataDelta: Partial<RegisterWebviewMetadata>): Promise<void>;
|
||||
|
||||
didLoadResource(requestId: number, content: VSBuffer | undefined): void;
|
||||
didLoadResource(requestId: number, response: WebviewManagerDidLoadResourceResponse): void;
|
||||
|
||||
setIgnoreMenuShortcuts(id: WebviewWebContentsId | WebviewWindowId, enabled: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface IWebviewPortMapping {
|
||||
*/
|
||||
export class WebviewPortMappingManager implements IDisposable {
|
||||
|
||||
private readonly _tunnels = new Map<number, Promise<RemoteTunnel>>();
|
||||
private readonly _tunnels = new Map<number, RemoteTunnel>();
|
||||
|
||||
constructor(
|
||||
private readonly _getExtensionLocation: () => URI | undefined,
|
||||
@@ -60,19 +60,19 @@ export class WebviewPortMappingManager implements IDisposable {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
async dispose() {
|
||||
for (const tunnel of this._tunnels.values()) {
|
||||
tunnel.then(tunnel => tunnel.dispose());
|
||||
await tunnel.dispose();
|
||||
}
|
||||
this._tunnels.clear();
|
||||
}
|
||||
|
||||
private getOrCreateTunnel(remoteAuthority: IAddress, remotePort: number): Promise<RemoteTunnel> | undefined {
|
||||
private async getOrCreateTunnel(remoteAuthority: IAddress, remotePort: number): Promise<RemoteTunnel | undefined> {
|
||||
const existing = this._tunnels.get(remotePort);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
const tunnel = this.tunnelService.openTunnel({ getAddress: async () => remoteAuthority }, undefined, remotePort);
|
||||
const tunnel = await this.tunnelService.openTunnel({ getAddress: async () => remoteAuthority }, undefined, remotePort);
|
||||
if (tunnel) {
|
||||
this._tunnels.set(remotePort, tunnel);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user