Skip to content

Commit

Permalink
feat: mv renderingOptions => blockedResourceTypes
Browse files Browse the repository at this point in the history
BREAKING CHANGE: renames “renderingOptions” to “blockedResourceTypes”. Default is now “None”

fix for issue #113
  • Loading branch information
blakebyrnes committed Dec 30, 2020
1 parent ae96ced commit ffa1b74
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 49 deletions.
4 changes: 2 additions & 2 deletions client/interfaces/IAgentDefaults.ts
@@ -1,7 +1,7 @@
import { IRenderingOption } from '@secret-agent/core-interfaces/ITabOptions';
import { IBlockedResourceType } from '@secret-agent/core-interfaces/ITabOptions';
import IUserProfile from '@secret-agent/core-interfaces/IUserProfile';

export default interface IAgentDefaults {
defaultRenderingOptions?: IRenderingOption[];
defaultBlockedResourceTypes?: IBlockedResourceType[];
defaultUserProfile?: IUserProfile;
}
7 changes: 4 additions & 3 deletions client/lib/Agent.ts
@@ -1,5 +1,5 @@
// eslint-disable-next-line max-classes-per-file
import { RenderingOption } from '@secret-agent/core-interfaces/ITabOptions';
import { BlockedResourceType } from '@secret-agent/core-interfaces/ITabOptions';
import StateMachine from 'awaited-dom/base/StateMachine';
import initializeConstantsAndProperties from 'awaited-dom/base/initializeConstantsAndProperties';
import { bindFunctions } from '@secret-agent/commons/utils';
Expand Down Expand Up @@ -33,7 +33,7 @@ import createConnection from '../connections/createConnection';
import IAgentConfigureOptions from '../interfaces/IAgentConfigureOptions';

export const DefaultOptions = {
defaultRenderingOptions: [RenderingOption.All],
defaultBlockedResourceTypes: [BlockedResourceType.None],
defaultUserProfile: {},
};
const scriptInstance = new ScriptInstance();
Expand Down Expand Up @@ -71,7 +71,8 @@ export default class Agent extends AwaitedEventTarget<{ close: void }> {
initializeConstantsAndProperties(this, [], propertyKeys);
bindFunctions(this);

options.renderingOptions = options.renderingOptions || Agent.options.defaultRenderingOptions;
options.blockedResourceTypes =
options.blockedResourceTypes || Agent.options.defaultBlockedResourceTypes;
options.userProfile = options.userProfile || Agent.options.defaultUserProfile;

const sessionName = scriptInstance.generateSessionName(options.name);
Expand Down
7 changes: 6 additions & 1 deletion core-interfaces/IConfigureSessionOptions.ts
Expand Up @@ -3,5 +3,10 @@ import ICreateSessionOptions from './ICreateSessionOptions';
export default interface IConfigureSessionOptions
extends Pick<
ICreateSessionOptions,
'userProfile' | 'viewport' | 'timezoneId' | 'locale' | 'upstreamProxyUrl' | 'renderingOptions'
| 'userProfile'
| 'viewport'
| 'timezoneId'
| 'locale'
| 'upstreamProxyUrl'
| 'blockedResourceTypes'
> {}
15 changes: 7 additions & 8 deletions core-interfaces/ITabOptions.ts
@@ -1,16 +1,15 @@
export default interface ITabOptions {
renderingOptions?: IRenderingOption[];
blockedResourceTypes?: IBlockedResourceType[];
}

export enum RenderingOption {
AwaitedDOM = 'AwaitedDOM',
export enum BlockedResourceType {
JsRuntime = 'JsRuntime',
LoadJsResources = 'LoadJsResources',
LoadCssResources = 'LoadCssResources',
LoadImages = 'LoadImages',
LoadResources = 'LoadResources',
BlockJsResources = 'BlockJsResources',
BlockCssResources = 'BlockCssResources',
BlockImages = 'BlockImages',
BlockAssets = 'BlockAssets',
All = 'All',
None = 'None',
}

export type IRenderingOption = keyof typeof RenderingOption;
export type IBlockedResourceType = keyof typeof BlockedResourceType;
11 changes: 7 additions & 4 deletions core/lib/Session.ts
Expand Up @@ -88,15 +88,18 @@ export default class Session extends TypedEventEmitter<{
log.warn('BrowserEmulators.PolyfillNotSupported', {
sessionId: this.id,
browserEmulatorId: this.browserEmulatorId,
userAgentString: this.browserEmulator.userAgentString,
userAgentString: this.browserEmulator.userAgentString,
runtimeOs: Os.platform(),
});
}

this.timezoneId = options.timezoneId;
this.viewport = options.viewport;
if (!this.viewport) {
this.viewport = Viewports.getDefault(this.browserEmulator.windowFraming, this.browserEmulator.windowFramingBase);
this.viewport = Viewports.getDefault(
this.browserEmulator.windowFraming,
this.browserEmulator.windowFramingBase,
);
}

this.humanEmulatorId = options.humanEmulatorId || HumanEmulators.getRandomId();
Expand Down Expand Up @@ -131,8 +134,8 @@ export default class Session extends TypedEventEmitter<{
this.upstreamProxyUrl = options.upstreamProxyUrl;
this.mitmRequestSession.upstreamProxyUrl = options.upstreamProxyUrl;
}
if (options.renderingOptions !== undefined) {
for (const tab of this.tabs) await tab.setRenderingOptions(options.renderingOptions);
if (options.blockedResourceTypes !== undefined) {
for (const tab of this.tabs) await tab.setBlockedResourceTypes(options.blockedResourceTypes);
}
if (options.viewport !== undefined) this.viewport = options.viewport;
if (options.userProfile !== undefined) {
Expand Down
24 changes: 14 additions & 10 deletions core/lib/Tab.ts
@@ -1,6 +1,6 @@
import { v1 as uuidv1 } from 'uuid';
import Log from '@secret-agent/commons/Logger';
import { IRenderingOption } from '@secret-agent/core-interfaces/ITabOptions';
import { IBlockedResourceType } from '@secret-agent/core-interfaces/ITabOptions';
import {
ILocationStatus,
ILocationTrigger,
Expand Down Expand Up @@ -143,27 +143,31 @@ export default class Tab extends TypedEventEmitter<ITabEventParams> {
]);
}

public async setRenderingOptions(renderingOptions: IRenderingOption[]): Promise<void> {
public async setBlockedResourceTypes(
blockedResourceTypes: IBlockedResourceType[],
): Promise<void> {
const mitmSession = this.session.mitmRequestSession;
const blockedResources = mitmSession.blockedResources.types;
let enableJs = true;

if (renderingOptions.includes('All')) {
if (blockedResourceTypes.includes('None')) {
blockedResources.length = 0;
} else if (renderingOptions.includes('None')) {
} else if (blockedResourceTypes.includes('All')) {
blockedResources.push('Image', 'Stylesheet', 'Script', 'Font', 'Ico', 'Media');
enableJs = false;
} else if (blockedResourceTypes.includes('BlockAssets')) {
blockedResources.push('Image', 'Stylesheet', 'Script');
} else {
if (!renderingOptions.includes('LoadImages')) {
if (blockedResourceTypes.includes('BlockImages')) {
blockedResources.push('Image');
}
if (!renderingOptions.includes('LoadCssResources')) {
if (blockedResourceTypes.includes('BlockCssResources')) {
blockedResources.push('Stylesheet');
}
if (!renderingOptions.includes('LoadJsResources')) {
if (blockedResourceTypes.includes('BlockJsResources')) {
blockedResources.push('Script');
}
if (!renderingOptions.includes('JsRuntime')) {
if (blockedResourceTypes.includes('JsRuntime')) {
enableJs = false;
}
}
Expand Down Expand Up @@ -513,8 +517,8 @@ export default class Tab extends TypedEventEmitter<ITabEventParams> {
}

await this.interactor.initialize();
if (this.session.options?.renderingOptions) {
await this.setRenderingOptions(this.session.options.renderingOptions);
if (this.session.options?.blockedResourceTypes) {
await this.setBlockedResourceTypes(this.session.options.blockedResourceTypes);
}
}

Expand Down
3 changes: 2 additions & 1 deletion emulate-browsers/base/lib/DomDiffLoader.ts
Expand Up @@ -30,7 +30,8 @@ function extractFilename(filenames: string[]) {
for (const filename of filenames) {
const matches = filename.match(/^dom-diffs-when-using-([a-z-]+)(-([0-9-]+))?.json$/);
if (!matches) continue;
const [osName, _, osVersion] = matches.slice(1); // eslint-disable-line @typescript-eslint/naming-convention

const [osName, _, osVersion] = matches.slice(1); // eslint-disable-line @typescript-eslint/naming-convention,@typescript-eslint/no-unused-vars
filenameMap[osName] = filenameMap[osName] || {};
filenameMap[osName][osVersion || 'ALL'] = filename;
}
Expand Down
37 changes: 37 additions & 0 deletions full-client/test/basic.test.ts
@@ -1,4 +1,5 @@
import { Helpers } from '@secret-agent/testing';
import Resource from '@secret-agent/client/lib/Resource';
import { Handler } from '../index';

let koaServer;
Expand All @@ -22,6 +23,42 @@ describe('basic Full Client tests', () => {
expect(url).toBe(koaServer.baseHost);
});

it('allows you to block resources', async () => {
koaServer.get('/block', ctx => {
ctx.body = `<html>
<head>
<link rel="stylesheet" href="/test.css" />
</head>
<body>
<img src="/img.png" alt="Image"/>
</body>
</html>`;
});

koaServer.get('/img.png', ctx => {
ctx.statusCode = 500;
});
koaServer.get('/test.css', ctx => {
ctx.statusCode = 500;
});

const agent = await handler.createAgent({
blockedResourceTypes: ['BlockAssets'],
});
Helpers.needsClosing.push(agent);

const resources: Resource[] = [];
await agent.activeTab.on('resource', event => resources.push(event));
await agent.goto(`${koaServer.baseUrl}/block`);
await agent.waitForAllContentLoaded();
expect(resources).toHaveLength(3);
for (const resource of resources) {
const status = await resource.response.statusCode;
if (resource.type === 'Document') expect(status).toBe(200);
else expect(status).toBe(404);
}
});

it('should get unreachable proxy errors in the client', async () => {
const agent = await handler.createAgent({
upstreamProxyUrl: koaServer.baseUrl,
Expand Down
1 change: 0 additions & 1 deletion puppet-chrome/lib/BrowserContext.ts
Expand Up @@ -17,7 +17,6 @@ import IRegisteredEventListener from '@secret-agent/core-interfaces/IRegisteredE
import { Page } from './Page';
import { Browser } from './Browser';
import { CDPSession } from './CDPSession';
import { Worker } from './Worker';
import Frame from './Frame';
import CookieParam = Protocol.Network.CookieParam;
import TargetInfo = Protocol.Target.TargetInfo;
Expand Down
4 changes: 2 additions & 2 deletions website/docs/BasicInterfaces/Agent.md
Expand Up @@ -59,7 +59,7 @@ const { Agent } = require('secret-agent');
- timezoneId `string`. Overrides the host timezone. A list of valid ids are available at [unicode.org](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/zone_tzid.html)
- locale `string`. Overrides the host languages settings (eg, en-US). Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting rules.
- viewport `IViewport`. Sets the emulated screen size, window position in the screen, inner/outer width and height. If not provided, the most popular resolution is used from [statcounter.com](https://gs.statcounter.com/screen-resolution-stats/desktop/united-states-of-america).
- renderingOptions `string[]`. Controls browser functionality.
- blockedResourceTypes `string[]`. Controls browser resource loading.
- userProfile `IUserProfile`. Previous user's cookies, session, etc.
- showReplay `boolean`. Whether or not to show the Replay UI. Can also be set with an env variable: `SA_SHOW_REPLAY=true`.
- upstreamProxyUrl `string`. A socks5 or http proxy url (and optional auth) to use for all HTTP requests in this session. Dns over Tls requests will also use this proxy, if provided. The optional "auth" should be included in the UserInfo section of the url, eg: `http://username:password@proxy.com:80`.
Expand Down Expand Up @@ -165,7 +165,7 @@ Update existing configuration settings.
- timezoneId `string`. Overrides the host timezone. A list of valid ids are available at [unicode.org](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/zone_tzid.html)
- locale `string`. Overrides the host languages settings (eg, en-US). Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting rules.
- viewport `IViewport`. Sets the emulated screen size, window position in the screen, inner/outer width.
- renderingOptions `string[]`. Controls enabled browser rendering features.
- blockedResourceTypes `string[]`. Controls browser resource loading.
- upstreamProxyUrl `string`. A socks5 or http proxy url (and optional auth) to use for all HTTP requests in this session. The optional "auth" should be included in the UserInfo section of the url, eg: `http://username:password@proxy.com:80`.
- coreConnection `options | CoreClientConnection`. An object containing `ICoreConnectionOptions` used to connect, or an already created `CoreClientConnection` instance. Defaults to automatically connecting to a local `Core`.

Expand Down
2 changes: 1 addition & 1 deletion website/docs/BasicInterfaces/Handler.md
Expand Up @@ -112,7 +112,7 @@ NOTE: when using this method, you must call [`agent.close()`](./agent#close) exp
- timezoneId `string`. Overrides the host timezone. A list of valid ids are available at [unicode.org](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/zone_tzid.html)
- locale `string`. Overrides the host languages settings (eg, en-US). Locale will affect navigator.language value, Accept-Language request header value as well as number and date formatting rules.
- viewport `IViewport`. Sets the emulated screen size, window position in the screen, inner/outer width and height. If not provided, the most popular resolution is used from [statcounter.com](https://gs.statcounter.com/screen-resolution-stats/desktop/united-states-of-america).
- renderingOptions `string[]`. Controls browser functionality.
- blockedResourceTypes `string[]`. Controls browser resource loading.
- userProfile `IUserProfile`. Previous user's cookies, session, etc.
- showReplay `boolean`. Whether or not to show the Replay UI. Can also be set with an env variable: `SA_SHOW_REPLAY=true`.
- upstreamProxyUrl `string`. A socks5 or http proxy url (and optional auth) to use for all HTTP requests in this session. The optional "auth" should be included in the UserInfo section of the url, eg: `http://username:password@proxy.com:80`.
Expand Down
4 changes: 2 additions & 2 deletions website/docs/Overview/BasicConcepts.md
Expand Up @@ -62,13 +62,13 @@ When used in a simple example as show above, Puppeteer's approach seems okay. Ho

## Headless Browsers Need Not Always Render

When you're trying to eke out performance, a common technique is to disable rendering various parts of a webpage. SecretAgent allows you to [turn off](./configuration#rendering) everything from the style and images of a page, to the javascript environment. You can even simulate making http requests from inside a loaded web page, without ever loading the page.
When you're trying to eke out performance, a common technique is to disable rendering various parts of a webpage. SecretAgent allows you to [turn off](./configuration#blocked-resources) everything from the style and images of a page, to the javascript environment. You can even simulate making http requests from inside a loaded web page, without ever loading the page.

```js
import agent from 'secret-agent';

await agent.configure({
renderingOptions: ['None'],
blockedResourceTypes: ['All'],
});
await agent.goto('https://secretagent.dev');
// referer will be https://secretagent.dev
Expand Down
27 changes: 13 additions & 14 deletions website/docs/Overview/Configuration.md
Expand Up @@ -12,7 +12,7 @@ The internal `@secret-agent/core` module can receive several configuration optio

The [CoreConnection](../advanced/core-connection) to be used by a [Handler](../basic-interfaces/handler) or [Agent](../basic-interfaces/agent).

All [configurations](../advanced/core-connection#configurations) accept both an `options` object and a [`CoreConnection`](../advanced/core-connection) instance.
All [configurations](../advanced/core-connection#configurations) accept both an `options` object and a [`CoreConnection`](../advanced/core-connection) instance.

Configuration is accepted in the following methods and constructors:

Expand Down Expand Up @@ -49,22 +49,21 @@ Configures the storage location for files created by Core.

Configurable via [`Core.start()`](#core-start) or the first [`CoreConnection`](../advanced/core-connection).

### Rendering Options <div class="specs"><i>Connection</i><i>Agent</i></div> {#rendering}
### Blocked Resource Types <div class="specs"><i>Connection</i><i>Agent</i></div> {#blocked-resources}

One of the best ways to optimize SecretAgent's memory and CPU is limiting the `renderingOptions` to only what you need. The following are valid options.
One of the best ways to optimize SecretAgent's memory and CPU is setting `blockedResourceTypes` to block resources you don't need. The following are valid options.

<p class="show-table-header show-bottom-border minimal-row-height"></p>

| Options | Description |
| --------------- | -------------------------------------------------------------- |
| `AwaitedDOM` | Uses Chromium to attach AwaitedDOM to window.document. |
| `JsRuntime` | Executes JS in webpage. Requires `AwaitedDOM`. |
| `LoadJsAssets` | Loads all referenced script assets. Requires `JsRuntime`. |
| `LoadCssAssets` | Loads all referenced CSS assets. Requires `JsRuntime`. |
| `LoadImages` | Loads all referenced images on page. Requires `JsRuntime`. |
| `LoadAssets` | Shortcut for `LoadJsAssets`, `LoadCssAssets` and `LoadImages`. |
| `All` | Activates all features listed above. |
| `None` | No AwaitedDOM or assets. Only retrieves window.response. |
| Options | Description |
| ---------------- | ------------------------------------------------------------------ |
| `JsRuntime` | Executes JS in webpage. Requires `AwaitedDOM`. |
| `BlockJsAssets` | Loads all referenced script assets. Requires `JsRuntime`. |
| `BlockCssAssets` | Loads all referenced CSS assets. Requires `JsRuntime`. |
| `BlockImages` | Loads all referenced images on page. Requires `JsRuntime`. |
| `BlockAssets` | Shortcut for `LoadJsAssets`, `LoadCssAssets` and `LoadImages`. |
| `All` | Blocks all of the resources above. Only retrieves window.response. |
| `None` | No assets are blocked. `default` |

As you'll notice above, some features are dependent on others and therefore automatically enable other features.

Expand Down Expand Up @@ -128,7 +127,7 @@ Update existing settings.
- maxConcurrentAgentsCount `number` defaults to `10`. Limit concurrent Agent sessions running at any given time.
- localProxyPortStart `number` defaults to `any open port`. Starting internal port to use for the mitm proxy.
- sessionsDir `string` defaults to `os.tmpdir()/.secret-agent`. Directory to store session files and mitm certificates.
- defaultRenderingOptions `string[]` defaults to `[All]`. Controls enabled browser rendering features.
- defaultBlockedResourceTypes `string[]` defaults to `[None]`. Controls enabled browser resources.
- defaultUserProfile `IUserProfile`. Define user cookies, session, and more.
- replayServerPort `number`. Port to start a live replay server on. Defaults to "any open port".

Expand Down

0 comments on commit ffa1b74

Please sign in to comment.