Use javascript modules for webview host script
This commit is contained in:
parent
b4d42b1424
commit
62c62103fc
4 changed files with 735 additions and 750 deletions
|
@ -3,115 +3,112 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
// @ts-check
|
||||
(function () {
|
||||
const id = document.location.search.match(/\bid=([\w-]+)/)[1];
|
||||
const onElectron = /platform=electron/.test(document.location.search);
|
||||
|
||||
const hostMessaging = new class HostMessaging {
|
||||
constructor() {
|
||||
/** @type {Map<string, Array<(event: MessageEvent, data: any) => void>>} */
|
||||
this.handlers = new Map();
|
||||
import { createWebviewManager } from './main.js';
|
||||
|
||||
window.addEventListener('message', (e) => {
|
||||
const channel = e.data.channel;
|
||||
const handlers = this.handlers.get(channel);
|
||||
if (handlers) {
|
||||
for (const handler of handlers) {
|
||||
handler(e, e.data.args);
|
||||
}
|
||||
} else {
|
||||
console.log('no handler for ', e);
|
||||
const id = document.location.search.match(/\bid=([\w-]+)/)[1];
|
||||
const onElectron = /platform=electron/.test(document.location.search);
|
||||
|
||||
const hostMessaging = new class HostMessaging {
|
||||
constructor() {
|
||||
/** @type {Map<string, Array<(event: MessageEvent, data: any) => void>>} */
|
||||
this.handlers = new Map();
|
||||
|
||||
window.addEventListener('message', (e) => {
|
||||
const channel = e.data.channel;
|
||||
const handlers = this.handlers.get(channel);
|
||||
if (handlers) {
|
||||
for (const handler of handlers) {
|
||||
handler(e, e.data.args);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {any} data
|
||||
*/
|
||||
postMessage(channel, data) {
|
||||
window.parent.postMessage({ target: id, channel, data }, '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: MessageEvent, data: any) => void} handler
|
||||
*/
|
||||
onMessage(channel, handler) {
|
||||
let handlers = this.handlers.get(channel);
|
||||
if (!handlers) {
|
||||
handlers = [];
|
||||
this.handlers.set(channel, handlers);
|
||||
} else {
|
||||
console.log('no handler for ', e);
|
||||
}
|
||||
handlers.push(handler);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {any} data
|
||||
*/
|
||||
postMessage(channel, data) {
|
||||
window.parent.postMessage({ target: id, channel, data }, '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} channel
|
||||
* @param {(event: MessageEvent, data: any) => void} handler
|
||||
*/
|
||||
onMessage(channel, handler) {
|
||||
let handlers = this.handlers.get(channel);
|
||||
if (!handlers) {
|
||||
handlers = [];
|
||||
this.handlers.set(channel, handlers);
|
||||
}
|
||||
}();
|
||||
handlers.push(handler);
|
||||
}
|
||||
}();
|
||||
|
||||
const unloadMonitor = new class {
|
||||
|
||||
const unloadMonitor = new class {
|
||||
constructor() {
|
||||
this.confirmBeforeClose = 'keyboardOnly';
|
||||
this.isModifierKeyDown = false;
|
||||
|
||||
constructor() {
|
||||
this.confirmBeforeClose = 'keyboardOnly';
|
||||
this.isModifierKeyDown = false;
|
||||
hostMessaging.onMessage('set-confirm-before-close', (_e, /** @type {string} */ data) => {
|
||||
this.confirmBeforeClose = data;
|
||||
});
|
||||
|
||||
hostMessaging.onMessage('set-confirm-before-close', (_e, /** @type {string} */ data) => {
|
||||
this.confirmBeforeClose = data;
|
||||
});
|
||||
hostMessaging.onMessage('content', (_e, /** @type {any} */ data) => {
|
||||
this.confirmBeforeClose = data.confirmBeforeClose;
|
||||
});
|
||||
|
||||
hostMessaging.onMessage('content', (_e, /** @type {any} */ data) => {
|
||||
this.confirmBeforeClose = data.confirmBeforeClose;
|
||||
});
|
||||
window.addEventListener('beforeunload', (event) => {
|
||||
if (onElectron) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', (event) => {
|
||||
if (onElectron) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.confirmBeforeClose) {
|
||||
case 'always':
|
||||
{
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
case 'never':
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 'keyboardOnly':
|
||||
default: {
|
||||
if (this.isModifierKeyDown) {
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
switch (this.confirmBeforeClose) {
|
||||
case 'always':
|
||||
{
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
case 'never':
|
||||
{
|
||||
break;
|
||||
}
|
||||
case 'keyboardOnly':
|
||||
default: {
|
||||
if (this.isModifierKeyDown) {
|
||||
event.preventDefault();
|
||||
event.returnValue = '';
|
||||
return '';
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onIframeLoaded(/** @type {HTMLIFrameElement} */frame) {
|
||||
frame.contentWindow.addEventListener('keydown', e => {
|
||||
this.isModifierKeyDown = e.metaKey || e.ctrlKey || e.altKey;
|
||||
});
|
||||
onIframeLoaded(/** @type {HTMLIFrameElement} */frame) {
|
||||
frame.contentWindow.addEventListener('keydown', e => {
|
||||
this.isModifierKeyDown = e.metaKey || e.ctrlKey || e.altKey;
|
||||
});
|
||||
|
||||
frame.contentWindow.addEventListener('keyup', () => {
|
||||
this.isModifierKeyDown = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
frame.contentWindow.addEventListener('keyup', () => {
|
||||
this.isModifierKeyDown = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/** @type {import('./main').WebviewHost} */
|
||||
const host = {
|
||||
postMessage: hostMessaging.postMessage.bind(hostMessaging),
|
||||
onMessage: hostMessaging.onMessage.bind(hostMessaging),
|
||||
onElectron: onElectron,
|
||||
useParentPostMessage: false,
|
||||
onIframeLoaded: (/** @type {HTMLIFrameElement} */ frame) => {
|
||||
unloadMonitor.onIframeLoaded(frame);
|
||||
}
|
||||
};
|
||||
|
||||
(/** @type {any} */ (window)).createWebviewManager(host);
|
||||
}());
|
||||
createWebviewManager({
|
||||
postMessage: hostMessaging.postMessage.bind(hostMessaging),
|
||||
onMessage: hostMessaging.onMessage.bind(hostMessaging),
|
||||
onElectron: onElectron,
|
||||
useParentPostMessage: false,
|
||||
onIframeLoaded: (frame) => {
|
||||
unloadMonitor.onIframeLoaded(frame);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,8 +13,7 @@
|
|||
</head>
|
||||
|
||||
<body style="margin: 0; overflow: hidden; width: 100%; height: 100%" role="document">
|
||||
<script src="main.js"></script>
|
||||
<script src="host.js"></script>
|
||||
<script type="module" src="host.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,44 +6,43 @@
|
|||
</head>
|
||||
|
||||
<body style="margin: 0; overflow: hidden; width: 100%; height: 100%" role="document">
|
||||
<script src="main.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
(/** @type {any} */ (window)).createWebviewManager({
|
||||
...window.vscodeHost,
|
||||
onIframeLoaded: (newFrame) => {
|
||||
newFrame.contentWindow.onbeforeunload = () => {
|
||||
if (window.vscodeHost.isInDevelopmentMode) { // Allow reloads while developing a webview
|
||||
window.vscodeHost.postMessage('do-reload');
|
||||
return false;
|
||||
}
|
||||
// Block navigation when not in development mode
|
||||
console.log('prevented webview navigation');
|
||||
<script type="module">
|
||||
import { createWebviewManager } from './main.js';
|
||||
|
||||
createWebviewManager({
|
||||
...window.vscodeHost,
|
||||
onIframeLoaded: (newFrame) => {
|
||||
newFrame.contentWindow.onbeforeunload = () => {
|
||||
if (window.vscodeHost.isInDevelopmentMode) { // Allow reloads while developing a webview
|
||||
window.vscodeHost.postMessage('do-reload');
|
||||
return false;
|
||||
};
|
||||
}
|
||||
// Block navigation when not in development mode
|
||||
console.log('prevented webview navigation');
|
||||
return false;
|
||||
};
|
||||
|
||||
// Electron 4 eats mouseup events from inside webviews
|
||||
// https://github.com/microsoft/vscode/issues/75090
|
||||
// Try to fix this by rebroadcasting mouse moves and mouseups so that we can
|
||||
// emulate these on the main window
|
||||
let isMouseDown = false;
|
||||
newFrame.contentWindow.addEventListener('mousedown', () => {
|
||||
isMouseDown = true;
|
||||
});
|
||||
// Electron 4 eats mouseup events from inside webviews
|
||||
// https://github.com/microsoft/vscode/issues/75090
|
||||
// Try to fix this by rebroadcasting mouse moves and mouseups so that we can
|
||||
// emulate these on the main window
|
||||
let isMouseDown = false;
|
||||
newFrame.contentWindow.addEventListener('mousedown', () => {
|
||||
isMouseDown = true;
|
||||
});
|
||||
|
||||
const tryDispatchSyntheticMouseEvent = (e) => {
|
||||
if (!isMouseDown) {
|
||||
window.vscodeHost.postMessage('synthetic-mouse-event', { type: e.type, screenX: e.screenX, screenY: e.screenY, clientX: e.clientX, clientY: e.clientY });
|
||||
}
|
||||
};
|
||||
newFrame.contentWindow.addEventListener('mouseup', e => {
|
||||
tryDispatchSyntheticMouseEvent(e);
|
||||
isMouseDown = false;
|
||||
});
|
||||
newFrame.contentWindow.addEventListener('mousemove', tryDispatchSyntheticMouseEvent);
|
||||
},
|
||||
});
|
||||
}());
|
||||
const tryDispatchSyntheticMouseEvent = (e) => {
|
||||
if (!isMouseDown) {
|
||||
window.vscodeHost.postMessage('synthetic-mouse-event', { type: e.type, screenX: e.screenX, screenY: e.screenY, clientX: e.clientX, clientY: e.clientY });
|
||||
}
|
||||
};
|
||||
newFrame.contentWindow.addEventListener('mouseup', e => {
|
||||
tryDispatchSyntheticMouseEvent(e);
|
||||
isMouseDown = false;
|
||||
});
|
||||
newFrame.contentWindow.addEventListener('mousemove', tryDispatchSyntheticMouseEvent);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
Loading…
Reference in a new issue