|
6 | 6 | const processIpcMessage = __RAW_process_ipc_message_fn__ |
7 | 7 | const osName = __TEMPLATE_os_name__ |
8 | 8 | const fetchChannelDataCommand = __TEMPLATE_fetch_channel_data_command__ |
9 | | - const useCustomProtocol = __TEMPLATE_use_custom_protocol__ |
| 9 | + const linuxIpcProtocolEnabled = __TEMPLATE_linux_ipc_protocol_enabled__ |
| 10 | + let customProtocolIpcFailed = false |
10 | 11 |
|
11 | | - Object.defineProperty(window.__TAURI_INTERNALS__, 'postMessage', { |
12 | | - value: (message) => { |
13 | | - const { cmd, callback, error, payload, options } = message |
| 12 | + // on Linux we only use the custom-protocol-based IPC if the the linux-ipc-protocol Cargo feature is enabled |
| 13 | + // on Android we never use it because Android does not have support to reading the request body |
| 14 | + const canUseCustomProtocol = |
| 15 | + osName === 'linux' ? linuxIpcProtocolEnabled : osName !== 'android' |
| 16 | + |
| 17 | + function sendIpcMessage(message) { |
| 18 | + const { cmd, callback, error, payload, options } = message |
14 | 19 |
|
15 | | - // use custom protocol for IPC if: |
16 | | - // - the flag is set to true or |
17 | | - // - the command is the fetch data command or |
18 | | - // - when not on Linux/Android |
19 | | - // AND |
20 | | - // - when not on macOS with an https URL |
21 | | - if ( |
22 | | - (useCustomProtocol || |
23 | | - cmd === fetchChannelDataCommand || |
24 | | - !(osName === 'linux' || osName === 'android')) && |
25 | | - !( |
26 | | - (osName === 'macos' || osName === 'ios') && |
27 | | - location.protocol === 'https:' |
28 | | - ) |
29 | | - ) { |
30 | | - const { contentType, data } = processIpcMessage(payload) |
31 | | - fetch(window.__TAURI_INTERNALS__.convertFileSrc(cmd, 'ipc'), { |
32 | | - method: 'POST', |
33 | | - body: data, |
34 | | - headers: { |
35 | | - 'Content-Type': contentType, |
36 | | - 'Tauri-Callback': callback, |
37 | | - 'Tauri-Error': error, |
38 | | - ...options?.headers |
| 20 | + if ( |
| 21 | + !customProtocolIpcFailed && |
| 22 | + (canUseCustomProtocol || cmd === fetchChannelDataCommand) |
| 23 | + ) { |
| 24 | + const { contentType, data } = processIpcMessage(payload) |
| 25 | + fetch(window.__TAURI_INTERNALS__.convertFileSrc(cmd, 'ipc'), { |
| 26 | + method: 'POST', |
| 27 | + body: data, |
| 28 | + headers: { |
| 29 | + 'Content-Type': contentType, |
| 30 | + 'Tauri-Callback': callback, |
| 31 | + 'Tauri-Error': error, |
| 32 | + ...options?.headers |
| 33 | + } |
| 34 | + }) |
| 35 | + .then((response) => { |
| 36 | + const cb = response.ok ? callback : error |
| 37 | + // we need to split here because on Android the content-type gets duplicated |
| 38 | + switch ((response.headers.get('content-type') || '').split(',')[0]) { |
| 39 | + case 'application/json': |
| 40 | + return response.json().then((r) => [cb, r]) |
| 41 | + case 'text/plain': |
| 42 | + return response.text().then((r) => [cb, r]) |
| 43 | + default: |
| 44 | + return response.arrayBuffer().then((r) => [cb, r]) |
| 45 | + } |
| 46 | + }) |
| 47 | + .then(([cb, data]) => { |
| 48 | + if (window[`_${cb}`]) { |
| 49 | + window[`_${cb}`](data) |
| 50 | + } else { |
| 51 | + console.warn( |
| 52 | + `[TAURI] Couldn't find callback id {cb} in window. This might happen when the app is reloaded while Rust is running an asynchronous operation.` |
| 53 | + ) |
39 | 54 | } |
40 | 55 | }) |
41 | | - .then((response) => { |
42 | | - const cb = response.ok ? callback : error |
43 | | - // we need to split here because on Android the content-type gets duplicated |
44 | | - switch ( |
45 | | - (response.headers.get('content-type') || '').split(',')[0] |
46 | | - ) { |
47 | | - case 'application/json': |
48 | | - return response.json().then((r) => [cb, r]) |
49 | | - case 'text/plain': |
50 | | - return response.text().then((r) => [cb, r]) |
51 | | - default: |
52 | | - return response.arrayBuffer().then((r) => [cb, r]) |
53 | | - } |
54 | | - }) |
55 | | - .then(([cb, data]) => { |
56 | | - if (window[`_${cb}`]) { |
57 | | - window[`_${cb}`](data) |
58 | | - } else { |
59 | | - console.warn( |
60 | | - `[TAURI] Couldn't find callback id {cb} in window. This might happen when the app is reloaded while Rust is running an asynchronous operation.` |
61 | | - ) |
62 | | - } |
63 | | - }) |
64 | | - } else { |
65 | | - // otherwise use the postMessage interface |
66 | | - const { data } = processIpcMessage({ |
67 | | - cmd, |
68 | | - callback, |
69 | | - error, |
70 | | - options, |
71 | | - payload |
| 56 | + .catch(() => { |
| 57 | + // failed to use the custom protocol IPC (either the webview blocked a custom protocol or it was a CSP error) |
| 58 | + // so we need to fallback to the postMessage interface |
| 59 | + customProtocolIpcFailed = true |
| 60 | + sendIpcMessage(message) |
72 | 61 | }) |
73 | | - window.ipc.postMessage(data) |
74 | | - } |
| 62 | + } else { |
| 63 | + // otherwise use the postMessage interface |
| 64 | + const { data } = processIpcMessage({ |
| 65 | + cmd, |
| 66 | + callback, |
| 67 | + error, |
| 68 | + options, |
| 69 | + payload |
| 70 | + }) |
| 71 | + window.ipc.postMessage(data) |
75 | 72 | } |
| 73 | + } |
| 74 | + |
| 75 | + Object.defineProperty(window.__TAURI_INTERNALS__, 'postMessage', { |
| 76 | + value: sendIpcMessage |
76 | 77 | }) |
77 | 78 | })() |
0 commit comments