creating native manifests

This commit is contained in:
antelle 2021-04-21 22:23:17 +02:00
parent dd4ad6d72b
commit ccb9b03287
No known key found for this signature in database
GPG Key ID: 63C9777AAB7C563C
4 changed files with 182 additions and 15 deletions

View File

@ -116,15 +116,9 @@ const BrowserExtensionConnector = {
window.removeEventListener('message', this.browserWindowMessage);
},
isEnabledOnDesktop() {
for (const browser of SupportedBrowsers) {
for (const ext of SupportedExtensions) {
if (AppSettingsModel[`extensionEnabled${ext.alias}${browser}`]) {
return true;
}
}
}
return false;
enable(browser, extension, enabled) {
const { ipcRenderer } = Launcher.electron();
ipcRenderer.invoke('browserExtensionConnectorEnable', browser, extension, enabled);
},
async startDesktopAppListener() {

View File

@ -4,7 +4,11 @@ import { Features } from 'util/features';
import { Links } from 'const/links';
import { AppSettingsModel } from 'models/app-settings-model';
import { Locale } from 'util/locale';
import { SupportedBrowsers, SupportedExtensions } from 'comp/extension/browser-extension-connector';
import {
BrowserExtensionConnector,
SupportedBrowsers,
SupportedExtensions
} from 'comp/extension/browser-extension-connector';
class SettingsBrowserView extends View {
template = template;
@ -23,9 +27,7 @@ class SettingsBrowserView extends View {
if (Features.isDesktop) {
data.extensionNames = ['KeeWeb Connect', 'KeePassXC-Browser'];
data.settingsPerBrowser = this.getSettingsPerBrowser();
data.anyBrowserIsEnabled = data.settingsPerBrowser.some((perBrowser) =>
perBrowser.extensions.some((ext) => ext.enabled)
);
data.anyBrowserIsEnabled = BrowserExtensionConnector.isEnabled();
} else {
const extensionBrowserFamily = Features.extensionBrowserFamily;
data.extensionBrowserFamily = Features.extensionBrowserFamily;
@ -69,6 +71,8 @@ class SettingsBrowserView extends View {
delete AppSettingsModel[setting];
}
BrowserExtensionConnector.enable(browser, extension, enabled);
this.render();
}

View File

@ -5,9 +5,11 @@ const net = require('net');
const { ipcMain, app } = require('electron');
const { Logger } = require('../logger');
const { getProcessInfo } = require('../util/process-utils');
const browserExtensionInstaller = require('../util/browser-extension-installer');
ipcMain.handle('browserExtensionConnectorStart', browserExtensionConnectorStart);
ipcMain.handle('browserExtensionConnectorStop', browserExtensionConnectorStop);
ipcMain.handle('browserExtensionConnectorEnable', browserExtensionConnectorEnable);
ipcMain.handle('browserExtensionConnectorSocketResult', browserExtensionConnectorSocketResult);
ipcMain.handle('browserExtensionConnectorSocketEvent', browserExtensionConnectorSocketEvent);
@ -15,11 +17,11 @@ const logger = new Logger('browser-extension-connector');
const MaxIncomingDataLength = 10_000;
const ExtensionOrigins = {
'chrome-extension://aphablpbogbpmocgkpeeadeljldnphon/': 'keeweb-connect',
'safari-keeweb-connect': 'keeweb-connect',
'keeweb-connect@keeweb.info': 'keeweb-connect',
'chrome-extension://oboonakemofpalcgghocfoadofidjkkk/': 'keepassxc-browser',
'chrome-extension://aphablpbogbpmocgkpeeadeljldnphon/': 'keeweb-connect',
'keepassxc-browser@keepassxc.org': 'keepassxc-browser',
'chrome-extension://oboonakemofpalcgghocfoadofidjkkk/': 'keepassxc-browser',
'chrome-extension://pdffhmdngciaglkoonimfcmckehcpafo/': 'keepassxc-browser'
};
@ -67,9 +69,24 @@ function browserExtensionConnectorStop() {
}
connectedSockets = new Map();
connectedSocketState = new WeakMap();
logger.info('Stopped');
}
async function browserExtensionConnectorEnable(e, browser, extension, enabled) {
logger.info(enabled ? 'Enable' : 'Disable', browser, extension);
try {
if (enabled) {
await browserExtensionInstaller.install(browser, extension);
} else {
await browserExtensionInstaller.uninstall(browser, extension);
}
} catch (e) {
logger.error(`Error installing extension: ${e}`);
}
}
function browserExtensionConnectorSocketResult(e, socketId, result) {
sendResultToSocket(socketId, result);
}

View File

@ -0,0 +1,152 @@
const fs = require('fs');
const path = require('path');
const { isDev } = require('./app-info');
const { app } = require('electron');
function getManifestDir(browser) {
const home = app.getPath('home');
switch (process.platform) {
case 'darwin':
switch (browser) {
case 'Chrome':
return `${home}/Library/Application Support/Google/Chrome/NativeMessagingHosts/`;
case 'Firefox':
return `${home}/Library/Application Support/Mozilla/NativeMessagingHosts/`;
case 'Edge':
return `${home}/Library/Application Support/Microsoft Edge/NativeMessagingHosts/`;
default:
return undefined;
}
case 'win32':
throw new Error('not implemented');
case 'linux':
switch (browser) {
case 'Chrome':
return `${home}/.config/google-chrome/NativeMessagingHosts/`;
case 'Firefox':
return `${home}/.mozilla/native-messaging-hosts/`;
case 'Edge':
return `${home}/.config/microsoft-edge/NativeMessagingHosts/`;
default:
return undefined;
}
}
}
function getManifestFileName(extension) {
switch (extension) {
case 'KWC':
return 'net.antelle.keeweb.keeweb_connect.json';
case 'KPXC':
return 'org.keepassxc.keepassxc_browser.json';
}
}
function createManifest(extension) {
switch (extension) {
case 'KWC':
return {
'allowed_origins': ['chrome-extension://aphablpbogbpmocgkpeeadeljldnphon/'],
'allowed_extensions': ['keeweb-connect@keeweb.info'],
description: 'KeeWeb native messaging host',
name: 'net.antelle.keeweb.keeweb_connect',
type: 'stdio'
};
case 'KPXC':
return {
'allowed_origins': [
'chrome-extension://pdffhmdngciaglkoonimfcmckehcpafo/',
'chrome-extension://oboonakemofpalcgghocfoadofidjkkk/'
],
'allowed_extensions': ['keepassxc-browser@keepassxc.org'],
description: 'Native messaging host created by KeeWeb',
name: 'org.keepassxc.keepassxc_browser',
type: 'stdio'
};
}
}
function getNativeMessagingHostPath() {
if (isDev) {
const packageBase = path.resolve('node_modules/@keeweb/keeweb-native-messaging-host');
const extension = process.platform === 'win32' ? '.exe' : '';
const exeName = `keeweb-native-messaging-host${extension}`;
return path.join(packageBase, `${process.platform}-${process.arch}`, exeName);
}
switch (process.platform) {
case 'darwin':
return path.join(app.getPath('exe'), '..', 'util', 'keeweb-native-messaging-host');
case 'win32':
return path.join(app.getPath('exe'), '..', 'keeweb-native-messaging-host.exe');
case 'linux':
return path.join(app.getPath('exe'), '..', 'keeweb-native-messaging-host');
}
}
module.exports.install = async function (browser, extension) {
const manifestDir = getManifestDir(browser);
if (!manifestDir) {
return;
}
await fs.promises.mkdir(manifestDir, { recursive: true });
const manifestFileName = getManifestFileName(extension);
if (!manifestFileName) {
return;
}
const fullPath = path.join(manifestDir, manifestFileName);
let manifest;
if (extension === 'KPXC') {
try {
await fs.promises.access(fullPath);
manifest = JSON.parse(await fs.promises.readFile(fullPath, 'utf8'));
manifest.pathKPXC = manifest.path;
} catch {}
}
if (!manifest) {
manifest = createManifest(extension);
}
if (!manifest) {
return;
}
manifest.path = getNativeMessagingHostPath();
await fs.promises.writeFile(fullPath, JSON.stringify(manifest, null, 4));
};
module.exports.uninstall = async function (browser, extension) {
const manifestDir = getManifestDir(browser);
if (!manifestDir) {
return;
}
const manifestFileName = getManifestFileName(extension);
if (!manifestFileName) {
return;
}
const fullPath = path.join(manifestDir, manifestFileName);
try {
await fs.promises.access(fullPath);
} catch {
return;
}
if (extension === 'KPXC') {
const manifest = JSON.parse(await fs.promises.readFile(fullPath, 'utf8'));
if (manifest.pathKPXC) {
manifest.path = manifest.pathKPXC;
delete manifest.pathKPXC;
await fs.promises.writeFile(fullPath, JSON.stringify(manifest, null, 4));
} else {
await fs.promises.unlink(fullPath);
}
} else {
await fs.promises.unlink(fullPath);
}
};