@lvce-editor/main-process 6.14.1 → 6.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/mainProcessMain.js +504 -157
- package/package.json +1 -1
package/dist/mainProcessMain.js
CHANGED
|
@@ -9,6 +9,8 @@ import { mkdirSync, createWriteStream, readFileSync, openAsBlob, existsSync, wri
|
|
|
9
9
|
import * as NodePath from 'node:path';
|
|
10
10
|
import { dirname, join as join$1 } from 'node:path';
|
|
11
11
|
import { homedir, tmpdir } from 'node:os';
|
|
12
|
+
import { pbkdf2Sync, createDecipheriv, createHash } from 'node:crypto';
|
|
13
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
12
14
|
import { MessageChannel } from 'node:worker_threads';
|
|
13
15
|
|
|
14
16
|
const scheme = 'lvce-oss';
|
|
@@ -3424,7 +3426,7 @@ const formatUtilityProcessName = name => {
|
|
|
3424
3426
|
const state$6 = {
|
|
3425
3427
|
all: Object.create(null)
|
|
3426
3428
|
};
|
|
3427
|
-
const add$
|
|
3429
|
+
const add$2 = (pid, process, name) => {
|
|
3428
3430
|
number(pid);
|
|
3429
3431
|
object(process);
|
|
3430
3432
|
string(name);
|
|
@@ -3459,7 +3461,7 @@ const trackUtilityProcess = (rawIpc, name) => {
|
|
|
3459
3461
|
pid
|
|
3460
3462
|
} = rawIpc;
|
|
3461
3463
|
const formattedName = formatUtilityProcessName(name);
|
|
3462
|
-
add$
|
|
3464
|
+
add$2(pid, rawIpc, formattedName);
|
|
3463
3465
|
const cleanup = () => {
|
|
3464
3466
|
remove$1(pid);
|
|
3465
3467
|
rawIpc.off('exit', handleExit);
|
|
@@ -4065,6 +4067,7 @@ const DidNavigate = 'did-navigate';
|
|
|
4065
4067
|
const PageTitleUpdated = 'page-title-updated';
|
|
4066
4068
|
const Destroyed = 'destroyed';
|
|
4067
4069
|
const BeforeInputEvent = 'before-input-event';
|
|
4070
|
+
const Login = 'login';
|
|
4068
4071
|
|
|
4069
4072
|
const Deny = 'deny';
|
|
4070
4073
|
|
|
@@ -4085,7 +4088,7 @@ const state$3 = {
|
|
|
4085
4088
|
fallThroughKeyBindings: [],
|
|
4086
4089
|
views: Object.create(null)
|
|
4087
4090
|
};
|
|
4088
|
-
const add = (id, browserWindow, view) => {
|
|
4091
|
+
const add$1 = (id, browserWindow, view) => {
|
|
4089
4092
|
// state
|
|
4090
4093
|
state$3.views[id] = {
|
|
4091
4094
|
browserWindow,
|
|
@@ -4603,6 +4606,409 @@ const beep$1 = () => {
|
|
|
4603
4606
|
shell.beep();
|
|
4604
4607
|
};
|
|
4605
4608
|
|
|
4609
|
+
const chromeV10Prefix = Buffer.from('v10');
|
|
4610
|
+
const chromeV10Key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1');
|
|
4611
|
+
const chromeV10Iv = Buffer.alloc(16, 0x20);
|
|
4612
|
+
const domainHashLength = 32;
|
|
4613
|
+
class UnsupportedChromeCookieEncryptionError extends Error {
|
|
4614
|
+
constructor() {
|
|
4615
|
+
super('Unsupported Chrome cookie encryption format');
|
|
4616
|
+
this.name = 'UnsupportedChromeCookieEncryptionError';
|
|
4617
|
+
}
|
|
4618
|
+
}
|
|
4619
|
+
const decrypt$1 = (hostKey, encryptedValue, databaseVersion) => {
|
|
4620
|
+
const buffer = Buffer.from(encryptedValue);
|
|
4621
|
+
if (buffer.length <= chromeV10Prefix.length || !buffer.subarray(0, chromeV10Prefix.length).equals(chromeV10Prefix)) {
|
|
4622
|
+
throw new UnsupportedChromeCookieEncryptionError();
|
|
4623
|
+
}
|
|
4624
|
+
const decipher = createDecipheriv('aes-128-cbc', chromeV10Key, chromeV10Iv);
|
|
4625
|
+
const plaintext = Buffer.concat([decipher.update(buffer.subarray(chromeV10Prefix.length)), decipher.final()]);
|
|
4626
|
+
if (databaseVersion < 24) {
|
|
4627
|
+
return plaintext.toString('utf8');
|
|
4628
|
+
}
|
|
4629
|
+
if (plaintext.length < domainHashLength) {
|
|
4630
|
+
throw new Error('Chrome cookie domain integrity check failed');
|
|
4631
|
+
}
|
|
4632
|
+
const expectedDomainHash = createHash('sha256').update(hostKey).digest();
|
|
4633
|
+
const actualDomainHash = plaintext.subarray(0, domainHashLength);
|
|
4634
|
+
if (!actualDomainHash.equals(expectedDomainHash)) {
|
|
4635
|
+
throw new Error('Chrome cookie domain integrity check failed');
|
|
4636
|
+
}
|
|
4637
|
+
return plaintext.subarray(domainHashLength).toString('utf8');
|
|
4638
|
+
};
|
|
4639
|
+
|
|
4640
|
+
const chromeEpochOffsetMicroseconds = 11_644_473_600_000_000n;
|
|
4641
|
+
const microsecondsPerSecond = 1_000_000n;
|
|
4642
|
+
const getSameSite = sameSite => {
|
|
4643
|
+
switch (sameSite) {
|
|
4644
|
+
case 0:
|
|
4645
|
+
return 'no_restriction';
|
|
4646
|
+
case 1:
|
|
4647
|
+
return 'lax';
|
|
4648
|
+
case 2:
|
|
4649
|
+
return 'strict';
|
|
4650
|
+
default:
|
|
4651
|
+
return 'unspecified';
|
|
4652
|
+
}
|
|
4653
|
+
};
|
|
4654
|
+
const getExpirationDate = expiresUtc => {
|
|
4655
|
+
const chromeMicroseconds = BigInt(expiresUtc);
|
|
4656
|
+
return Number(chromeMicroseconds - chromeEpochOffsetMicroseconds) / Number(microsecondsPerSecond);
|
|
4657
|
+
};
|
|
4658
|
+
const getValue = (row, databaseVersion) => {
|
|
4659
|
+
if (row.value) {
|
|
4660
|
+
return row.value;
|
|
4661
|
+
}
|
|
4662
|
+
return decrypt$1(row.hostKey, row.encryptedValue, databaseVersion);
|
|
4663
|
+
};
|
|
4664
|
+
const convert = (row, databaseVersion, now = Date.now() / 1000) => {
|
|
4665
|
+
if (!row.hostKey || row.topFrameSiteKey) {
|
|
4666
|
+
return undefined;
|
|
4667
|
+
}
|
|
4668
|
+
const host = row.hostKey.startsWith('.') ? row.hostKey.slice(1) : row.hostKey;
|
|
4669
|
+
if (!host) {
|
|
4670
|
+
return undefined;
|
|
4671
|
+
}
|
|
4672
|
+
const secure = Boolean(row.isSecure);
|
|
4673
|
+
const details = {
|
|
4674
|
+
httpOnly: Boolean(row.isHttpOnly),
|
|
4675
|
+
name: row.name,
|
|
4676
|
+
path: row.path || '/',
|
|
4677
|
+
sameSite: getSameSite(row.sameSite),
|
|
4678
|
+
secure,
|
|
4679
|
+
url: `${secure ? 'https' : 'http'}://${host}/`,
|
|
4680
|
+
value: getValue(row, databaseVersion)
|
|
4681
|
+
};
|
|
4682
|
+
if (row.hostKey.startsWith('.')) {
|
|
4683
|
+
details.domain = row.hostKey;
|
|
4684
|
+
}
|
|
4685
|
+
if (row.hasExpires) {
|
|
4686
|
+
const expirationDate = getExpirationDate(row.expiresUtc);
|
|
4687
|
+
if (!Number.isFinite(expirationDate) || expirationDate <= now) {
|
|
4688
|
+
return undefined;
|
|
4689
|
+
}
|
|
4690
|
+
details.expirationDate = expirationDate;
|
|
4691
|
+
}
|
|
4692
|
+
return details;
|
|
4693
|
+
};
|
|
4694
|
+
|
|
4695
|
+
/* eslint-disable n/no-unsupported-features/node-builtins -- Electron 43 provides the node:sqlite API used by the main process */
|
|
4696
|
+
const getDatabaseError = error => {
|
|
4697
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4698
|
+
if (message.toLowerCase().includes('locked') || message.toLowerCase().includes('busy')) {
|
|
4699
|
+
return new Error('Chrome cookie database is busy. Close Chrome and try again.');
|
|
4700
|
+
}
|
|
4701
|
+
return new Error('Failed to read the Chrome cookie database');
|
|
4702
|
+
};
|
|
4703
|
+
const withDatabase = (path, fn) => {
|
|
4704
|
+
let database;
|
|
4705
|
+
try {
|
|
4706
|
+
database = new DatabaseSync(path, {
|
|
4707
|
+
readOnly: true
|
|
4708
|
+
});
|
|
4709
|
+
database.exec('PRAGMA busy_timeout = 1000');
|
|
4710
|
+
return fn(database);
|
|
4711
|
+
} catch (error) {
|
|
4712
|
+
if (error instanceof Error && error.message.startsWith('Unsupported Chrome cookie database version')) {
|
|
4713
|
+
throw error;
|
|
4714
|
+
}
|
|
4715
|
+
throw getDatabaseError(error);
|
|
4716
|
+
} finally {
|
|
4717
|
+
database?.close();
|
|
4718
|
+
}
|
|
4719
|
+
};
|
|
4720
|
+
const getVersion = database => {
|
|
4721
|
+
const row = database.prepare(`SELECT value FROM meta WHERE key = 'version'`).get();
|
|
4722
|
+
const version = Number(row?.value);
|
|
4723
|
+
if (version !== 24) {
|
|
4724
|
+
throw new Error(`Unsupported Chrome cookie database version ${Number.isFinite(version) ? version : 'unknown'}`);
|
|
4725
|
+
}
|
|
4726
|
+
return version;
|
|
4727
|
+
};
|
|
4728
|
+
const getCookieCount = path => {
|
|
4729
|
+
return withDatabase(path, database => {
|
|
4730
|
+
getVersion(database);
|
|
4731
|
+
const row = database.prepare('SELECT COUNT(*) AS count FROM cookies').get();
|
|
4732
|
+
return row.count;
|
|
4733
|
+
});
|
|
4734
|
+
};
|
|
4735
|
+
const readCookies = path => {
|
|
4736
|
+
return withDatabase(path, database => {
|
|
4737
|
+
const version = getVersion(database);
|
|
4738
|
+
const rows = database.prepare(`
|
|
4739
|
+
SELECT
|
|
4740
|
+
encrypted_value AS encryptedValue,
|
|
4741
|
+
CAST(expires_utc AS TEXT) AS expiresUtc,
|
|
4742
|
+
has_expires AS hasExpires,
|
|
4743
|
+
host_key AS hostKey,
|
|
4744
|
+
is_httponly AS isHttpOnly,
|
|
4745
|
+
is_secure AS isSecure,
|
|
4746
|
+
name,
|
|
4747
|
+
path,
|
|
4748
|
+
samesite AS sameSite,
|
|
4749
|
+
top_frame_site_key AS topFrameSiteKey,
|
|
4750
|
+
value
|
|
4751
|
+
FROM cookies
|
|
4752
|
+
`).all();
|
|
4753
|
+
return {
|
|
4754
|
+
rows,
|
|
4755
|
+
version
|
|
4756
|
+
};
|
|
4757
|
+
});
|
|
4758
|
+
};
|
|
4759
|
+
|
|
4760
|
+
const isValidProfileDirectory = value => {
|
|
4761
|
+
return value !== '' && value !== '.' && value !== '..' && !value.includes('/') && !value.includes('\\');
|
|
4762
|
+
};
|
|
4763
|
+
const getCookieDatabasePath = (chromeDataDirectory, profileDirectory) => {
|
|
4764
|
+
const profilePath = join$1(chromeDataDirectory, profileDirectory);
|
|
4765
|
+
const candidates = [join$1(profilePath, 'Cookies'), join$1(profilePath, 'Network', 'Cookies')];
|
|
4766
|
+
for (const candidate of candidates) {
|
|
4767
|
+
if (existsSync(candidate)) {
|
|
4768
|
+
return candidate;
|
|
4769
|
+
}
|
|
4770
|
+
}
|
|
4771
|
+
throw new Error(`Chrome cookie database was not found for profile ${profileDirectory}`);
|
|
4772
|
+
};
|
|
4773
|
+
const getMostRecentlyActiveProfile = infoCache => {
|
|
4774
|
+
let selected;
|
|
4775
|
+
let selectedActiveTime = -Infinity;
|
|
4776
|
+
for (const [directory, info] of Object.entries(infoCache)) {
|
|
4777
|
+
if (!isValidProfileDirectory(directory)) {
|
|
4778
|
+
continue;
|
|
4779
|
+
}
|
|
4780
|
+
const activeTime = typeof info.active_time === 'number' && Number.isFinite(info.active_time) ? info.active_time : -Infinity;
|
|
4781
|
+
if (selected === undefined || activeTime > selectedActiveTime) {
|
|
4782
|
+
selected = directory;
|
|
4783
|
+
selectedActiveTime = activeTime;
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4786
|
+
return selected;
|
|
4787
|
+
};
|
|
4788
|
+
const getChromeDataDirectory = () => {
|
|
4789
|
+
const configDirectory = process.env.XDG_CONFIG_HOME || join$1(homedir(), '.config');
|
|
4790
|
+
return join$1(configDirectory, 'google-chrome');
|
|
4791
|
+
};
|
|
4792
|
+
const getActiveProfile = chromeDataDirectory => {
|
|
4793
|
+
const localStatePath = join$1(chromeDataDirectory, 'Local State');
|
|
4794
|
+
if (!existsSync(localStatePath)) {
|
|
4795
|
+
throw new Error(`Google Chrome profile data was not found at ${chromeDataDirectory}`);
|
|
4796
|
+
}
|
|
4797
|
+
let localState;
|
|
4798
|
+
try {
|
|
4799
|
+
localState = JSON.parse(readFileSync(localStatePath, 'utf8'));
|
|
4800
|
+
} catch {
|
|
4801
|
+
throw new Error('Google Chrome profile metadata is invalid');
|
|
4802
|
+
}
|
|
4803
|
+
const infoCache = localState.profile?.info_cache || {};
|
|
4804
|
+
const orderedProfile = localState.profile?.profiles_order?.find(isValidProfileDirectory);
|
|
4805
|
+
const directory = getMostRecentlyActiveProfile(infoCache) || orderedProfile || 'Default';
|
|
4806
|
+
const name = infoCache[directory]?.name || directory;
|
|
4807
|
+
const cookieDatabasePath = getCookieDatabasePath(chromeDataDirectory, directory);
|
|
4808
|
+
return {
|
|
4809
|
+
cookieDatabasePath,
|
|
4810
|
+
directory,
|
|
4811
|
+
name
|
|
4812
|
+
};
|
|
4813
|
+
};
|
|
4814
|
+
|
|
4815
|
+
const MainFrame = 'mainFrame';
|
|
4816
|
+
const Script = 'script';
|
|
4817
|
+
const Xhr = 'xhr';
|
|
4818
|
+
|
|
4819
|
+
const Get = 'GET';
|
|
4820
|
+
const Head = 'HEAD';
|
|
4821
|
+
const Options = 'OPTIONS';
|
|
4822
|
+
const Post = 'POST';
|
|
4823
|
+
|
|
4824
|
+
// @ts-ignore
|
|
4825
|
+
|
|
4826
|
+
const getBeforeRequestResponseMainFrame = (method, url) => {
|
|
4827
|
+
return {};
|
|
4828
|
+
};
|
|
4829
|
+
const cancelIfStartsWith = (url, canceledUrls) => {
|
|
4830
|
+
for (const canceledUrl of canceledUrls) {
|
|
4831
|
+
if (url.startsWith(canceledUrl)) {
|
|
4832
|
+
return {
|
|
4833
|
+
cancel: true
|
|
4834
|
+
};
|
|
4835
|
+
}
|
|
4836
|
+
}
|
|
4837
|
+
return {};
|
|
4838
|
+
};
|
|
4839
|
+
const getBeforeRequestResponseXhrPost = url => {
|
|
4840
|
+
const canceledUrls = ['https://www.youtube.com/api/stats/qoe', 'https://www.youtube.com/youtubei/v1/log_event', 'https://play.google.com/log'];
|
|
4841
|
+
return cancelIfStartsWith(url, canceledUrls);
|
|
4842
|
+
};
|
|
4843
|
+
const getBeforeRequestResponseXhrGet = url => {
|
|
4844
|
+
const canceledUrls = ['https://www.youtube.com/pagead/', 'https://www.youtube.com/api/stats/qoe', 'https://www.youtube.com/api/stats/ads', 'https://www.youtube.com/api/stats/delayplay', 'https://www.youtube.com/ptracking', 'https://www.youtube.com/api/timedtext', 'https://www.youtube.com/pcs/activeview', 'https://googleads.g.doubleclick.net/pagead/id'];
|
|
4845
|
+
return cancelIfStartsWith(url, canceledUrls);
|
|
4846
|
+
};
|
|
4847
|
+
const getBeforeRequestResponseXhrOptions = url => {
|
|
4848
|
+
const canceledUrls = ['https://play.google.com/log'];
|
|
4849
|
+
return cancelIfStartsWith(url, canceledUrls);
|
|
4850
|
+
};
|
|
4851
|
+
const getBeforeRequestResponseXhrHead = url => {
|
|
4852
|
+
const canceledUrls = ['https://www.youtube.com/generate_204'];
|
|
4853
|
+
return cancelIfStartsWith(url, canceledUrls);
|
|
4854
|
+
};
|
|
4855
|
+
const getBeforeRequestResponseXhr = (method, url) => {
|
|
4856
|
+
switch (method) {
|
|
4857
|
+
case Get:
|
|
4858
|
+
return getBeforeRequestResponseXhrGet(url);
|
|
4859
|
+
case Head:
|
|
4860
|
+
return getBeforeRequestResponseXhrHead(url);
|
|
4861
|
+
case Options:
|
|
4862
|
+
return getBeforeRequestResponseXhrOptions(url);
|
|
4863
|
+
case Post:
|
|
4864
|
+
return getBeforeRequestResponseXhrPost(url);
|
|
4865
|
+
default:
|
|
4866
|
+
return {};
|
|
4867
|
+
}
|
|
4868
|
+
};
|
|
4869
|
+
const getBeforeRequestResponseDefault = (method, url) => {
|
|
4870
|
+
return {};
|
|
4871
|
+
};
|
|
4872
|
+
const getBeforeRequestResponseScript = (method, url) => {
|
|
4873
|
+
const canceledUrls = ['https://static.doubleclick.net'];
|
|
4874
|
+
return cancelIfStartsWith(url, canceledUrls);
|
|
4875
|
+
};
|
|
4876
|
+
const getBeforeRequestResponse = details => {
|
|
4877
|
+
const {
|
|
4878
|
+
method,
|
|
4879
|
+
resourceType,
|
|
4880
|
+
url
|
|
4881
|
+
} = details;
|
|
4882
|
+
switch (resourceType) {
|
|
4883
|
+
case MainFrame:
|
|
4884
|
+
return getBeforeRequestResponseMainFrame();
|
|
4885
|
+
case Script:
|
|
4886
|
+
return getBeforeRequestResponseScript(method, url);
|
|
4887
|
+
case Xhr:
|
|
4888
|
+
return getBeforeRequestResponseXhr(method, url);
|
|
4889
|
+
default:
|
|
4890
|
+
return getBeforeRequestResponseDefault();
|
|
4891
|
+
}
|
|
4892
|
+
};
|
|
4893
|
+
|
|
4894
|
+
/**
|
|
4895
|
+
*
|
|
4896
|
+
* @param {Electron.OnBeforeRequestListenerDetails } details
|
|
4897
|
+
* @param {(response: globalThis.Electron.CallbackResponse) => void} callback
|
|
4898
|
+
*/
|
|
4899
|
+
const handleBeforeRequest = (details, callback) => {
|
|
4900
|
+
const response = getBeforeRequestResponse(details);
|
|
4901
|
+
callback(response);
|
|
4902
|
+
};
|
|
4903
|
+
const filter = {
|
|
4904
|
+
// urls: ['https://*.youtube.com/*'],
|
|
4905
|
+
urls: ['<all_urls>']
|
|
4906
|
+
};
|
|
4907
|
+
|
|
4908
|
+
const state = {
|
|
4909
|
+
session: undefined
|
|
4910
|
+
};
|
|
4911
|
+
const isAllowedPermission = permission => {
|
|
4912
|
+
switch (permission) {
|
|
4913
|
+
case ClipBoardRead:
|
|
4914
|
+
case ClipBoardSanitizedWrite:
|
|
4915
|
+
case FullScreen:
|
|
4916
|
+
case GeoLocation:
|
|
4917
|
+
case WindowPlacement:
|
|
4918
|
+
return true;
|
|
4919
|
+
default:
|
|
4920
|
+
return false;
|
|
4921
|
+
}
|
|
4922
|
+
};
|
|
4923
|
+
const handlePermissionRequest = (webContents, permission, callback, details) => {
|
|
4924
|
+
callback(isAllowedPermission(permission));
|
|
4925
|
+
};
|
|
4926
|
+
const handlePermissionCheck = (webContents, permission, origin, details) => {
|
|
4927
|
+
return isAllowedPermission(permission);
|
|
4928
|
+
};
|
|
4929
|
+
const createSession = () => {
|
|
4930
|
+
const sessionId = `persist:browserView`;
|
|
4931
|
+
const session = Electron.session.fromPartition(sessionId, {
|
|
4932
|
+
cache: true
|
|
4933
|
+
});
|
|
4934
|
+
session.setPermissionRequestHandler(handlePermissionRequest);
|
|
4935
|
+
session.setPermissionCheckHandler(handlePermissionCheck);
|
|
4936
|
+
session.webRequest.onBeforeRequest(filter, handleBeforeRequest);
|
|
4937
|
+
// session.webRequest.addSessionChromeExtensions(session)
|
|
4938
|
+
return session;
|
|
4939
|
+
};
|
|
4940
|
+
const getSession = () => {
|
|
4941
|
+
state.session ||= createSession();
|
|
4942
|
+
return state.session;
|
|
4943
|
+
};
|
|
4944
|
+
|
|
4945
|
+
const assertLinux = () => {
|
|
4946
|
+
if (process.platform !== 'linux') {
|
|
4947
|
+
throw new Error('Importing Chrome cookies is only supported on Linux');
|
|
4948
|
+
}
|
|
4949
|
+
};
|
|
4950
|
+
const getInfoFromDirectory = chromeDataDirectory => {
|
|
4951
|
+
const profile = getActiveProfile(chromeDataDirectory);
|
|
4952
|
+
const cookieCount = getCookieCount(profile.cookieDatabasePath);
|
|
4953
|
+
return {
|
|
4954
|
+
cookieCount,
|
|
4955
|
+
profileDirectory: profile.directory,
|
|
4956
|
+
profileName: profile.name
|
|
4957
|
+
};
|
|
4958
|
+
};
|
|
4959
|
+
const getInfo = () => {
|
|
4960
|
+
assertLinux();
|
|
4961
|
+
return getInfoFromDirectory(getChromeDataDirectory());
|
|
4962
|
+
};
|
|
4963
|
+
const importFromDirectory = async (chromeDataDirectory, session) => {
|
|
4964
|
+
const profile = getActiveProfile(chromeDataDirectory);
|
|
4965
|
+
const {
|
|
4966
|
+
rows,
|
|
4967
|
+
version
|
|
4968
|
+
} = readCookies(profile.cookieDatabasePath);
|
|
4969
|
+
const cookies = [];
|
|
4970
|
+
let skipped = 0;
|
|
4971
|
+
let unsupportedEncryption = 0;
|
|
4972
|
+
for (const row of rows) {
|
|
4973
|
+
try {
|
|
4974
|
+
const cookie = convert(row, version);
|
|
4975
|
+
if (cookie) {
|
|
4976
|
+
cookies.push(cookie);
|
|
4977
|
+
} else {
|
|
4978
|
+
skipped++;
|
|
4979
|
+
}
|
|
4980
|
+
} catch (error) {
|
|
4981
|
+
skipped++;
|
|
4982
|
+
if (error instanceof UnsupportedChromeCookieEncryptionError) {
|
|
4983
|
+
unsupportedEncryption++;
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
if (cookies.length === 0 && unsupportedEncryption > 0) {
|
|
4988
|
+
throw new Error('Unsupported Chrome cookie encryption format');
|
|
4989
|
+
}
|
|
4990
|
+
let imported = 0;
|
|
4991
|
+
let failed = 0;
|
|
4992
|
+
for (const cookie of cookies) {
|
|
4993
|
+
try {
|
|
4994
|
+
await session.cookies.set(cookie);
|
|
4995
|
+
imported++;
|
|
4996
|
+
} catch {
|
|
4997
|
+
failed++;
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
await session.cookies.flushStore();
|
|
5001
|
+
return {
|
|
5002
|
+
failed,
|
|
5003
|
+
imported,
|
|
5004
|
+
skipped
|
|
5005
|
+
};
|
|
5006
|
+
};
|
|
5007
|
+
const importCookies = async () => {
|
|
5008
|
+
assertLinux();
|
|
5009
|
+
return importFromDirectory(getChromeDataDirectory(), getSession());
|
|
5010
|
+
};
|
|
5011
|
+
|
|
4606
5012
|
const handleTimeout = () => {
|
|
4607
5013
|
throw new Error('oops');
|
|
4608
5014
|
};
|
|
@@ -5750,14 +6156,14 @@ const getKeyBindingIdentifier = input => {
|
|
|
5750
6156
|
return identifier;
|
|
5751
6157
|
};
|
|
5752
6158
|
|
|
5753
|
-
const key$
|
|
5754
|
-
const attach$
|
|
6159
|
+
const key$7 = 'before-input';
|
|
6160
|
+
const attach$7 = (webContents, listener) => {
|
|
5755
6161
|
webContents.on(BeforeInputEvent, listener);
|
|
5756
6162
|
};
|
|
5757
|
-
const detach$
|
|
6163
|
+
const detach$7 = (webContents, listener) => {
|
|
5758
6164
|
webContents.off(BeforeInputEvent, listener);
|
|
5759
6165
|
};
|
|
5760
|
-
const handler$
|
|
6166
|
+
const handler$7 = (event, input) => {
|
|
5761
6167
|
if (input.type !== KeyDown) {
|
|
5762
6168
|
return {
|
|
5763
6169
|
messages: [],
|
|
@@ -5782,6 +6188,28 @@ const handler$6 = (event, input) => {
|
|
|
5782
6188
|
};
|
|
5783
6189
|
|
|
5784
6190
|
const ElectronBrowserViewEventListenerBeforeInput = {
|
|
6191
|
+
__proto__: null,
|
|
6192
|
+
attach: attach$7,
|
|
6193
|
+
detach: detach$7,
|
|
6194
|
+
handler: handler$7,
|
|
6195
|
+
key: key$7
|
|
6196
|
+
};
|
|
6197
|
+
|
|
6198
|
+
const key$6 = 'context-menu';
|
|
6199
|
+
const attach$6 = (webContents, listener) => {
|
|
6200
|
+
webContents.on(ContextMenu, listener);
|
|
6201
|
+
};
|
|
6202
|
+
const detach$6 = (webContents, listener) => {
|
|
6203
|
+
webContents.off(ContextMenu, listener);
|
|
6204
|
+
};
|
|
6205
|
+
const handler$6 = (event, params) => {
|
|
6206
|
+
return {
|
|
6207
|
+
messages: [['handleContextMenu', params]],
|
|
6208
|
+
result: undefined
|
|
6209
|
+
};
|
|
6210
|
+
};
|
|
6211
|
+
|
|
6212
|
+
const ElectronBrowserViewEventListenerContextMenu = {
|
|
5785
6213
|
__proto__: null,
|
|
5786
6214
|
attach: attach$6,
|
|
5787
6215
|
detach: detach$6,
|
|
@@ -5789,21 +6217,21 @@ const ElectronBrowserViewEventListenerBeforeInput = {
|
|
|
5789
6217
|
key: key$6
|
|
5790
6218
|
};
|
|
5791
6219
|
|
|
5792
|
-
const key$5 = '
|
|
6220
|
+
const key$5 = 'destroyed';
|
|
5793
6221
|
const attach$5 = (webContents, listener) => {
|
|
5794
|
-
webContents.on(
|
|
6222
|
+
webContents.on(Destroyed, listener);
|
|
5795
6223
|
};
|
|
5796
6224
|
const detach$5 = (webContents, listener) => {
|
|
5797
|
-
webContents.off(
|
|
6225
|
+
webContents.off(Destroyed, listener);
|
|
5798
6226
|
};
|
|
5799
|
-
const handler$5 = (
|
|
6227
|
+
const handler$5 = () => {
|
|
5800
6228
|
return {
|
|
5801
|
-
messages: [['
|
|
6229
|
+
messages: [['handleBrowserViewDestroyed']],
|
|
5802
6230
|
result: undefined
|
|
5803
6231
|
};
|
|
5804
6232
|
};
|
|
5805
6233
|
|
|
5806
|
-
const
|
|
6234
|
+
const ElectronBrowserViewEventListenerDestroyed = {
|
|
5807
6235
|
__proto__: null,
|
|
5808
6236
|
attach: attach$5,
|
|
5809
6237
|
detach: detach$5,
|
|
@@ -5811,21 +6239,21 @@ const ElectronBrowserViewEventListenerContextMenu = {
|
|
|
5811
6239
|
key: key$5
|
|
5812
6240
|
};
|
|
5813
6241
|
|
|
5814
|
-
const key$4 = '
|
|
6242
|
+
const key$4 = 'did-navigate';
|
|
5815
6243
|
const attach$4 = (webContents, listener) => {
|
|
5816
|
-
webContents.on(
|
|
6244
|
+
webContents.on(DidNavigate, listener);
|
|
5817
6245
|
};
|
|
5818
6246
|
const detach$4 = (webContents, listener) => {
|
|
5819
|
-
webContents.off(
|
|
6247
|
+
webContents.off(DidNavigate, listener);
|
|
5820
6248
|
};
|
|
5821
|
-
const handler$4 = () => {
|
|
6249
|
+
const handler$4 = (event, url) => {
|
|
5822
6250
|
return {
|
|
5823
|
-
messages: [['
|
|
6251
|
+
messages: [['handleDidNavigate', url]],
|
|
5824
6252
|
result: undefined
|
|
5825
6253
|
};
|
|
5826
6254
|
};
|
|
5827
6255
|
|
|
5828
|
-
const
|
|
6256
|
+
const ElectronBrowserViewEventListenerDidNavigate = {
|
|
5829
6257
|
__proto__: null,
|
|
5830
6258
|
attach: attach$4,
|
|
5831
6259
|
detach: detach$4,
|
|
@@ -5833,21 +6261,64 @@ const ElectronBrowserViewEventListenerDestroyed = {
|
|
|
5833
6261
|
key: key$4
|
|
5834
6262
|
};
|
|
5835
6263
|
|
|
5836
|
-
const
|
|
6264
|
+
const pendingLogins = new Map();
|
|
6265
|
+
let nextRequestId = 1;
|
|
6266
|
+
const add = (webContentsId, callback) => {
|
|
6267
|
+
const requestId = `${webContentsId}:${nextRequestId++}`;
|
|
6268
|
+
pendingLogins.set(requestId, {
|
|
6269
|
+
callback,
|
|
6270
|
+
webContentsId
|
|
6271
|
+
});
|
|
6272
|
+
return requestId;
|
|
6273
|
+
};
|
|
6274
|
+
const take = requestId => {
|
|
6275
|
+
const pendingLogin = pendingLogins.get(requestId);
|
|
6276
|
+
pendingLogins.delete(requestId);
|
|
6277
|
+
return pendingLogin;
|
|
6278
|
+
};
|
|
6279
|
+
const accept = (requestId, username, password) => {
|
|
6280
|
+
const pendingLogin = take(requestId);
|
|
6281
|
+
pendingLogin?.callback(username, password);
|
|
6282
|
+
};
|
|
6283
|
+
const cancel = requestId => {
|
|
6284
|
+
const pendingLogin = take(requestId);
|
|
6285
|
+
pendingLogin?.callback();
|
|
6286
|
+
};
|
|
6287
|
+
const cancelForWebContents = webContentsId => {
|
|
6288
|
+
for (const [requestId, pendingLogin] of pendingLogins) {
|
|
6289
|
+
if (pendingLogin.webContentsId !== webContentsId) {
|
|
6290
|
+
continue;
|
|
6291
|
+
}
|
|
6292
|
+
pendingLogins.delete(requestId);
|
|
6293
|
+
pendingLogin.callback();
|
|
6294
|
+
}
|
|
6295
|
+
};
|
|
6296
|
+
|
|
6297
|
+
const key$3 = Login;
|
|
5837
6298
|
const attach$3 = (webContents, listener) => {
|
|
5838
|
-
webContents.on(
|
|
6299
|
+
webContents.on(Login, listener);
|
|
5839
6300
|
};
|
|
5840
6301
|
const detach$3 = (webContents, listener) => {
|
|
5841
|
-
webContents.off(
|
|
6302
|
+
webContents.off(Login, listener);
|
|
5842
6303
|
};
|
|
5843
|
-
const handler$3 = (event,
|
|
6304
|
+
const handler$3 = (event, authenticationResponseDetails, authInfo, callback, webContentsId) => {
|
|
6305
|
+
event.preventDefault();
|
|
6306
|
+
const requestId = add(webContentsId, callback);
|
|
5844
6307
|
return {
|
|
5845
|
-
messages: [['
|
|
6308
|
+
messages: [['handleLogin', {
|
|
6309
|
+
host: authInfo.host,
|
|
6310
|
+
isProxy: authInfo.isProxy,
|
|
6311
|
+
port: authInfo.port,
|
|
6312
|
+
realm: authInfo.realm,
|
|
6313
|
+
requestId,
|
|
6314
|
+
scheme: authInfo.scheme,
|
|
6315
|
+
url: String(authenticationResponseDetails.url)
|
|
6316
|
+
}]],
|
|
5846
6317
|
result: undefined
|
|
5847
6318
|
};
|
|
5848
6319
|
};
|
|
5849
6320
|
|
|
5850
|
-
const
|
|
6321
|
+
const ElectronBrowserViewEventListenerLogin = {
|
|
5851
6322
|
__proto__: null,
|
|
5852
6323
|
attach: attach$3,
|
|
5853
6324
|
detach: detach$3,
|
|
@@ -5934,141 +6405,12 @@ const ElectronBrowserViewEventListeners = {
|
|
|
5934
6405
|
contextMenu: ElectronBrowserViewEventListenerContextMenu,
|
|
5935
6406
|
destroyed: ElectronBrowserViewEventListenerDestroyed,
|
|
5936
6407
|
didNavigate: ElectronBrowserViewEventListenerDidNavigate,
|
|
6408
|
+
login: ElectronBrowserViewEventListenerLogin,
|
|
5937
6409
|
pageTitleUpdated: ElectronBrowserViewEventListenerPageTitleUpdated,
|
|
5938
6410
|
willNavigate: ElectronBrowserViewEventListenerWillNavigate,
|
|
5939
6411
|
windowOpen: ElectronBrowserViewEventListenerWindowOpen
|
|
5940
6412
|
};
|
|
5941
6413
|
|
|
5942
|
-
const MainFrame = 'mainFrame';
|
|
5943
|
-
const Script = 'script';
|
|
5944
|
-
const Xhr = 'xhr';
|
|
5945
|
-
|
|
5946
|
-
const Get = 'GET';
|
|
5947
|
-
const Head = 'HEAD';
|
|
5948
|
-
const Options = 'OPTIONS';
|
|
5949
|
-
const Post = 'POST';
|
|
5950
|
-
|
|
5951
|
-
// @ts-ignore
|
|
5952
|
-
|
|
5953
|
-
const getBeforeRequestResponseMainFrame = (method, url) => {
|
|
5954
|
-
return {};
|
|
5955
|
-
};
|
|
5956
|
-
const cancelIfStartsWith = (url, canceledUrls) => {
|
|
5957
|
-
for (const canceledUrl of canceledUrls) {
|
|
5958
|
-
if (url.startsWith(canceledUrl)) {
|
|
5959
|
-
return {
|
|
5960
|
-
cancel: true
|
|
5961
|
-
};
|
|
5962
|
-
}
|
|
5963
|
-
}
|
|
5964
|
-
return {};
|
|
5965
|
-
};
|
|
5966
|
-
const getBeforeRequestResponseXhrPost = url => {
|
|
5967
|
-
const canceledUrls = ['https://www.youtube.com/api/stats/qoe', 'https://www.youtube.com/youtubei/v1/log_event', 'https://play.google.com/log'];
|
|
5968
|
-
return cancelIfStartsWith(url, canceledUrls);
|
|
5969
|
-
};
|
|
5970
|
-
const getBeforeRequestResponseXhrGet = url => {
|
|
5971
|
-
const canceledUrls = ['https://www.youtube.com/pagead/', 'https://www.youtube.com/api/stats/qoe', 'https://www.youtube.com/api/stats/ads', 'https://www.youtube.com/api/stats/delayplay', 'https://www.youtube.com/ptracking', 'https://www.youtube.com/api/timedtext', 'https://www.youtube.com/pcs/activeview', 'https://googleads.g.doubleclick.net/pagead/id'];
|
|
5972
|
-
return cancelIfStartsWith(url, canceledUrls);
|
|
5973
|
-
};
|
|
5974
|
-
const getBeforeRequestResponseXhrOptions = url => {
|
|
5975
|
-
const canceledUrls = ['https://play.google.com/log'];
|
|
5976
|
-
return cancelIfStartsWith(url, canceledUrls);
|
|
5977
|
-
};
|
|
5978
|
-
const getBeforeRequestResponseXhrHead = url => {
|
|
5979
|
-
const canceledUrls = ['https://www.youtube.com/generate_204'];
|
|
5980
|
-
return cancelIfStartsWith(url, canceledUrls);
|
|
5981
|
-
};
|
|
5982
|
-
const getBeforeRequestResponseXhr = (method, url) => {
|
|
5983
|
-
switch (method) {
|
|
5984
|
-
case Get:
|
|
5985
|
-
return getBeforeRequestResponseXhrGet(url);
|
|
5986
|
-
case Head:
|
|
5987
|
-
return getBeforeRequestResponseXhrHead(url);
|
|
5988
|
-
case Options:
|
|
5989
|
-
return getBeforeRequestResponseXhrOptions(url);
|
|
5990
|
-
case Post:
|
|
5991
|
-
return getBeforeRequestResponseXhrPost(url);
|
|
5992
|
-
default:
|
|
5993
|
-
return {};
|
|
5994
|
-
}
|
|
5995
|
-
};
|
|
5996
|
-
const getBeforeRequestResponseDefault = (method, url) => {
|
|
5997
|
-
return {};
|
|
5998
|
-
};
|
|
5999
|
-
const getBeforeRequestResponseScript = (method, url) => {
|
|
6000
|
-
const canceledUrls = ['https://static.doubleclick.net'];
|
|
6001
|
-
return cancelIfStartsWith(url, canceledUrls);
|
|
6002
|
-
};
|
|
6003
|
-
const getBeforeRequestResponse = details => {
|
|
6004
|
-
const {
|
|
6005
|
-
method,
|
|
6006
|
-
resourceType,
|
|
6007
|
-
url
|
|
6008
|
-
} = details;
|
|
6009
|
-
switch (resourceType) {
|
|
6010
|
-
case MainFrame:
|
|
6011
|
-
return getBeforeRequestResponseMainFrame();
|
|
6012
|
-
case Script:
|
|
6013
|
-
return getBeforeRequestResponseScript(method, url);
|
|
6014
|
-
case Xhr:
|
|
6015
|
-
return getBeforeRequestResponseXhr(method, url);
|
|
6016
|
-
default:
|
|
6017
|
-
return getBeforeRequestResponseDefault();
|
|
6018
|
-
}
|
|
6019
|
-
};
|
|
6020
|
-
|
|
6021
|
-
/**
|
|
6022
|
-
*
|
|
6023
|
-
* @param {Electron.OnBeforeRequestListenerDetails } details
|
|
6024
|
-
* @param {(response: globalThis.Electron.CallbackResponse) => void} callback
|
|
6025
|
-
*/
|
|
6026
|
-
const handleBeforeRequest = (details, callback) => {
|
|
6027
|
-
const response = getBeforeRequestResponse(details);
|
|
6028
|
-
callback(response);
|
|
6029
|
-
};
|
|
6030
|
-
const filter = {
|
|
6031
|
-
// urls: ['https://*.youtube.com/*'],
|
|
6032
|
-
urls: ['<all_urls>']
|
|
6033
|
-
};
|
|
6034
|
-
|
|
6035
|
-
const state = {
|
|
6036
|
-
session: undefined
|
|
6037
|
-
};
|
|
6038
|
-
const isAllowedPermission = permission => {
|
|
6039
|
-
switch (permission) {
|
|
6040
|
-
case ClipBoardRead:
|
|
6041
|
-
case ClipBoardSanitizedWrite:
|
|
6042
|
-
case FullScreen:
|
|
6043
|
-
case GeoLocation:
|
|
6044
|
-
case WindowPlacement:
|
|
6045
|
-
return true;
|
|
6046
|
-
default:
|
|
6047
|
-
return false;
|
|
6048
|
-
}
|
|
6049
|
-
};
|
|
6050
|
-
const handlePermissionRequest = (webContents, permission, callback, details) => {
|
|
6051
|
-
callback(isAllowedPermission(permission));
|
|
6052
|
-
};
|
|
6053
|
-
const handlePermissionCheck = (webContents, permission, origin, details) => {
|
|
6054
|
-
return isAllowedPermission(permission);
|
|
6055
|
-
};
|
|
6056
|
-
const createSession = () => {
|
|
6057
|
-
const sessionId = `persist:browserView`;
|
|
6058
|
-
const session = Electron.session.fromPartition(sessionId, {
|
|
6059
|
-
cache: true
|
|
6060
|
-
});
|
|
6061
|
-
session.setPermissionRequestHandler(handlePermissionRequest);
|
|
6062
|
-
session.setPermissionCheckHandler(handlePermissionCheck);
|
|
6063
|
-
session.webRequest.onBeforeRequest(filter, handleBeforeRequest);
|
|
6064
|
-
// session.webRequest.addSessionChromeExtensions(session)
|
|
6065
|
-
return session;
|
|
6066
|
-
};
|
|
6067
|
-
const getSession = () => {
|
|
6068
|
-
state.session ||= createSession();
|
|
6069
|
-
return state.session;
|
|
6070
|
-
};
|
|
6071
|
-
|
|
6072
6414
|
const send = (method, ...params) => {
|
|
6073
6415
|
const rpc = get(EmbedsProcess);
|
|
6074
6416
|
if (!rpc) {
|
|
@@ -6092,7 +6434,7 @@ const createWebContentsView = async () => {
|
|
|
6092
6434
|
const {
|
|
6093
6435
|
id
|
|
6094
6436
|
} = webContents;
|
|
6095
|
-
add(id, browserWindow, view);
|
|
6437
|
+
add$1(id, browserWindow, view);
|
|
6096
6438
|
return id;
|
|
6097
6439
|
};
|
|
6098
6440
|
const attachEventListeners = webContentsId => {
|
|
@@ -6108,7 +6450,7 @@ const attachEventListeners = webContentsId => {
|
|
|
6108
6450
|
const {
|
|
6109
6451
|
messages,
|
|
6110
6452
|
result
|
|
6111
|
-
} = value.handler(...args);
|
|
6453
|
+
} = value.handler(...args, webContentsId);
|
|
6112
6454
|
for (const message of messages) {
|
|
6113
6455
|
const [key, ...rest] = message;
|
|
6114
6456
|
send(`ElectronWebContents.${key}`, webContentsId, ...rest);
|
|
@@ -6122,6 +6464,7 @@ const attachEventListeners = webContentsId => {
|
|
|
6122
6464
|
};
|
|
6123
6465
|
const disposeWebContentsView = browserViewId => {
|
|
6124
6466
|
console.log('[main process] dispose browser view', browserViewId);
|
|
6467
|
+
cancelForWebContents(browserViewId);
|
|
6125
6468
|
const instance = get$3(browserViewId);
|
|
6126
6469
|
if (!instance) {
|
|
6127
6470
|
return;
|
|
@@ -6657,6 +7000,8 @@ const trash = async path => {
|
|
|
6657
7000
|
const commandMap = {
|
|
6658
7001
|
'AppWindow.createAppWindow': createAppWindow,
|
|
6659
7002
|
'Beep.beep': beep$1,
|
|
7003
|
+
'ChromeCookieImport.getInfo': getInfo,
|
|
7004
|
+
'ChromeCookieImport.importCookies': importCookies,
|
|
6660
7005
|
'Crash.crashMainProcess': crashMainProcess$1,
|
|
6661
7006
|
'CreateMessagePort.createMessagePort': createMessagePort,
|
|
6662
7007
|
'CreatePidMap.createPidMap': createPidMap,
|
|
@@ -6695,7 +7040,9 @@ const commandMap = {
|
|
|
6695
7040
|
'ElectronWebContents.callFunction': callFunction,
|
|
6696
7041
|
'ElectronWebContents.dispose': dispose$1,
|
|
6697
7042
|
'ElectronWebContents.getStats': getStats$1,
|
|
7043
|
+
'ElectronWebContentsView.acceptLogin': accept,
|
|
6698
7044
|
'ElectronWebContentsView.attachEventListeners': attachEventListeners,
|
|
7045
|
+
'ElectronWebContentsView.cancelLogin': cancel,
|
|
6699
7046
|
'ElectronWebContentsView.createWebContentsView': createWebContentsView,
|
|
6700
7047
|
'ElectronWebContentsView.disposeWebContentsView': disposeWebContentsView,
|
|
6701
7048
|
'ElectronWebContentsViewFunctions.addToWindow': addToWindow,
|