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

Move off in Webview #206363

Merged
merged 18 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/vs/workbench/api/browser/mainThreadCodeInsets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { getWindow } from 'vs/base/browser/dom';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { isEqual } from 'vs/base/common/resources';
import { URI, UriComponents } from 'vs/base/common/uri';
Expand Down Expand Up @@ -88,14 +89,16 @@ export class MainThreadEditorInsets implements MainThreadEditorInsetsShape {
}

const disposables = new DisposableStore();
const codeWindow = getWindow(editor.getDomNode());

const webview = this._webviewService.createWebviewElement({
title: undefined,
options: {
enableFindWidget: false,
},
contentOptions: reviveWebviewContentOptions(options),
extension: { id: extensionId, location: URI.revive(extensionLocation) }
extension: { id: extensionId, location: URI.revive(extensionLocation) },
codeWindow: codeWindow
});

const webviewZone = new EditorWebviewZone(editor, line, height, webview);
Expand Down
4 changes: 3 additions & 1 deletion src/vs/workbench/api/browser/mainThreadWebviewPanels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { getActiveWindow } from 'vs/base/browser/dom';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Event } from 'vs/base/common/event';
import { Disposable, DisposableMap } from 'vs/base/common/lifecycle';
Expand Down Expand Up @@ -170,7 +171,8 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc
title: initData.title,
options: reviveWebviewOptions(initData.panelOptions),
contentOptions: reviveWebviewContentOptions(initData.webviewOptions),
extension
extension,
codeWindow: getActiveWindow()
bpasero marked this conversation as resolved.
Show resolved Hide resolved
}, this.webviewPanelViewType.fromExternal(viewType), initData.title, mainThreadShowOptions);

this.addWebviewInput(handle, webview, { serializeBuffersForPostMessage: initData.serializeBuffersForPostMessage });
Expand Down
11 changes: 11 additions & 0 deletions src/vs/workbench/browser/parts/editor/editorPane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { ITextResourceConfigurationChangeEvent, ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration';
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
import { getWindowById } from 'vs/base/browser/dom';

/**
* The base class of editors in the workbench. Editors register themselves for specific editor inputs.
Expand Down Expand Up @@ -163,6 +164,16 @@ export abstract class EditorPane extends Composite implements IEditorPane {
this._group = group;
}

getContainingWindow() {
let codeWindow;
rebornix marked this conversation as resolved.
Show resolved Hide resolved
if (this.group?.windowId) {
const windowById = getWindowById(this.group.windowId);
codeWindow = windowById?.window;
}

return codeWindow;
}

setBoundarySashes(_sashes: IBoundarySashes) {
// Subclasses can implement
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { getWindowById } from 'vs/base/browser/dom';
import { mainWindow } from 'vs/base/browser/window';
import { VSBuffer } from 'vs/base/common/buffer';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IReference } from 'vs/base/common/lifecycle';
Expand All @@ -22,6 +24,7 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { IOverlayWebview, IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';

Expand All @@ -43,12 +46,16 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
// If it's an untitled file we must populate the untitledDocumentData
const untitledString = accessor.get(IUntitledTextEditorService).getValue(resource);
const untitledDocumentData = untitledString ? VSBuffer.fromString(untitledString) : undefined;
const editorGroupService = accessor.get(IEditorGroupsService);
const windowId = group ? editorGroupService.getGroup(group)?.windowId : undefined;
rebornix marked this conversation as resolved.
Show resolved Hide resolved
const codeWindow = windowId ? (getWindowById(windowId)?.window ?? mainWindow) : mainWindow;
const webview = accessor.get(IWebviewService).createWebviewOverlay({
providedViewType: viewType,
title: undefined,
options: { customClasses: options?.customClasses },
contentOptions: {},
extension: undefined,
codeWindow
});
const input = instantiationService.createInstance(CustomEditorInput, { resource, viewType }, webview, { untitledDocumentData: untitledDocumentData, oldResource: options?.oldResource });
if (typeof group !== 'undefined') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { getActiveWindow } from 'vs/base/browser/dom';
import { CodeWindow } from 'vs/base/browser/window';
import { Disposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { isEqual } from 'vs/base/common/resources';
Expand Down Expand Up @@ -100,7 +102,7 @@ export class CustomEditorInputSerializer extends WebviewEditorInputSerializer {
}
}

function reviveWebview(webviewService: IWebviewService, data: { origin: string | undefined; viewType: string; state: any; webviewOptions: WebviewOptions; contentOptions: WebviewContentOptions; extension?: WebviewExtensionDescription }) {
function reviveWebview(webviewService: IWebviewService, data: { origin: string | undefined; viewType: string; state: any; webviewOptions: WebviewOptions; contentOptions: WebviewContentOptions; extension?: WebviewExtensionDescription; codeWindow: CodeWindow }) {
const webview = webviewService.createWebviewOverlay({
providedViewType: data.viewType,
origin: data.origin,
Expand All @@ -112,6 +114,7 @@ function reviveWebview(webviewService: IWebviewService, data: { origin: string |
},
contentOptions: data.contentOptions,
extension: data.extension,
codeWindow: data.codeWindow
});
webview.state = data.state;
return webview;
Expand Down Expand Up @@ -185,6 +188,7 @@ export class ComplexCustomWorkingCopyEditorHandler extends Disposable implements
contentOptions: restoreWebviewContentOptions(backupData.webview.options),
state: backupData.webview.state,
extension,
codeWindow: getActiveWindow()
rebornix marked this conversation as resolved.
Show resolved Hide resolved
});

const editor = this._instantiationService.createInstance(CustomEditorInput, { resource: URI.revive(backupData.editorResource), viewType: backupData.viewType }, webview, { backupId: backupData.backupId });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { $, Dimension, addDisposableListener, append, setParentFlowTo } from 'vs/base/browser/dom';
import { $, Dimension, addDisposableListener, append, getWindow, setParentFlowTo } from 'vs/base/browser/dom';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateFactory';
import { setupCustomHover } from 'vs/base/browser/ui/hover/updatableHoverWidget';
Expand Down Expand Up @@ -661,6 +661,8 @@ export class ExtensionEditor extends EditorPane {
return Promise.resolve(null);
}

const codeWindow = this.getContainingWindow() ?? getWindow(container);
rebornix marked this conversation as resolved.
Show resolved Hide resolved

const webview = this.contentDisposables.add(this.webviewService.createWebviewOverlay({
title,
options: {
Expand All @@ -670,16 +672,17 @@ export class ExtensionEditor extends EditorPane {
},
contentOptions: {},
extension: undefined,
codeWindow: codeWindow
}));

webview.initialScrollProgress = this.initialScrollProgress.get(webviewIndex) || 0;

webview.claim(this, this.scopedContextKeyService);
webview.claim(this, codeWindow, this.scopedContextKeyService);
setParentFlowTo(webview.container, container);
webview.layoutWebviewOverElement(container);

webview.setHtml(body);
webview.claim(this, undefined);
webview.claim(this, codeWindow, undefined);

this.contentDisposables.add(webview.onDidFocus(() => this.fireOnDidFocus()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import { IEditorOptions } from 'vs/platform/editor/common/editor';
import { cellIndexesToRanges, cellRangesToIndexes } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { NotebookDiffOverviewRuler } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffOverviewRuler';
import { registerZIndex, ZIndex } from 'vs/platform/layout/browser/zIndexRegistry';
import { mainWindow } from 'vs/base/browser/window';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';

const $ = DOM.$;
Expand Down Expand Up @@ -154,7 +153,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
@ICodeEditorService codeEditorService: ICodeEditorService
) {
super(NotebookTextDiffEditor.ID, telemetryService, themeService, storageService);
this._notebookOptions = new NotebookOptions(DOM.getWindowById(this.group?.windowId, true).window ?? mainWindow, this.configurationService, notebookExecutionStateService, codeEditorService, false);
this._notebookOptions = new NotebookOptions(DOM.getWindowById(this.group?.windowId, true).window, this.configurationService, notebookExecutionStateService, codeEditorService, false);
this._register(this._notebookOptions);
this._revealFirst = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
this.webview.mountTo(this.element);
this._register(this.webview);

this._register(new WebviewWindowDragMonitor(() => this.webview));
this._register(new WebviewWindowDragMonitor(codeWindow, () => this.webview));

const initializePromise = new DeferredPromise<void>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { SimpleSettingRenderer } from 'vs/workbench/contrib/markdown/browser/mar
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Schemas } from 'vs/base/common/network';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { getActiveWindow } from 'vs/base/browser/dom';

export class ReleaseNotesManager {
private readonly _simpleSettingRenderer: SimpleSettingRenderer;
Expand Down Expand Up @@ -104,7 +105,8 @@ export class ReleaseNotesManager {
localResourceRoots: [],
allowScripts: true
},
extension: undefined
extension: undefined,
codeWindow: getActiveWindow()
},
'releaseNotes',
title,
Expand Down
10 changes: 7 additions & 3 deletions src/vs/workbench/contrib/webview/browser/overlayWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Dimension } from 'vs/base/browser/dom';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { CodeWindow } from 'vs/base/browser/window';
import { Emitter } from 'vs/base/common/event';
import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
Expand Down Expand Up @@ -35,6 +36,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
private _options: WebviewOptions;

private _owner: any = undefined;
public _codeWindow: CodeWindow | undefined = undefined;

private readonly _scopedContextKeyService = this._register(new MutableDisposable<IScopedContextKeyService>());
private _findWidgetVisible: IContextKey<boolean> | undefined;
Expand Down Expand Up @@ -109,15 +111,16 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
return this._container.domNode;
}

public claim(owner: any, scopedContextKeyService: IContextKeyService | undefined) {
public claim(owner: any, codeWindow: CodeWindow, scopedContextKeyService: IContextKeyService | undefined) {
if (this._isDisposed) {
return;
}

const oldOwner = this._owner;

this._owner = owner;
this._show();
this._codeWindow = codeWindow;
this._show(codeWindow);

if (oldOwner !== owner) {
const contextKeyService = (scopedContextKeyService || this._baseContextKeyService);
Expand Down Expand Up @@ -184,7 +187,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
}
}

private _show() {
private _show(codeWindow: CodeWindow) {
if (this._isDisposed) {
throw new Error('OverlayWebview is disposed');
}
Expand All @@ -197,6 +200,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
options: this._options,
contentOptions: this._contentOptions,
extension: this.extension,
codeWindow: codeWindow
});
this._webview.value = webview;
webview.state = this._state;
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/webview/browser/webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export interface WebviewInitInfo {
readonly contentOptions: WebviewContentOptions;

readonly extension: WebviewExtensionDescription | undefined;
readonly codeWindow?: CodeWindow;
readonly codeWindow: CodeWindow;
}

export const enum WebviewContentPurpose {
Expand Down Expand Up @@ -308,7 +308,7 @@ export interface IOverlayWebview extends IWebview {
* @param claimant Identifier for the object claiming the webview.
* This must match the `claimant` passed to {@link IOverlayWebview.release}.
*/
claim(claimant: any, scopedContextKeyService: IContextKeyService | undefined): void;
claim(claimant: any, codeWindow: CodeWindow, scopedContextKeyService: IContextKeyService | undefined): void;

/**
* Release ownership of the webview.
Expand Down
27 changes: 18 additions & 9 deletions src/vs/workbench/contrib/webview/browser/webviewElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { isFirefox } from 'vs/base/browser/browser';
import { addDisposableListener, EventType, getActiveWindow } from 'vs/base/browser/dom';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { promiseWithResolvers, ThrottledDelayer } from 'vs/base/common/async';
import { streamToBuffer, VSBufferReadableStream } from 'vs/base/common/buffer';
Expand Down Expand Up @@ -37,7 +37,7 @@ import { WebviewFindDelegate, WebviewFindWidget } from 'vs/workbench/contrib/web
import { FromWebviewMessage, KeyEvent, ToWebviewMessage } from 'vs/workbench/contrib/webview/browser/webviewMessages';
import { decodeAuthority, webviewGenericCspSource, webviewRootResourceAuthority } from 'vs/workbench/contrib/webview/common/webview';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { $window } from 'vs/base/browser/window';
import { CodeWindow } from 'vs/base/browser/window';

interface WebviewContent {
readonly html: string;
Expand Down Expand Up @@ -88,6 +88,14 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
*/
public readonly origin: string;

private readonly _codeWindow: CodeWindow;

/**
* The code window the webview is contained within.
*/
public get codeWindow(): CodeWindow { return this._codeWindow; }
bpasero marked this conversation as resolved.
Show resolved Hide resolved


private readonly _encodedWebviewOriginPromise: Promise<string>;
private _encodedWebviewOrigin: string | undefined;

Expand All @@ -103,7 +111,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
if (!this._focused) {
return false;
}
if ($window.document.activeElement && $window.document.activeElement !== this.element) {
if (this._codeWindow.document.activeElement && this._codeWindow.document.activeElement !== this.element) {
// looks like https://github.com/microsoft/vscode/issues/132641
// where the focus is actually not in the `<iframe>`
return false;
Expand Down Expand Up @@ -159,8 +167,9 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD

this.providedViewType = initInfo.providedViewType;
this.origin = initInfo.origin ?? this.id;
this._codeWindow = initInfo.codeWindow;

this._encodedWebviewOriginPromise = parentOriginHash($window.origin, this.origin).then(id => this._encodedWebviewOrigin = id);
this._encodedWebviewOriginPromise = parentOriginHash(this._codeWindow.origin, this.origin).then(id => this._encodedWebviewOrigin = id);

this._options = initInfo.options;
this.extension = initInfo.extension;
Expand All @@ -180,7 +189,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD

this._element = this._createElement(initInfo.options, initInfo.contentOptions);

const subscription = this._register(addDisposableListener(initInfo.codeWindow ?? getActiveWindow(), 'message', (e: MessageEvent) => {
const subscription = this._register(addDisposableListener(this._codeWindow, 'message', (e: MessageEvent) => {
if (!this._encodedWebviewOrigin || e?.data?.target !== this.id) {
return;
}
Expand Down Expand Up @@ -460,7 +469,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
extensionId: extension?.id.value ?? '',
platform: this.platform,
'vscode-resource-base-authority': webviewRootResourceAuthority,
parentOrigin: $window.origin,
parentOrigin: this._codeWindow.origin,
};

if (this._options.disableServiceWorker) {
Expand Down Expand Up @@ -500,7 +509,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
}));
}

for (const node of [element, $window]) {
for (const node of [element, this._codeWindow]) {
this._register(addDisposableListener(node, EventType.DRAG_END, () => {
this._stopBlockingIframeDragEvents();
}));
Expand Down Expand Up @@ -683,7 +692,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
get: () => this.element,
});
// And re-dispatch
$window.dispatchEvent(emulatedKeyboardEvent);
this._codeWindow.dispatchEvent(emulatedKeyboardEvent);
}

windowDidDragStart(): void {
Expand Down Expand Up @@ -825,7 +834,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
return;
}

if ($window.document.activeElement && $window.document.activeElement !== this.element && $window.document.activeElement?.tagName !== 'BODY') {
if (this._codeWindow.document.activeElement && this._codeWindow.document.activeElement !== this.element && this._codeWindow.document.activeElement?.tagName !== 'BODY') {
return;
}

Expand Down
Loading
Loading