IPC Communication
Reference for Electron IPC communication patterns.
Overviewβ
FitFileViewer uses Electron's IPC for secure main-renderer communication.
Available Channelsβ
File Operationsβ
dialog:open-fit-fileβ
Opens file selection dialog.
// Renderer
const result = await window.electronAPI.openFile();
// Main handler
ipcMain.handle('dialog:open-fit-file', async () => {
return dialog.showOpenDialog({
properties: ['openFile'],
filters: [{ name: 'FIT Files', extensions: ['fit'] }]
});
});
file:readβ
Reads file contents.
// Renderer
const buffer = await window.electronAPI.readFile(filePath);
// Main handler
ipcMain.handle('file:read', async (event, filePath) => {
return fs.promises.readFile(filePath);
});
App Informationβ
app:get-versionβ
Gets application version.
// Renderer
const version = await window.electronAPI.getVersion();
// Main handler
ipcMain.handle('app:get-version', () => {
return app.getVersion();
});
Preload Scriptβ
Exposed APIβ
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
// File operations
openFile: () => ipcRenderer.invoke('dialog:open-fit-file'),
readFile: (path) => ipcRenderer.invoke('file:read', path),
// App info
getVersion: () => ipcRenderer.invoke('app:get-version'),
// Events
onFileOpened: (callback) => {
ipcRenderer.on('file:opened', (event, data) => callback(data));
}
});
Event Communicationβ
Main β Rendererβ
// Main process
mainWindow.webContents.send('file:opened', {
path: filePath,
data: fileData
});
// Renderer (via preload)
window.electronAPI.onFileOpened((data) => {
console.log('File opened:', data.path);
});
Renderer β Mainβ
// Renderer
const result = await window.electronAPI.openFile();
// Main
ipcMain.handle('dialog:open-fit-file', async (event) => {
// Handle request
return result;
});
Security Considerationsβ
Input Validationβ
// Always validate in main process
ipcMain.handle('file:read', async (event, filePath) => {
// Validate path
if (typeof filePath !== 'string') {
throw new Error('Invalid path type');
}
// Validate extension
if (!filePath.endsWith('.fit')) {
throw new Error('Invalid file type');
}
// Validate path traversal
const normalized = path.normalize(filePath);
if (normalized.includes('..')) {
throw new Error('Path traversal detected');
}
return fs.promises.readFile(normalized);
});
Limited Exposureβ
Only expose necessary functions:
// β Bad: Exposes too much
ipcRenderer: ipcRenderer, // Full access
// β
Good: Specific functions only
openFile: () => ipcRenderer.invoke('dialog:open-fit-file'),
Next: State Management β