Skip to content

Instantly share code, notes, and snippets.

@CharlieAIO
Created December 20, 2021 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CharlieAIO/0fc4e3403d303301ae48e27088861493 to your computer and use it in GitHub Desktop.
Save CharlieAIO/0fc4e3403d303301ae48e27088861493 to your computer and use it in GitHub Desktop.
Electron load extension
const fs = require('fs');
const path = require('path');
const { ipcMain, BrowserWindow } = require('electron');
const METAMASK_ID = 'nkbihfbeogaeaoehlefnkodbefgpgknn';
const METAMASK_KEY = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlcgI4VVL4JUvo6hlSgeCZp9mGltZrzFvc2Asqzb1dDGO9baoYOe+QRoh27/YyVXugxni480Q/R147INhBOyQZVMhZOD5pFMVutia9MHMaZhgRXzrK3BHtNSkKLL1c5mhutQNwiLqLtFkMSGvka91LoMEC8WTI0wi4tACnJ5FyFZQYzvtqy5sXo3VS3gzfOBluLKi7BxYcaUJjNrhOIxl1xL2qgK5lDrDOLKcbaurDiwqofVtAFOL5sM3uJ6D8nOO9tG+T7hoobRFN+nxk43PHgCv4poicOv+NMZQEk3da1m/xfuzXV88NcE/YRbRLwAS82m3gsJZKc6mLqm4wZHzBwIDAQAB';
const getMetamaskPath = (isDev) => {
if (isDev) {
return path.join(__dirname,`../extension/`);
}
// console.log(path.resolve(__dirname,`../../app.asar.unpacked/dist/extensions/metamask/`))
return path.resolve(__dirname,`../extension/`);
};
const loadMetamaskFromManifest = async (session, metamaskPath) => {
let manifest = await new Promise((resolve, reject) => {
fs.readFile(`${metamaskPath}/manifest.json`, 'utf8', async function (err, data) {
if (err) reject(err);
resolve(data)
});
})
// console.log(metamaskPath)
let extensionPath = path.resolve('extension')
console.log(extensionPath)
await session.defaultSession.loadExtension(extensionPath, {allowFileAccess:true});
};
const loadMetamask = async (session, window, isDev) => {
let manifest;
let metamaskPopup;
let metamaskNotification;
let mainWindow = window;
const metamaskPath = getMetamaskPath(isDev);
await loadMetamaskFromManifest(session, metamaskPath);
return
ipcMain.on('open-metamask-popup', (event, arg) => {
if(metamaskPopup && !metamaskPopup.isDestroyed()) metamaskPopup.close();
metamaskPopup = new BrowserWindow({
title: 'MetaMask',
width: 360,
height: 520,
type: 'popup',
resizable: false
});
metamaskPopup.loadURL(`chrome-extension://${METAMASK_ID}/popup.html`);
});
ipcMain.on('open-metamask-notification', (event, arg) => {
if(metamaskNotification && !metamaskNotification.isDestroyed()) metamaskNotification.close();
metamaskNotification = new BrowserWindow({
title: 'MetaMask',
width: 360,
height: 520,
type: 'popup',
resizable: false
});
metamaskNotification.loadURL(`chrome-extension://${METAMASK_ID}/notification.html`);
});
ipcMain.on('close-metamask-notification', (event, arg) => {
if(metamaskPopup && !metamaskPopup.isDestroyed()) metamaskPopup.close();
});
ipcMain.on('reload-metamask', (event, arg) => {
loadMetamaskFromManifest(session, metamaskPath);
session.defaultSession.extensions.enable(METAMASK_ID)
});
};
module.exports = {
loadMetamask
};
// Module to control the application lifecycle and the native browser window.
const { app, BrowserWindow, protocol,session } = require("electron");
require('dotenv').config()
const path = require("path");
const url = require("url");
const extensions = require('./extensions');
let isDev;
try {
isDev = require('electron-is-dev');
} catch(e) {
isDev = false;
}
if(isDev) {
require('electron-reload')(path.join(__dirname));
}
// Create the native browser window.
function createWindow() {
const mainWindow = new BrowserWindow({
minWidth:1050,
maxWidth:1500,
width:1100,
minHeight:600,
maxHeight:800,
height:600,
title:process.env.TITLE,
frame:false,
// transparent:true,
// Set the path of an additional "preload" script that can be used to
// communicate between node-land and browser-land.
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
// In production, set the initial browser path to the local bundle generated
// by the Create React App build process.
// In development, set it to localhost to allow live/hot-reloading.
const appURL = app.isPackaged
? url.format({
pathname: path.join(__dirname, "index.html"),
protocol: "file:",
slashes: true,
})
: "http://localhost:3000";
mainWindow.loadURL(appURL);
// Automatically open Chrome's DevTools in development mode.
if (!app.isPackaged) {
mainWindow.webContents.openDevTools();
}
return mainWindow
}
// Setup a local proxy to adjust the paths of requested files when loading
// them from the local production bundle (e.g.: local fonts, etc...).
function setupLocalFilesNormalizerProxy() {
protocol.registerHttpProtocol(
"file",
(request, callback) => {
const url = request.url.substr(8);
callback({ path: path.normalize(`${__dirname}/${url}`) });
},
(error) => {
if (error) console.error("Failed to register protocol");
}
);
}
// This method will be called when Electron has finished its initialization and
// is ready to create the browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
let win = createWindow();
setupLocalFilesNormalizerProxy();
extensions.loadMetamask(session, win, isDev);
const filter = {
urls: ['*://pro-api.coinmarketcap.com/*']
};
win.webContents.session.webRequest.onBeforeSendHeaders(
filter,
(details, callback) => {
details.requestHeaders.Origin = `http://example.com/*`
callback({ requestHeaders: details.requestHeaders })
}
)
win.webContents.session.webRequest.onHeadersReceived(
filter,
(details, callback) => {
details.responseHeaders['access-control-allow-origin'] = [
'capacitor-electron://-',
'http://localhost:3000' // URL your local electron app hosted
]
callback({ responseHeaders: details.responseHeaders })
}
)
app.on("activate", function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
// Quit when all windows are closed, except on macOS.
// There, it's common for applications and their menu bar to stay active until
// the user quits explicitly with Cmd + Q.
app.on("window-all-closed", function () {
if (process.platform !== "darwin") {
app.quit();
}
});
// If your app has no need to navigate or only needs to navigate to known pages,
// it is a good idea to limit navigation outright to that known scope,
// disallowing any other kinds of navigation.
const allowedNavigationDestinations = ["https://my-electron-app.com","https://pro-api.coinmarketcap.com/"];
app.on("web-contents-created", (event, contents) => {
contents.on("will-navigate", (event, navigationUrl) => {
const parsedUrl = new URL(navigationUrl);
if (!allowedNavigationDestinations.includes(parsedUrl.origin)) {
event.preventDefault();
}
});
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment