|
5 | 5 | <meta charset="UTF-8"> |
6 | 6 |
|
7 | 7 | <meta http-equiv="Content-Security-Policy" |
8 | | - content="default-src 'none'; script-src 'sha256-R3BsSkqy7qFbvWSmwr7WqT1eg6Sq4zSe0uIlrUQ4EKE=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> |
| 8 | + content="default-src 'none'; script-src 'sha256-1qYtPnTQa4VwKNJO61EOhs2agF9TvuQSYIJ27OgzZqI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> |
9 | 9 |
|
10 | 10 | <!-- Disable pinch zooming --> |
11 | 11 | <meta name="viewport" |
|
35 | 35 | const onElectron = searchParams.get('platform') === 'electron'; |
36 | 36 | const disableServiceWorker = searchParams.has('disableServiceWorker'); |
37 | 37 | const expectedWorkerVersion = parseInt(searchParams.get('swVersion')); |
| 38 | + /** @type {MessageChannel | undefined} */ |
| 39 | + let outerIframeMessageChannel; |
38 | 40 |
|
39 | 41 | /** |
40 | 42 | * Use polling to track focus of main webview and iframes within the webview |
|
110 | 112 | color: var(--vscode-textLink-foreground); |
111 | 113 | } |
112 | 114 |
|
| 115 | + p > a { |
| 116 | + text-decoration: var(--text-link-decoration); |
| 117 | + } |
| 118 | +
|
113 | 119 | a:hover { |
114 | 120 | color: var(--vscode-textLink-activeForeground); |
115 | 121 | } |
|
232 | 238 | } |
233 | 239 |
|
234 | 240 | const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`); |
235 | | - navigator.serviceWorker.register(swPath) |
| 241 | + navigator.serviceWorker.register(swPath, { type: 'module' }) |
236 | 242 | .then(async registration => { |
237 | 243 | /** |
238 | 244 | * @param {MessageEvent} event |
|
260 | 266 | navigator.serviceWorker.addEventListener('message', versionHandler); |
261 | 267 |
|
262 | 268 | const postVersionMessage = (/** @type {ServiceWorker} */ controller) => { |
263 | | - controller.postMessage({ channel: 'version' }); |
| 269 | + outerIframeMessageChannel = new MessageChannel(); |
| 270 | + controller.postMessage({ channel: 'version' }, [outerIframeMessageChannel.port2]); |
264 | 271 | }; |
265 | 272 |
|
266 | 273 | // At this point, either the service worker is ready and |
|
797 | 804 | } |
798 | 805 | } |
799 | 806 |
|
| 807 | + |
| 808 | + function handleInnerDragEvent(/** @type {DragEvent} */ e) { |
| 809 | + /** |
| 810 | + * To ensure that the drop event always fires as expected, you should always include a preventDefault() call in the part of your code which handles the dragover event. |
| 811 | + * source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event |
| 812 | + **/ |
| 813 | + e.preventDefault(); |
| 814 | + |
| 815 | + if (!e.dataTransfer) { |
| 816 | + return; |
| 817 | + } |
| 818 | + |
| 819 | + |
| 820 | + // Only handle drags from outside editor for now |
| 821 | + if (e.dataTransfer.items.length && Array.prototype.every.call(e.dataTransfer.items, item => item.kind === 'file')) { |
| 822 | + hostMessaging.postMessage('drag', { |
| 823 | + shiftKey: e.shiftKey |
| 824 | + }); |
| 825 | + } |
| 826 | + |
| 827 | + } |
| 828 | + |
| 829 | + function handleInnerDropEvent(/**@type {DragEvent} */e) { |
| 830 | + e.preventDefault(); |
| 831 | + } |
| 832 | + |
800 | 833 | /** |
801 | 834 | * @param {() => void} callback |
802 | 835 | */ |
|
887 | 920 | window.addEventListener('keydown', handleInnerKeydown); |
888 | 921 | window.addEventListener('keyup', handleInnerKeyup); |
889 | 922 | window.addEventListener('dragenter', handleInnerDragStartEvent); |
890 | | - window.addEventListener('dragover', handleInnerDragStartEvent); |
| 923 | + window.addEventListener('dragover', handleInnerDragEvent); |
| 924 | + window.addEventListener('drag', handleInnerDragEvent); |
| 925 | + window.addEventListener('drop', handleInnerDropEvent); |
| 926 | + |
891 | 927 |
|
892 | 928 | onDomReady(() => { |
893 | 929 | if (!document.body) { |
|
980 | 1016 | const previousPendingFrame = getPendingFrame(); |
981 | 1017 | if (previousPendingFrame) { |
982 | 1018 | previousPendingFrame.setAttribute('id', ''); |
983 | | - document.body.removeChild(previousPendingFrame); |
| 1019 | + previousPendingFrame.remove(); |
984 | 1020 | } |
985 | 1021 | if (!wasFirstLoad) { |
986 | 1022 | pendingMessages = []; |
|
1077 | 1113 | if (newFrame && newFrame.contentDocument && newFrame.contentDocument === contentDocument) { |
1078 | 1114 | const wasFocused = document.hasFocus(); |
1079 | 1115 | const oldActiveFrame = getActiveFrame(); |
1080 | | - if (oldActiveFrame) { |
1081 | | - document.body.removeChild(oldActiveFrame); |
1082 | | - } |
| 1116 | + oldActiveFrame?.remove(); |
1083 | 1117 | // Styles may have changed since we created the element. Make sure we re-style |
1084 | 1118 | if (initialStyleVersion !== styleVersion) { |
1085 | 1119 | applyStyles(newFrame.contentDocument, newFrame.contentDocument.body); |
|
1171 | 1205 | }); |
1172 | 1206 |
|
1173 | 1207 | contentWindow.addEventListener('dragenter', handleInnerDragStartEvent); |
1174 | | - contentWindow.addEventListener('dragover', handleInnerDragStartEvent); |
| 1208 | + contentWindow.addEventListener('dragover', handleInnerDragEvent); |
| 1209 | + contentWindow.addEventListener('drag', handleInnerDragEvent); |
| 1210 | + contentWindow.addEventListener('drop', handleInnerDropEvent); |
1175 | 1211 |
|
1176 | 1212 | unloadMonitor.onIframeLoaded(newFrame); |
1177 | 1213 | } |
| 1214 | + |
| 1215 | + if (!disableServiceWorker && outerIframeMessageChannel) { |
| 1216 | + outerIframeMessageChannel.port1.onmessage = event => { |
| 1217 | + switch (event.data.channel) { |
| 1218 | + case 'load-resource': |
| 1219 | + case 'load-localhost': |
| 1220 | + hostMessaging.postMessage(event.data.channel, event.data); |
| 1221 | + return; |
| 1222 | + } |
| 1223 | + }; |
| 1224 | + } |
1178 | 1225 | }); |
1179 | 1226 |
|
1180 | 1227 | // propagate vscode-context-menu-visible class |
|
0 commit comments