// Wrapper around chrome.runtime.sendMessage for native host communication. /** Send a typed message to the native host and return a Promise resolving to the response. */ function sendToNative(type, payload) { return new Promise((resolve) => { chrome.runtime.sendMessage( { target: 'holesail-native', action: 'send', payload: { type, payload } }, (response) => { void chrome.runtime.lastError; resolve(response); } ); }); } /** * Like sendToNative but resolves with a normalized result (checks chrome.runtime.lastError). * @returns {Promise<{ ok: true, data: object } | { ok: false, error: string }>} */ function sendToNativeResult(type, payload) { return new Promise((resolve) => { chrome.runtime.sendMessage( { target: 'holesail-native', action: 'send', payload: { type, payload } }, (response) => { const lastErr = chrome.runtime.lastError; if (lastErr) { resolve({ ok: false, error: lastErr.message || 'Extension messaging failed' }); return; } if (!response) { resolve({ ok: false, error: 'No response from extension' }); return; } if (response.error != null && response.ok !== true) { resolve({ ok: false, error: String(response.error) }); return; } if (response.ok === false) { resolve({ ok: false, error: response.error ? String(response.error) : 'Request failed' }); return; } resolve({ ok: true, data: response }); } ); }); } /** * Show a toast for a failed native call (user-initiated actions). * @param {string} [context] - Short label, e.g. "SSH" * @param {string} [error] - Error message */ function notifyNativeFailure(context, error) { const msg = error && String(error).trim() ? String(error) : 'Something went wrong'; const prefix = context && String(context).trim() ? String(context).trim() + ': ' : ''; if (typeof showToast === 'function') showToast(prefix + msg, 'error'); } /** Fetch the full extension state from the background service worker. */ async function fetchState() { return new Promise((resolve) => { chrome.runtime.sendMessage( { target: 'holesail-native', action: 'getState' }, (response) => { if (chrome.runtime.lastError) { log('fetchState error:', chrome.runtime.lastError.message); resolve(null); return; } if (response && response.ok) resolve(response.state); else resolve(null); } ); }); }