1
0
mirror of https://github.com/jiahaog/Nativefier synced 2024-06-28 07:50:49 +02:00
Nativefier/src/helpers/helpers.ts
Adam Weeden dd6e15fb5c
Fix injecting multiple css/js files (fix #458) (#1162)
* Add ability to inject multiple css/js files

* API doc: Move misplaced macOS shortcuts doc (PR #1158)

When I added this documentation originally, I guess I placed it in the wrong location.

* README: use quotes in example, to divert users from shell globbing pitfalls

Follow-up of https://github.com/nativefier/nativefier/issues/1159#issuecomment-827184112

* Support opening URLs passed as arg to Nativefied application (fix #405) (PR #1154)

Co-authored-by: Ronan Jouchet <ronan@jouchet.fr>

* macOS: Fix crash when using --tray (fix #527), and invisible icon (fix #942, fix #668) (#1156)

This fixes:

1. A startup crash on macOS when using the `--tray` option; see #527.
  ![image](https://user-images.githubusercontent.com/22625791/115987741-99544600-a5b6-11eb-866a-dadb5640eecb.png)
2. Invisible tray icon on macOS; see #942 and #668.  
   ![image](https://user-images.githubusercontent.com/22625791/115988276-24364000-a5b9-11eb-80c3-561a8a646754.png)

Co-authored-by: Ronan Jouchet <ronan@jouchet.fr>

* API.md / --widevine: document signing apps to make some sites like HBO Max & Udemy work (fix #1147)

* Prompt to confirm when page is attempting to prevent unload (#1163)

Should alleviate part of the issue in #1151

* Add an option to upgrade an existing app (fix #1131) (PR #1138)

This adds a `--upgrade` option to upgrade-in-place an old app, re-using its options it can.
Should help fix #1131

Co-authored-by: Ronan Jouchet <ronan@jouchet.fr>

* Bump to Electron 12.0.5 with Chrome 89.0.4389.128

* Add newly discovered Google internal login page (#1167)

* Fix Widevine by properly listening to widevine-... events, and update docs (fix #1153) (PR #1164)

As documented in #1153, for Widevine support to work properly, we need to listen for the Widevine ready event, and as well for certain sites the app must be signed.

This PR adds the events, and as well adds better documentation on the signing limitation.

This may also help resolve #1147

* Improve suffix creation + tests

* API: clarif in existing doc by the way

* Typo

Co-authored-by: Ronan Jouchet <ronan@jouchet.fr>
Co-authored-by: Ben Curtis <github@nosolutions.com>
Co-authored-by: Fabian Wolf <22625791+fabiwlf@users.noreply.github.com>
2021-04-30 11:04:10 -04:00

174 lines
4.3 KiB
TypeScript

import { spawnSync } from 'child_process';
import * as crypto from 'crypto';
import * as os from 'os';
import * as path from 'path';
import axios from 'axios';
import * as hasbin from 'hasbin';
import * as log from 'loglevel';
import { ncp } from 'ncp';
import * as tmp from 'tmp';
tmp.setGracefulCleanup(); // cleanup temp dirs even when an uncaught exception occurs
const now = new Date();
const TMP_TIME = `${now.getHours()}-${now.getMinutes()}-${now.getSeconds()}`;
type DownloadResult = {
data: Buffer;
ext: string;
};
export function isOSX(): boolean {
return os.platform() === 'darwin';
}
export function isWindows(): boolean {
return os.platform() === 'win32';
}
export function isWindowsAdmin(): boolean {
if (process.platform !== 'win32') {
return false;
}
// https://stackoverflow.com/questions/4051883/batch-script-how-to-check-for-admin-rights
// https://stackoverflow.com/questions/57009374/check-admin-or-non-admin-users-in-nodejs-or-javascript
return spawnSync('fltmc').status === 0;
}
/**
* Create a temp directory with a debug-friendly name, and return its path.
* Will be automatically deleted on exit.
*/
export function getTempDir(prefix: string, mode?: number): string {
return tmp.dirSync({
mode,
unsafeCleanup: true, // recursively remove tmp dir on exit, even if not empty.
prefix: `nativefier-${TMP_TIME}-${prefix}-`,
}).name;
}
export async function copyFileOrDir(
sourceFileOrDir: string,
dest: string,
): Promise<void> {
return new Promise((resolve, reject) => {
ncp(sourceFileOrDir, dest, (error: any) => {
if (error) {
reject(error);
}
resolve();
});
});
}
export async function downloadFile(fileUrl: string): Promise<DownloadResult> {
log.debug(`Downloading ${fileUrl}`);
return axios
.get(fileUrl, {
responseType: 'arraybuffer',
})
.then((response) => {
if (!response.data) {
return null;
}
return {
data: response.data,
ext: path.extname(fileUrl),
};
});
}
export function getAllowedIconFormats(platform: string): string[] {
const hasIdentify = hasbin.sync('identify') || hasbin.sync('gm');
const hasConvert = hasbin.sync('convert') || hasbin.sync('gm');
const hasIconUtil = hasbin.sync('iconutil');
const pngToIcns = hasConvert && hasIconUtil;
const pngToIco = hasConvert;
const icoToIcns = pngToIcns && hasIdentify;
const icoToPng = hasConvert;
// Unsupported
const icnsToPng = false;
const icnsToIco = false;
const formats = [];
// Shell scripting is not supported on windows, temporary override
if (isWindows()) {
switch (platform) {
case 'darwin':
formats.push('.icns');
break;
case 'linux':
formats.push('.png');
break;
case 'win32':
formats.push('.ico');
break;
default:
throw new Error(`Unknown platform ${platform}`);
}
log.debug(
`Allowed icon formats when building for ${platform} (limited on Windows):`,
formats,
);
return formats;
}
switch (platform) {
case 'darwin':
formats.push('.icns');
if (pngToIcns) {
formats.push('.png');
}
if (icoToIcns) {
formats.push('.ico');
}
break;
case 'linux':
formats.push('.png');
if (icoToPng) {
formats.push('.ico');
}
if (icnsToPng) {
formats.push('.icns');
}
break;
case 'win32':
formats.push('.ico');
if (pngToIco) {
formats.push('.png');
}
if (icnsToIco) {
formats.push('.icns');
}
break;
default:
throw new Error(`Unknown platform ${platform}`);
}
log.debug(`Allowed icon formats when building for ${platform}:`, formats);
return formats;
}
/**
* Refuse args like '--n' or '-name', we accept either short '-n' or long '--name'
*/
export function isArgFormatInvalid(arg: string): boolean {
return (
(arg.startsWith('---') ||
/^--[a-z]$/i.exec(arg) !== null ||
/^-[a-z]{2,}$/i.exec(arg) !== null) &&
!['--x', '--y'].includes(arg) // exception for long args --{x,y}
);
}
export function generateRandomSuffix(length = 6): string {
const hash = crypto.createHash('md5');
// Add a random salt to help avoid collisions
hash.update(crypto.randomBytes(256));
return hash.digest('hex').substring(0, length);
}