@crawlee/puppeteer 3.0.0-alpha.2 → 3.0.0-alpha.3
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/LICENSE.md +201 -0
- package/{README.md → dist/README.md} +0 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +76 -0
- package/dist/internals/enqueue-links/click-elements.d.ts +188 -0
- package/dist/internals/enqueue-links/click-elements.d.ts.map +1 -0
- package/dist/internals/enqueue-links/click-elements.js +336 -0
- package/dist/internals/enqueue-links/click-elements.js.map +1 -0
- package/dist/internals/puppeteer-crawler.d.ts +149 -0
- package/dist/internals/puppeteer-crawler.d.ts.map +1 -0
- package/dist/internals/puppeteer-crawler.js +117 -0
- package/dist/internals/puppeteer-crawler.js.map +1 -0
- package/dist/internals/puppeteer-launcher.d.ts +134 -0
- package/dist/internals/puppeteer-launcher.d.ts.map +1 -0
- package/dist/internals/puppeteer-launcher.js +146 -0
- package/dist/internals/puppeteer-launcher.js.map +1 -0
- package/dist/internals/stealth/hiding_tricks.d.ts +10 -0
- package/dist/internals/stealth/hiding_tricks.d.ts.map +1 -0
- package/dist/internals/stealth/hiding_tricks.js +334 -0
- package/dist/internals/stealth/hiding_tricks.js.map +1 -0
- package/dist/internals/stealth/index.d.ts +40 -0
- package/dist/internals/stealth/index.d.ts.map +1 -0
- package/dist/internals/stealth/index.js +108 -0
- package/dist/internals/stealth/index.js.map +1 -0
- package/dist/internals/utils/puppeteer_request_interception.d.ts +60 -0
- package/dist/internals/utils/puppeteer_request_interception.d.ts.map +1 -0
- package/dist/internals/utils/puppeteer_request_interception.js +225 -0
- package/dist/internals/utils/puppeteer_request_interception.js.map +1 -0
- package/dist/internals/utils/puppeteer_utils.d.ts +298 -0
- package/dist/internals/utils/puppeteer_utils.d.ts.map +1 -0
- package/dist/internals/utils/puppeteer_utils.js +468 -0
- package/dist/internals/utils/puppeteer_utils.js.map +1 -0
- package/dist/package.json +66 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +8 -7
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Browser } from 'puppeteer';
|
|
2
|
+
import { PuppeteerPlugin } from '@crawlee/browser-pool';
|
|
3
|
+
import { BrowserLaunchContext, BrowserLauncher } from '@crawlee/browser';
|
|
4
|
+
import { StealthOptions } from './stealth';
|
|
5
|
+
/**
|
|
6
|
+
* Apify extends the launch options of Puppeteer.
|
|
7
|
+
* You can use any of the Puppeteer compatible
|
|
8
|
+
* [`LaunchOptions`](https://pptr.dev/#?product=Puppeteer&show=api-puppeteerlaunchoptions)
|
|
9
|
+
* options by providing the `launchOptions` property.
|
|
10
|
+
*
|
|
11
|
+
* **Example:**
|
|
12
|
+
* ```js
|
|
13
|
+
* // launch a headless Chrome (not Chromium)
|
|
14
|
+
* const launchContext = {
|
|
15
|
+
* // Apify helpers
|
|
16
|
+
* useChrome: true,
|
|
17
|
+
* proxyUrl: 'http://user:password@some.proxy.com'
|
|
18
|
+
* // Native Puppeteer options
|
|
19
|
+
* launchOptions: {
|
|
20
|
+
* headless: true,
|
|
21
|
+
* args: ['--some-flag'],
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export interface PuppeteerLaunchContext extends BrowserLaunchContext<PuppeteerPlugin['launchOptions'], unknown> {
|
|
27
|
+
/**
|
|
28
|
+
* `puppeteer.launch` [options](https://pptr.dev/#?product=Puppeteer&version=v5.5.0&show=api-puppeteerlaunchoptions)
|
|
29
|
+
*/
|
|
30
|
+
launchOptions?: PuppeteerPlugin['launchOptions'];
|
|
31
|
+
/**
|
|
32
|
+
* URL to a HTTP proxy server. It must define the port number,
|
|
33
|
+
* and it may also contain proxy username and password.
|
|
34
|
+
*
|
|
35
|
+
* Example: `http://bob:pass123@proxy.example.com:1234`.
|
|
36
|
+
*/
|
|
37
|
+
proxyUrl?: string;
|
|
38
|
+
/**
|
|
39
|
+
* The `User-Agent` HTTP header used by the browser.
|
|
40
|
+
* If not provided, the function sets `User-Agent` to a reasonable default
|
|
41
|
+
* to reduce the chance of detection of the crawler.
|
|
42
|
+
*/
|
|
43
|
+
userAgent?: string;
|
|
44
|
+
/**
|
|
45
|
+
* If `true` and `executablePath` is not set,
|
|
46
|
+
* Puppeteer will launch full Google Chrome browser available on the machine
|
|
47
|
+
* rather than the bundled Chromium. The path to Chrome executable
|
|
48
|
+
* is taken from the `APIFY_CHROME_EXECUTABLE_PATH` environment variable if provided,
|
|
49
|
+
* or defaults to the typical Google Chrome executable location specific for the operating system.
|
|
50
|
+
* By default, this option is `false`.
|
|
51
|
+
* @default false
|
|
52
|
+
*/
|
|
53
|
+
useChrome?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Already required module (`Object`). This enables usage of various Puppeteer
|
|
56
|
+
* wrappers such as `puppeteer-extra`.
|
|
57
|
+
*
|
|
58
|
+
* Take caution, because it can cause all kinds of unexpected errors and weird behavior.
|
|
59
|
+
* Apify SDK is not tested with any other library besides `puppeteer` itself.
|
|
60
|
+
*/
|
|
61
|
+
launcher?: unknown;
|
|
62
|
+
/**
|
|
63
|
+
* This setting hides most of the known properties that identify headless Chrome and makes it nearly undetectable.
|
|
64
|
+
* It is recommended to use it together with the `useChrome` set to `true`.
|
|
65
|
+
*/
|
|
66
|
+
stealth?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Using this configuration, you can disable some of the hiding tricks.
|
|
69
|
+
* For these settings to take effect `stealth` must be set to true
|
|
70
|
+
*/
|
|
71
|
+
stealthOptions?: StealthOptions;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* `PuppeteerLauncher` is based on the `BrowserLauncher`. It launches `puppeteer` browser instance.
|
|
75
|
+
* @ignore
|
|
76
|
+
*/
|
|
77
|
+
export declare class PuppeteerLauncher extends BrowserLauncher<PuppeteerPlugin, unknown> {
|
|
78
|
+
protected static optionsShape: {
|
|
79
|
+
launcher: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
80
|
+
userAgent: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
|
|
81
|
+
stealth: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
|
|
82
|
+
stealthOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
83
|
+
proxyUrl: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
|
|
84
|
+
useChrome: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
|
|
85
|
+
useIncognitoPages: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
|
|
86
|
+
userDataDir: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
|
|
87
|
+
launchOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
88
|
+
};
|
|
89
|
+
stealth?: boolean;
|
|
90
|
+
stealthOptions: StealthOptions;
|
|
91
|
+
/**
|
|
92
|
+
* All `PuppeteerLauncher` parameters are passed via an launchContext object.
|
|
93
|
+
*/
|
|
94
|
+
constructor(launchContext?: PuppeteerLaunchContext);
|
|
95
|
+
launch(): Promise<import("packages/browser-pool/dist/puppeteer/puppeteer-proxy-per-page").Browser>;
|
|
96
|
+
createLaunchOptions(): {
|
|
97
|
+
args?: string[] | undefined;
|
|
98
|
+
} & import("packages/utils/dist").Dictionary<unknown>;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Launches headless Chrome using Puppeteer pre-configured to work within the Apify platform.
|
|
102
|
+
* The function has the same argument and the return value as `puppeteer.launch()`.
|
|
103
|
+
* See [Puppeteer documentation](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions) for more details.
|
|
104
|
+
*
|
|
105
|
+
* The `launchPuppeteer()` function alters the following Puppeteer options:
|
|
106
|
+
*
|
|
107
|
+
* - Passes the setting from the `APIFY_HEADLESS` environment variable to the `headless` option,
|
|
108
|
+
* unless it was already defined by the caller or `APIFY_XVFB` environment variable is set to `1`.
|
|
109
|
+
* Note that Apify Actor cloud platform automatically sets `APIFY_HEADLESS=1` to all running actors.
|
|
110
|
+
* - Takes the `proxyUrl` option, validates it and adds it to `args` as `--proxy-server=XXX`.
|
|
111
|
+
* The proxy URL must define a port number and have one of the following schemes: `http://`,
|
|
112
|
+
* `https://`, `socks4://` or `socks5://`.
|
|
113
|
+
* If the proxy is HTTP (i.e. has the `http://` scheme) and contains username or password,
|
|
114
|
+
* the `launchPuppeteer` functions sets up an anonymous proxy HTTP
|
|
115
|
+
* to make the proxy work with headless Chrome. For more information, read the
|
|
116
|
+
* [blog post about proxy-chain library](https://blog.apify.com/how-to-make-headless-chrome-and-puppeteer-use-a-proxy-server-with-authentication-249a21a79212).
|
|
117
|
+
*
|
|
118
|
+
* To use this function, you need to have the [puppeteer](https://www.npmjs.com/package/puppeteer)
|
|
119
|
+
* NPM package installed in your project.
|
|
120
|
+
* When running on the Apify cloud, you can achieve that simply
|
|
121
|
+
* by using the `apify/actor-node-chrome` base Docker image for your actor - see
|
|
122
|
+
* [Apify Actor documentation](https://docs.apify.com/actor/build#base-images)
|
|
123
|
+
* for details.
|
|
124
|
+
*
|
|
125
|
+
* For an example of usage, see the [Puppeteer proxy Example](/docs/examples/puppeteer-with-proxy).
|
|
126
|
+
*
|
|
127
|
+
* @param [launchContext]
|
|
128
|
+
* All `PuppeteerLauncher` parameters are passed via an launchContext object.
|
|
129
|
+
* If you want to pass custom `puppeteer.launch(options)` options you can use the `PuppeteerLaunchContext.launchOptions` property.
|
|
130
|
+
* @returns
|
|
131
|
+
* Promise that resolves to Puppeteer's `Browser` instance.
|
|
132
|
+
*/
|
|
133
|
+
export declare function launchPuppeteer(launchContext?: PuppeteerLaunchContext): Promise<Browser>;
|
|
134
|
+
//# sourceMappingURL=puppeteer-launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"puppeteer-launcher.d.ts","sourceRoot":"","sources":["../../src/internals/puppeteer-launcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAyB,cAAc,EAAE,MAAM,WAAW,CAAC;AAalE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC3G;;OAEG;IACH,aAAa,CAAC,EAAE,eAAe,CAAC,eAAe,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAED;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,eAAe,CAAC,eAAe,EAAE,OAAO,CAAC;IAC5E,iBAA0B,YAAY;;;;;;;;;;MAMpC;IAEF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,cAAc,CAAC;IAE/B;;OAEG;gBACS,aAAa,GAAE,sBAA2B;IA0BvC,MAAM;IAYZ,mBAAmB;;;CAoC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,eAAe,CAAC,aAAa,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,CAAC,CAI9F"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.launchPuppeteer = exports.PuppeteerLauncher = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const ow_1 = tslib_1.__importDefault(require("ow"));
|
|
6
|
+
const browser_pool_1 = require("@crawlee/browser-pool");
|
|
7
|
+
const browser_1 = require("@crawlee/browser");
|
|
8
|
+
const stealth_1 = require("./stealth");
|
|
9
|
+
/**
|
|
10
|
+
* The default user agent used by `Actor.launchPuppeteer`.
|
|
11
|
+
* Last updated on 2020-05-22.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36';
|
|
14
|
+
const LAUNCH_PUPPETEER_DEFAULT_VIEWPORT = {
|
|
15
|
+
width: 1366,
|
|
16
|
+
height: 768,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* `PuppeteerLauncher` is based on the `BrowserLauncher`. It launches `puppeteer` browser instance.
|
|
20
|
+
* @ignore
|
|
21
|
+
*/
|
|
22
|
+
class PuppeteerLauncher extends browser_1.BrowserLauncher {
|
|
23
|
+
/**
|
|
24
|
+
* All `PuppeteerLauncher` parameters are passed via an launchContext object.
|
|
25
|
+
*/
|
|
26
|
+
constructor(launchContext = {}) {
|
|
27
|
+
(0, ow_1.default)(launchContext, 'PuppeteerLauncher', ow_1.default.object.exactShape(PuppeteerLauncher.optionsShape));
|
|
28
|
+
const { launcher = browser_1.BrowserLauncher.requireLauncherOrThrow('puppeteer', 'apify/actor-node-puppeteer-chrome'), userAgent, stealth = false, stealthOptions = {}, ...browserLauncherOptions } = launchContext;
|
|
29
|
+
super({
|
|
30
|
+
...browserLauncherOptions,
|
|
31
|
+
launcher,
|
|
32
|
+
});
|
|
33
|
+
Object.defineProperty(this, "stealth", {
|
|
34
|
+
enumerable: true,
|
|
35
|
+
configurable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
value: void 0
|
|
38
|
+
});
|
|
39
|
+
Object.defineProperty(this, "stealthOptions", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: void 0
|
|
44
|
+
});
|
|
45
|
+
this.userAgent = userAgent;
|
|
46
|
+
this.stealth = stealth;
|
|
47
|
+
this.stealthOptions = {
|
|
48
|
+
hideWebDriver: true,
|
|
49
|
+
...stealthOptions,
|
|
50
|
+
};
|
|
51
|
+
this.Plugin = browser_pool_1.PuppeteerPlugin;
|
|
52
|
+
}
|
|
53
|
+
async launch() {
|
|
54
|
+
const browser = await super.launch();
|
|
55
|
+
if (this.stealth) {
|
|
56
|
+
const { hideWebDriver, ...newStealthOptions } = this.stealthOptions;
|
|
57
|
+
(0, stealth_1.applyStealthToBrowser)(browser, newStealthOptions);
|
|
58
|
+
}
|
|
59
|
+
return browser;
|
|
60
|
+
}
|
|
61
|
+
createLaunchOptions() {
|
|
62
|
+
const launchOptions = super.createLaunchOptions();
|
|
63
|
+
launchOptions.args = launchOptions.args || [];
|
|
64
|
+
try {
|
|
65
|
+
// eslint-disable-next-line
|
|
66
|
+
const { isAtHome } = require('apify');
|
|
67
|
+
if (isAtHome())
|
|
68
|
+
launchOptions.args.push('--no-sandbox');
|
|
69
|
+
// eslint-disable-next-line no-empty
|
|
70
|
+
}
|
|
71
|
+
catch { }
|
|
72
|
+
launchOptions.defaultViewport ?? (launchOptions.defaultViewport = LAUNCH_PUPPETEER_DEFAULT_VIEWPORT);
|
|
73
|
+
// When User-Agent is not set and we're using Chromium or headless mode,
|
|
74
|
+
// it is better to use DEFAULT_USER_AGENT to reduce chance of detection
|
|
75
|
+
let { userAgent } = this;
|
|
76
|
+
if (!userAgent && (!launchOptions.executablePath || launchOptions.headless)) {
|
|
77
|
+
userAgent = DEFAULT_USER_AGENT;
|
|
78
|
+
}
|
|
79
|
+
if (userAgent) {
|
|
80
|
+
launchOptions.args.push(`--user-agent=${userAgent}`);
|
|
81
|
+
}
|
|
82
|
+
if (this.stealthOptions?.hideWebDriver) {
|
|
83
|
+
const idx = launchOptions.args.findIndex((arg) => arg.startsWith('--disable-blink-features='));
|
|
84
|
+
if (idx !== -1) {
|
|
85
|
+
const arg = launchOptions.args[idx];
|
|
86
|
+
launchOptions.args[idx] = `${arg},AutomationControlled`;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
launchOptions.args.push('--disable-blink-features=AutomationControlled');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return launchOptions;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.PuppeteerLauncher = PuppeteerLauncher;
|
|
96
|
+
Object.defineProperty(PuppeteerLauncher, "optionsShape", {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
configurable: true,
|
|
99
|
+
writable: true,
|
|
100
|
+
value: {
|
|
101
|
+
...browser_1.BrowserLauncher.optionsShape,
|
|
102
|
+
launcher: ow_1.default.optional.object,
|
|
103
|
+
userAgent: ow_1.default.optional.string,
|
|
104
|
+
stealth: ow_1.default.optional.boolean,
|
|
105
|
+
stealthOptions: ow_1.default.optional.object,
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* Launches headless Chrome using Puppeteer pre-configured to work within the Apify platform.
|
|
110
|
+
* The function has the same argument and the return value as `puppeteer.launch()`.
|
|
111
|
+
* See [Puppeteer documentation](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions) for more details.
|
|
112
|
+
*
|
|
113
|
+
* The `launchPuppeteer()` function alters the following Puppeteer options:
|
|
114
|
+
*
|
|
115
|
+
* - Passes the setting from the `APIFY_HEADLESS` environment variable to the `headless` option,
|
|
116
|
+
* unless it was already defined by the caller or `APIFY_XVFB` environment variable is set to `1`.
|
|
117
|
+
* Note that Apify Actor cloud platform automatically sets `APIFY_HEADLESS=1` to all running actors.
|
|
118
|
+
* - Takes the `proxyUrl` option, validates it and adds it to `args` as `--proxy-server=XXX`.
|
|
119
|
+
* The proxy URL must define a port number and have one of the following schemes: `http://`,
|
|
120
|
+
* `https://`, `socks4://` or `socks5://`.
|
|
121
|
+
* If the proxy is HTTP (i.e. has the `http://` scheme) and contains username or password,
|
|
122
|
+
* the `launchPuppeteer` functions sets up an anonymous proxy HTTP
|
|
123
|
+
* to make the proxy work with headless Chrome. For more information, read the
|
|
124
|
+
* [blog post about proxy-chain library](https://blog.apify.com/how-to-make-headless-chrome-and-puppeteer-use-a-proxy-server-with-authentication-249a21a79212).
|
|
125
|
+
*
|
|
126
|
+
* To use this function, you need to have the [puppeteer](https://www.npmjs.com/package/puppeteer)
|
|
127
|
+
* NPM package installed in your project.
|
|
128
|
+
* When running on the Apify cloud, you can achieve that simply
|
|
129
|
+
* by using the `apify/actor-node-chrome` base Docker image for your actor - see
|
|
130
|
+
* [Apify Actor documentation](https://docs.apify.com/actor/build#base-images)
|
|
131
|
+
* for details.
|
|
132
|
+
*
|
|
133
|
+
* For an example of usage, see the [Puppeteer proxy Example](/docs/examples/puppeteer-with-proxy).
|
|
134
|
+
*
|
|
135
|
+
* @param [launchContext]
|
|
136
|
+
* All `PuppeteerLauncher` parameters are passed via an launchContext object.
|
|
137
|
+
* If you want to pass custom `puppeteer.launch(options)` options you can use the `PuppeteerLaunchContext.launchOptions` property.
|
|
138
|
+
* @returns
|
|
139
|
+
* Promise that resolves to Puppeteer's `Browser` instance.
|
|
140
|
+
*/
|
|
141
|
+
async function launchPuppeteer(launchContext) {
|
|
142
|
+
const puppeteerLauncher = new PuppeteerLauncher(launchContext);
|
|
143
|
+
return puppeteerLauncher.launch();
|
|
144
|
+
}
|
|
145
|
+
exports.launchPuppeteer = launchPuppeteer;
|
|
146
|
+
//# sourceMappingURL=puppeteer-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"puppeteer-launcher.js","sourceRoot":"","sources":["../../src/internals/puppeteer-launcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const hackPermissions: () => void;
|
|
2
|
+
export declare const addLanguage: () => void;
|
|
3
|
+
export declare const emulateWebGL: () => void;
|
|
4
|
+
export declare const emulateWindowFrame: () => void;
|
|
5
|
+
export declare const addPlugins: () => void;
|
|
6
|
+
export declare const emulateConsoleDebug: () => void;
|
|
7
|
+
export declare const mockChrome: () => void;
|
|
8
|
+
export declare const mockChromeInIframe: () => void;
|
|
9
|
+
export declare const mockDeviceMemory: () => void;
|
|
10
|
+
//# sourceMappingURL=hiding_tricks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hiding_tricks.d.ts","sourceRoot":"","sources":["../../../src/internals/stealth/hiding_tricks.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,YAqC3B,CAAC;AAEF,eAAO,MAAM,WAAW,YAIvB,CAAC;AAEF,eAAO,MAAM,YAAY,YAoBxB,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAS9B,CAAC;AAEF,eAAO,MAAM,UAAU,YAmNtB,CAAC;AAEF,eAAO,MAAM,mBAAmB,YAI/B,CAAC;AAGF,eAAO,MAAM,UAAU,YAStB,CAAC;AAIF,eAAO,MAAM,kBAAkB,YA0D9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,YAK5B,CAAC"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mockDeviceMemory = exports.mockChromeInIframe = exports.mockChrome = exports.emulateConsoleDebug = exports.addPlugins = exports.emulateWindowFrame = exports.emulateWebGL = exports.addLanguage = exports.hackPermissions = void 0;
|
|
4
|
+
const hackPermissions = () => {
|
|
5
|
+
const originalQuery = window.navigator.permissions.query;
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
window.navigator.permissions.__proto__.query = parameters => parameters.name === 'notifications' // eslint-disable-line
|
|
8
|
+
? Promise.resolve({ state: Notification.permission }) //eslint-disable-line
|
|
9
|
+
: originalQuery(parameters);
|
|
10
|
+
// Inspired by: https://github.com/ikarienator/phantomjs_hide_and_seek/blob/master/5.spoofFunctionBind.js
|
|
11
|
+
const oldCall = Function.prototype.call;
|
|
12
|
+
function call() {
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
return oldCall.apply(this, arguments); //eslint-disable-line
|
|
15
|
+
}
|
|
16
|
+
// eslint-disable-next-line
|
|
17
|
+
Function.prototype.call = call;
|
|
18
|
+
const nativeToStringFunctionString = Error.toString().replace(/Error/g, 'toString');
|
|
19
|
+
const oldToString = Function.prototype.toString;
|
|
20
|
+
function functionToString() {
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
if (this === window.navigator.permissions.query) {
|
|
23
|
+
return 'function query() { [native code] }';
|
|
24
|
+
}
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
if (this === functionToString) {
|
|
27
|
+
return nativeToStringFunctionString;
|
|
28
|
+
}
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
return oldCall.call(oldToString, this);
|
|
31
|
+
}
|
|
32
|
+
// eslint-disable-next-line
|
|
33
|
+
Function.prototype.toString = functionToString;
|
|
34
|
+
};
|
|
35
|
+
exports.hackPermissions = hackPermissions;
|
|
36
|
+
const addLanguage = () => {
|
|
37
|
+
Object.defineProperty(Object.getPrototypeOf(navigator), 'languages', {
|
|
38
|
+
get: () => ['en-US', 'en'],
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
exports.addLanguage = addLanguage;
|
|
42
|
+
const emulateWebGL = () => {
|
|
43
|
+
try {
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
const getParameterOld = WebGLRenderingContext.getParameter;
|
|
46
|
+
WebGLRenderingContext.prototype.getParameter = function (parameter) {
|
|
47
|
+
// UNMASKED_VENDOR_WEBGL
|
|
48
|
+
if (parameter === 37445) {
|
|
49
|
+
return 'Intel Inc.';
|
|
50
|
+
}
|
|
51
|
+
// UNMASKED_RENDERER_WEBGL
|
|
52
|
+
if (parameter === 37446) {
|
|
53
|
+
return 'Intel(R) Iris(TM) Plus Graphics 640';
|
|
54
|
+
}
|
|
55
|
+
return getParameterOld(parameter);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
// eslint-disable-next-line no-console
|
|
60
|
+
console.error('hiding_tricks: Could not emulate WebGL');
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.emulateWebGL = emulateWebGL;
|
|
64
|
+
const emulateWindowFrame = () => {
|
|
65
|
+
if (window.outerWidth && window.outerHeight) {
|
|
66
|
+
return; // nothing to do here
|
|
67
|
+
}
|
|
68
|
+
const windowFrame = 85; // probably OS and WM dependent
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
window.outerWidth = window.innerWidth;
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
window.outerHeight = window.innerHeight + windowFrame;
|
|
73
|
+
};
|
|
74
|
+
exports.emulateWindowFrame = emulateWindowFrame;
|
|
75
|
+
const addPlugins = () => {
|
|
76
|
+
function mockPluginsAndMimeTypes() {
|
|
77
|
+
// Disguise custom functions as being native
|
|
78
|
+
const makeFnsNative = (fns = []) => {
|
|
79
|
+
const oldCall = Function.prototype.call;
|
|
80
|
+
function call() {
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
return oldCall.apply(this, arguments); // eslint-disable-line
|
|
83
|
+
}
|
|
84
|
+
// eslint-disable-next-line
|
|
85
|
+
Function.prototype.call = call;
|
|
86
|
+
const nativeToStringFunctionString = Error.toString().replace(/Error/g, 'toString');
|
|
87
|
+
const oldToString = Function.prototype.toString;
|
|
88
|
+
function functionToString() {
|
|
89
|
+
for (const fn of fns) {
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
if (this === fn.ref) {
|
|
92
|
+
return `function ${fn.name}() { [native code] }`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
if (this === functionToString) {
|
|
97
|
+
return nativeToStringFunctionString;
|
|
98
|
+
}
|
|
99
|
+
// @ts-ignore
|
|
100
|
+
return oldCall.call(oldToString, this);
|
|
101
|
+
}
|
|
102
|
+
// eslint-disable-next-line
|
|
103
|
+
Function.prototype.toString = functionToString;
|
|
104
|
+
};
|
|
105
|
+
const mockedFns = [];
|
|
106
|
+
const fakeData = {
|
|
107
|
+
mimeTypes: [
|
|
108
|
+
{
|
|
109
|
+
type: 'application/pdf',
|
|
110
|
+
suffixes: 'pdf',
|
|
111
|
+
description: '',
|
|
112
|
+
__pluginName: 'Chrome PDF Viewer',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
type: 'application/x-google-chrome-pdf',
|
|
116
|
+
suffixes: 'pdf',
|
|
117
|
+
description: 'Portable Document Format',
|
|
118
|
+
__pluginName: 'Chrome PDF Plugin',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'application/x-nacl',
|
|
122
|
+
suffixes: '',
|
|
123
|
+
description: 'Native Client Executable',
|
|
124
|
+
enabledPlugin: window.Plugin,
|
|
125
|
+
__pluginName: 'Native Client',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: 'application/x-pnacl',
|
|
129
|
+
suffixes: '',
|
|
130
|
+
description: 'Portable Native Client Executable',
|
|
131
|
+
__pluginName: 'Native Client',
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
plugins: [
|
|
135
|
+
{
|
|
136
|
+
name: 'Chrome PDF Plugin',
|
|
137
|
+
filename: 'internal-pdf-viewer',
|
|
138
|
+
description: 'Portable Document Format',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'Chrome PDF Viewer',
|
|
142
|
+
filename: 'mhjfbmdgcfjbbpaeojofohoefgiehjai',
|
|
143
|
+
description: '',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: 'Native Client',
|
|
147
|
+
filename: 'internal-nacl-plugin',
|
|
148
|
+
description: '',
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
fns: {
|
|
152
|
+
namedItem: (instanceName) => {
|
|
153
|
+
// Returns the Plugin/MimeType with the specified name.
|
|
154
|
+
const fn = function (name) {
|
|
155
|
+
if (!arguments.length) {
|
|
156
|
+
throw new TypeError(`Failed to execute 'namedItem' on '${instanceName}': 1 argument required, but only 0 present.`);
|
|
157
|
+
}
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
return this[name] || null;
|
|
160
|
+
};
|
|
161
|
+
mockedFns.push({ ref: fn, name: 'namedItem' });
|
|
162
|
+
return fn;
|
|
163
|
+
},
|
|
164
|
+
item: (instanceName) => {
|
|
165
|
+
// Returns the Plugin/MimeType at the specified index into the array.
|
|
166
|
+
const fn = function (index) {
|
|
167
|
+
if (!arguments.length) {
|
|
168
|
+
throw new TypeError(`Failed to execute 'namedItem' on '${instanceName}': 1 argument required, but only 0 present.`);
|
|
169
|
+
}
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
return this[index] || null;
|
|
172
|
+
};
|
|
173
|
+
mockedFns.push({ ref: fn, name: 'item' });
|
|
174
|
+
return fn;
|
|
175
|
+
},
|
|
176
|
+
refresh: () => {
|
|
177
|
+
// Refreshes all plugins on the current page, optionally reloading documents.
|
|
178
|
+
const fn = function () {
|
|
179
|
+
return undefined;
|
|
180
|
+
};
|
|
181
|
+
mockedFns.push({ ref: fn, name: 'refresh' });
|
|
182
|
+
return fn;
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
// Poor mans _.pluck
|
|
187
|
+
const getSubset = (keys, obj) => keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});
|
|
188
|
+
function generateMimeTypeArray() {
|
|
189
|
+
const arr = fakeData.mimeTypes
|
|
190
|
+
.map((obj) => getSubset(['type', 'suffixes', 'description'], obj))
|
|
191
|
+
.map((obj) => Object.setPrototypeOf(obj, MimeType.prototype));
|
|
192
|
+
arr.forEach((obj) => {
|
|
193
|
+
arr[obj.type] = obj;
|
|
194
|
+
});
|
|
195
|
+
// Mock functions
|
|
196
|
+
const arr2 = arr;
|
|
197
|
+
arr2.namedItem = fakeData.fns.namedItem('MimeTypeArray');
|
|
198
|
+
arr2.item = fakeData.fns.item('MimeTypeArray');
|
|
199
|
+
return Object.setPrototypeOf(arr, MimeTypeArray.prototype);
|
|
200
|
+
}
|
|
201
|
+
const mimeTypeArray = generateMimeTypeArray();
|
|
202
|
+
Object.defineProperty(window.navigator, 'mimeTypes', {
|
|
203
|
+
get: () => mimeTypeArray,
|
|
204
|
+
});
|
|
205
|
+
function generatePluginArray() {
|
|
206
|
+
const arr = fakeData.plugins
|
|
207
|
+
.map((obj) => getSubset(['name', 'filename', 'description'], obj))
|
|
208
|
+
.map((obj) => {
|
|
209
|
+
const mimes = fakeData.mimeTypes.filter(m => m.__pluginName === obj.name);
|
|
210
|
+
// Add mimetypes
|
|
211
|
+
mimes.forEach((mime, index) => {
|
|
212
|
+
// @ts-expect-error mimeTypes can be indexed by number and string too
|
|
213
|
+
window.navigator.mimeTypes[mime.type].enabledPlugin = obj;
|
|
214
|
+
// @ts-expect-error mimeTypes can be indexed by number and string too
|
|
215
|
+
obj[mime.type] = window.navigator.mimeTypes[mime.type];
|
|
216
|
+
// @ts-expect-error mimeTypes can be indexed by number and string too
|
|
217
|
+
obj[index] = window.navigator.mimeTypes[mime.type];
|
|
218
|
+
});
|
|
219
|
+
return {
|
|
220
|
+
...obj,
|
|
221
|
+
length: mimes.length,
|
|
222
|
+
};
|
|
223
|
+
})
|
|
224
|
+
.map((obj) => {
|
|
225
|
+
// Mock functions
|
|
226
|
+
return {
|
|
227
|
+
...obj,
|
|
228
|
+
namedItem: fakeData.fns.namedItem('Plugin'),
|
|
229
|
+
item: fakeData.fns.item('Plugin'),
|
|
230
|
+
};
|
|
231
|
+
})
|
|
232
|
+
.map((obj) => Object.setPrototypeOf(obj, window.Plugin.prototype));
|
|
233
|
+
arr.forEach((obj) => {
|
|
234
|
+
arr[obj.name] = obj;
|
|
235
|
+
});
|
|
236
|
+
// Mock functions
|
|
237
|
+
const arr2 = arr;
|
|
238
|
+
arr2.namedItem = fakeData.fns.namedItem('PluginArray');
|
|
239
|
+
arr2.item = fakeData.fns.item('PluginArray');
|
|
240
|
+
arr2.refresh = fakeData.fns.refresh();
|
|
241
|
+
return Object.setPrototypeOf(arr, PluginArray.prototype);
|
|
242
|
+
}
|
|
243
|
+
const pluginArray = generatePluginArray();
|
|
244
|
+
Object.defineProperty(window.navigator, 'plugins', {
|
|
245
|
+
get: () => pluginArray,
|
|
246
|
+
});
|
|
247
|
+
// Make mockedFns toString() representation resemble a native function
|
|
248
|
+
makeFnsNative(mockedFns);
|
|
249
|
+
}
|
|
250
|
+
const isPluginArray = window.navigator.plugins instanceof PluginArray;
|
|
251
|
+
const hasPlugins = isPluginArray && window.navigator.plugins.length > 0;
|
|
252
|
+
if (isPluginArray && hasPlugins) {
|
|
253
|
+
return; // nothing to do here
|
|
254
|
+
}
|
|
255
|
+
mockPluginsAndMimeTypes();
|
|
256
|
+
};
|
|
257
|
+
exports.addPlugins = addPlugins;
|
|
258
|
+
const emulateConsoleDebug = () => {
|
|
259
|
+
window.console.debug = () => {
|
|
260
|
+
return null;
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
exports.emulateConsoleDebug = emulateConsoleDebug;
|
|
264
|
+
// Should be mocked more properly - this one will bypass only some stupid tests
|
|
265
|
+
const mockChrome = () => {
|
|
266
|
+
// @ts-ignore
|
|
267
|
+
if (!window.chrome) {
|
|
268
|
+
Object.defineProperty(window, 'chrome', {
|
|
269
|
+
value: {
|
|
270
|
+
runtime: {},
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
exports.mockChrome = mockChrome;
|
|
276
|
+
// not sure if this hack does not broke iframe on websites... Should figure out how to test properly
|
|
277
|
+
// Should cover that it is custom function same as the permission query
|
|
278
|
+
const mockChromeInIframe = () => {
|
|
279
|
+
const oldCreate = document.createElement.bind(document);
|
|
280
|
+
const newCreate = (...args) => {
|
|
281
|
+
if (args[0] === 'iframe') {
|
|
282
|
+
const iframe = oldCreate(...args);
|
|
283
|
+
if (!iframe.contentWindow) {
|
|
284
|
+
Object.defineProperty(iframe, 'contentWindow', {
|
|
285
|
+
configurable: true,
|
|
286
|
+
value: { chrome: {} },
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// @ts-expect-error
|
|
290
|
+
if (!iframe.contentWindow?.chrome) {
|
|
291
|
+
Object.defineProperty(iframe.contentWindow, 'chrome', {
|
|
292
|
+
value: {},
|
|
293
|
+
configurable: true,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
return iframe;
|
|
297
|
+
}
|
|
298
|
+
return oldCreate(...args);
|
|
299
|
+
};
|
|
300
|
+
newCreate.toString = () => 'function createElement() { [native code] }';
|
|
301
|
+
document.createElement = newCreate;
|
|
302
|
+
const oldCall = Function.prototype.call;
|
|
303
|
+
function call() {
|
|
304
|
+
// @ts-ignore
|
|
305
|
+
return oldCall.apply(this, arguments); //eslint-disable-line
|
|
306
|
+
}
|
|
307
|
+
// eslint-disable-next-line
|
|
308
|
+
Function.prototype.call = call;
|
|
309
|
+
const nativeToStringFunctionString = Error.toString().replace(/Error/g, 'toString');
|
|
310
|
+
const oldToString = Function.prototype.toString;
|
|
311
|
+
function functionToString() {
|
|
312
|
+
// @ts-ignore
|
|
313
|
+
if (this === window.document.createElement) {
|
|
314
|
+
return 'function createElement() { [native code] }';
|
|
315
|
+
}
|
|
316
|
+
// @ts-ignore
|
|
317
|
+
if (this === functionToString) {
|
|
318
|
+
return nativeToStringFunctionString;
|
|
319
|
+
}
|
|
320
|
+
// @ts-ignore
|
|
321
|
+
return oldCall.call(oldToString, this);
|
|
322
|
+
}
|
|
323
|
+
// eslint-disable-next-line
|
|
324
|
+
Function.prototype.toString = functionToString;
|
|
325
|
+
};
|
|
326
|
+
exports.mockChromeInIframe = mockChromeInIframe;
|
|
327
|
+
const mockDeviceMemory = () => {
|
|
328
|
+
// TODO: Count from env according to - https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory
|
|
329
|
+
Object.defineProperty(navigator, 'deviceMemory', {
|
|
330
|
+
value: 8,
|
|
331
|
+
});
|
|
332
|
+
};
|
|
333
|
+
exports.mockDeviceMemory = mockDeviceMemory;
|
|
334
|
+
//# sourceMappingURL=hiding_tricks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hiding_tricks.js","sourceRoot":"","sources":["../../../src/internals/stealth/hiding_tricks.ts"],"names":[],"mappings":"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"}
|