Add acquireVsCodeApi to get handle to vscode api inside webview

Fixes #48540
This commit is contained in:
Matt Bierner
2018-04-25 22:27:51 -07:00
parent 6d7bb1a174
commit 82d97b4c3c
8 changed files with 155 additions and 118 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,33 +3,48 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { MessagePoster } from './messaging';
import { getSettings } from './settings'; import { getSettings } from './settings';
import { getStrings } from './strings'; import { getStrings } from './strings';
import { postCommand } from './messaging';
/** /**
* Shows an alert when there is a content security policy violation. * Shows an alert when there is a content security policy violation.
*/ */
export class CspAlerter { export class CspAlerter {
private didShow = false; private didShow = false;
private didHaveCspWarning = false;
private messaging?: MessagePoster;
constructor() { constructor() {
document.addEventListener('securitypolicyviolation', () => { document.addEventListener('securitypolicyviolation', () => {
this.showCspWarning(); this.onCspWarning();
}); });
window.addEventListener('message', (event) => { window.addEventListener('message', (event) => {
if (event && event.data && event.data.name === 'vscode-did-block-svg') { if (event && event.data && event.data.name === 'vscode-did-block-svg') {
this.showCspWarning(); this.onCspWarning();
} }
}); });
} }
public setPoster(poster: MessagePoster) {
this.messaging = poster;
if (this.didHaveCspWarning) {
this.showCspWarning();
}
}
private onCspWarning() {
this.didHaveCspWarning = true;
this.showCspWarning();
}
private showCspWarning() { private showCspWarning() {
const strings = getStrings(); const strings = getStrings();
const settings = getSettings(); const settings = getSettings();
if (this.didShow || settings.disableSecurityWarnings) { if (this.didShow || settings.disableSecurityWarnings || !this.messaging) {
return; return;
} }
this.didShow = true; this.didShow = true;
@@ -42,7 +57,7 @@ export class CspAlerter {
notification.setAttribute('role', 'button'); notification.setAttribute('role', 'button');
notification.setAttribute('aria-label', strings.cspAlertMessageLabel); notification.setAttribute('aria-label', strings.cspAlertMessageLabel);
notification.onclick = () => { notification.onclick = () => {
postCommand('markdown.showPreviewSecuritySelector', [settings.source]); this.messaging!.postCommand('markdown.showPreviewSecuritySelector', [settings.source]);
}; };
document.body.appendChild(notification); document.body.appendChild(notification);
} }

View File

@@ -3,17 +3,27 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { getSettings } from './settings';
import { postCommand, postMessage } from './messaging';
import { onceDocumentLoaded } from './events';
import { getEditorLineNumberForPageOffset, scrollToRevealSourceLine } from './scroll-sync';
import { ActiveLineMarker } from './activeLineMarker'; import { ActiveLineMarker } from './activeLineMarker';
import { onceDocumentLoaded } from './events';
import { createPosterForVsCode } from './messaging';
import { getEditorLineNumberForPageOffset, scrollToRevealSourceLine } from './scroll-sync';
import { getSettings } from './settings';
import throttle = require('lodash.throttle'); import throttle = require('lodash.throttle');
declare var acquireVsCodeApi: any;
var scrollDisabled = true; var scrollDisabled = true;
const marker = new ActiveLineMarker(); const marker = new ActiveLineMarker();
const settings = getSettings(); const settings = getSettings();
const vscode = acquireVsCodeApi();
vscode.postMessage({});
const messaging = createPosterForVsCode(vscode);
window.cspAlerter.setPoster(messaging);
window.styleLoadingMonitor.setPoster(messaging);
onceDocumentLoaded(() => { onceDocumentLoaded(() => {
if (settings.scrollPreviewWithEditor) { if (settings.scrollPreviewWithEditor) {
setTimeout(() => { setTimeout(() => {
@@ -75,7 +85,7 @@ document.addEventListener('dblclick', event => {
const offset = event.pageY; const offset = event.pageY;
const line = getEditorLineNumberForPageOffset(offset); const line = getEditorLineNumberForPageOffset(offset);
if (typeof line === 'number' && !isNaN(line)) { if (typeof line === 'number' && !isNaN(line)) {
postMessage('didClick', { line: Math.floor(line) }); messaging.postMessage('didClick', { line: Math.floor(line) });
} }
}); });
@@ -92,7 +102,7 @@ document.addEventListener('click', event => {
} }
if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:')) { if (node.href.startsWith('file://') || node.href.startsWith('vscode-resource:')) {
const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').split('#'); const [path, fragment] = node.href.replace(/^(file:\/\/|vscode-resource:)/i, '').split('#');
postCommand('_markdown.openDocumentLink', [{ path, fragment }]); messaging.postCommand('_markdown.openDocumentLink', [{ path, fragment }]);
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
break; break;
@@ -110,7 +120,7 @@ if (settings.scrollEditorWithPreview) {
} else { } else {
const line = getEditorLineNumberForPageOffset(window.scrollY); const line = getEditorLineNumberForPageOffset(window.scrollY);
if (typeof line === 'number' && !isNaN(line)) { if (typeof line === 'number' && !isNaN(line)) {
postMessage('revealLine', { line }); messaging.postMessage('revealLine', { line });
} }
} }
}, 50)); }, 50));

View File

@@ -2,10 +2,13 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { postCommand } from './messaging'; import { MessagePoster } from './messaging';
export class StyleLoadingMonitor { export class StyleLoadingMonitor {
private unloadedStyles: string[] = []; private unloadedStyles: string[] = [];
private finishedLoading: boolean = false;
private poster?: MessagePoster;
constructor() { constructor() {
const onStyleLoadError = (event: any) => { const onStyleLoadError = (event: any) => {
@@ -25,7 +28,17 @@ export class StyleLoadingMonitor {
if (!this.unloadedStyles.length) { if (!this.unloadedStyles.length) {
return; return;
} }
postCommand('_markdown.onPreviewStyleLoadError', [this.unloadedStyles]); this.finishedLoading = true;
if (this.poster) {
this.poster.postCommand('_markdown.onPreviewStyleLoadError', [this.unloadedStyles]);
}
}); });
} }
public setPoster(poster: MessagePoster): void {
this.poster = poster;
if (this.finishedLoading) {
poster.postCommand('_markdown.onPreviewStyleLoadError', [this.unloadedStyles]);
}
}
} }

View File

@@ -5,22 +5,31 @@
import { getSettings } from './settings'; import { getSettings } from './settings';
declare var vscode: any; export interface MessagePoster {
/**
* Post a message to the markdown extension
*/
postMessage(type: string, body: object): void;
/**
* Post a message to the markdown extension /**
*/ * Post a command to be executed to the markdown extension
export function postMessage(type: string, body: object) { */
vscode.postMessage({ postCommand(command: string, args: any[]): void;
type,
source: getSettings().source,
body
});
} }
/** export const createPosterForVsCode = (vscode: any) => {
* Post a command to be executed to the markdown extension return new class implements MessagePoster {
*/ postMessage(type: string, body: object): void {
export function postCommand(command: string, args: any[]) { vscode.postMessage({
postMessage('command', { command, args }); type,
} source: getSettings().source,
body
});
}
postCommand(command: string, args: any[]) {
this.postMessage('command', { command, args });
}
};
};

View File

@@ -6,8 +6,12 @@
import { CspAlerter } from './csp'; import { CspAlerter } from './csp';
import { StyleLoadingMonitor } from './loading'; import { StyleLoadingMonitor } from './loading';
// tslint:disable-next-line:no-unused-expression declare global {
new CspAlerter(); interface Window {
cspAlerter: CspAlerter;
styleLoadingMonitor: StyleLoadingMonitor;
}
}
// tslint:disable-next-line:no-unused-expression window.cspAlerter = new CspAlerter();
new StyleLoadingMonitor(); window.styleLoadingMonitor = new StyleLoadingMonitor();

View File

@@ -178,15 +178,25 @@
if (enableWrappedPostMessage) { if (enableWrappedPostMessage) {
const defaultScript = newDocument.createElement('script'); const defaultScript = newDocument.createElement('script');
defaultScript.textContent = ` defaultScript.textContent = `
const vscode = Object.freeze((function() { const acquireVsCodeApi = (function() {
const originalPostMessage = window.parent.postMessage.bind(window.parent); const originalPostMessage = window.parent.postMessage.bind(window.parent);
return { let acquired = false;
postMessage: function(msg) {
return originalPostMessage(msg, '*'); return () => {
if (acquired) {
throw new Error('An instance of the VS Code API has already been acquired');
} }
acquired = true;
return Object.freeze({
postMessage: function(msg) {
return originalPostMessage(msg, '*');
}
});
}; };
})()); })();
delete window.parent; delete window.parent;
delete window.top;
delete window.frameElement;
`; `;
if (newDocument.head.hasChildNodes()) { if (newDocument.head.hasChildNodes()) {