feat(rpc): disallow deps into rpc client from outside (#3199)
For this, common converters are extracted from rpc serializers.
This commit is contained in:
parent
3e023f6c3d
commit
6cb1e03713
|
|
@ -18,7 +18,7 @@
|
|||
"tsc-installer": "tsc -p ./src/install/tsconfig.json",
|
||||
"doc": "node utils/doclint/cli.js",
|
||||
"test-infra": "node utils/doclint/check_public_api/test/test.js && node utils/doclint/preprocessor/test.js && node utils/testrunner/test/test.js",
|
||||
"lint": "npm run eslint && npm run tsc && npm run doc && npm run test-types && npm run test-infra",
|
||||
"lint": "npm run eslint && npm run tsc && npm run doc && npm run check-deps && npm run test-types && npm run test-infra",
|
||||
"debug-test": "node --inspect-brk test/test.js",
|
||||
"clean": "rimraf lib && rimraf types",
|
||||
"prepare": "node install-from-github.js",
|
||||
|
|
|
|||
123
src/converters.ts
Normal file
123
src/converters.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as mime from 'mime';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as types from './types';
|
||||
import { helper, assert } from './helper';
|
||||
|
||||
export async function normalizeFilePayloads(files: string | types.FilePayload | string[] | types.FilePayload[]): Promise<types.FilePayload[]> {
|
||||
let ff: string[] | types.FilePayload[];
|
||||
if (!Array.isArray(files))
|
||||
ff = [ files ] as string[] | types.FilePayload[];
|
||||
else
|
||||
ff = files;
|
||||
const filePayloads: types.FilePayload[] = [];
|
||||
for (const item of ff) {
|
||||
if (typeof item === 'string') {
|
||||
const file: types.FilePayload = {
|
||||
name: path.basename(item),
|
||||
mimeType: mime.getType(item) || 'application/octet-stream',
|
||||
buffer: await util.promisify(fs.readFile)(item)
|
||||
};
|
||||
filePayloads.push(file);
|
||||
} else {
|
||||
filePayloads.push(item);
|
||||
}
|
||||
}
|
||||
return filePayloads;
|
||||
}
|
||||
|
||||
export async function normalizeFulfillParameters(params: types.FulfillResponse & { path?: string }): Promise<types.NormalizedFulfillResponse> {
|
||||
let body = '';
|
||||
let isBase64 = false;
|
||||
let length = 0;
|
||||
if (params.path) {
|
||||
const buffer = await util.promisify(fs.readFile)(params.path);
|
||||
body = buffer.toString('base64');
|
||||
isBase64 = true;
|
||||
length = buffer.length;
|
||||
} else if (helper.isString(params.body)) {
|
||||
body = params.body;
|
||||
isBase64 = false;
|
||||
length = Buffer.byteLength(body);
|
||||
} else if (params.body) {
|
||||
body = params.body.toString('base64');
|
||||
isBase64 = true;
|
||||
length = params.body.length;
|
||||
}
|
||||
const headers: types.Headers = {};
|
||||
for (const header of Object.keys(params.headers || {}))
|
||||
headers[header.toLowerCase()] = String(params.headers![header]);
|
||||
if (params.contentType)
|
||||
headers['content-type'] = String(params.contentType);
|
||||
else if (params.path)
|
||||
headers['content-type'] = mime.getType(params.path) || 'application/octet-stream';
|
||||
if (length && !('content-length' in headers))
|
||||
headers['content-length'] = String(length);
|
||||
|
||||
return {
|
||||
status: params.status || 200,
|
||||
headers: headersObjectToArray(headers),
|
||||
body,
|
||||
isBase64
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeContinueOverrides(overrides: types.ContinueOverrides): types.NormalizedContinueOverrides {
|
||||
return {
|
||||
method: overrides.method,
|
||||
headers: overrides.headers ? headersObjectToArray(overrides.headers) : undefined,
|
||||
postData: helper.isString(overrides.postData) ? Buffer.from(overrides.postData, 'utf8') : overrides.postData,
|
||||
};
|
||||
}
|
||||
|
||||
export function headersObjectToArray(headers: types.Headers): types.HeadersArray {
|
||||
const result: types.HeadersArray = [];
|
||||
for (const name in headers) {
|
||||
if (!Object.is(headers[name], undefined)) {
|
||||
const value = headers[name];
|
||||
assert(helper.isString(value), `Expected value of header "${name}" to be String, but "${typeof value}" is found.`);
|
||||
result.push({ name, value });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function headersArrayToObject(headers: types.HeadersArray): types.Headers {
|
||||
const result: types.Headers = {};
|
||||
for (const { name, value } of headers)
|
||||
result[name] = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function envObjectToArray(env: types.Env): types.EnvArray {
|
||||
const result: types.EnvArray = [];
|
||||
for (const name in env) {
|
||||
if (!Object.is(env[name], undefined))
|
||||
result.push({ name, value: String(env[name]) });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function envArrayToObject(env: types.EnvArray): types.Env {
|
||||
const result: types.Env = {};
|
||||
for (const { name, value } of env)
|
||||
result[name] = value;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ import * as types from './types';
|
|||
import { Progress } from './progress';
|
||||
import DebugScript from './debug/injected/debugScript';
|
||||
import { FatalDOMError, RetargetableDOMError } from './common/domErrors';
|
||||
import { normalizeFilePayloads } from './rpc/serializers';
|
||||
import { normalizeFilePayloads } from './converters';
|
||||
|
||||
export class FrameExecutionContext extends js.ExecutionContext {
|
||||
readonly frame: frames.Frame;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import * as frames from './frames';
|
|||
import * as types from './types';
|
||||
import { assert, helper } from './helper';
|
||||
import { URLSearchParams } from 'url';
|
||||
import { normalizeFulfillParameters, normalizeContinueOverrides } from './rpc/serializers';
|
||||
import { normalizeFulfillParameters, normalizeContinueOverrides } from './converters';
|
||||
|
||||
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
|
||||
const parsedURLs = urls.map(s => new URL(s));
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import { ChannelOwner } from './channelOwner';
|
|||
import { Events } from '../../events';
|
||||
import { LoggerSink } from '../../loggerSink';
|
||||
import { BrowserType } from './browserType';
|
||||
import { headersObjectToArray } from '../serializers';
|
||||
import { headersObjectToArray } from '../../converters';
|
||||
|
||||
export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
|
||||
readonly _contexts = new Set<BrowserContext>();
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { Browser } from './browser';
|
|||
import { Events } from '../../events';
|
||||
import { TimeoutSettings } from '../../timeoutSettings';
|
||||
import { Waiter } from './waiter';
|
||||
import { headersObjectToArray } from '../serializers';
|
||||
import { headersObjectToArray } from '../../converters';
|
||||
|
||||
export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserContextInitializer> {
|
||||
_pages = new Set<Page>();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { BrowserContext } from './browserContext';
|
|||
import { ChannelOwner } from './channelOwner';
|
||||
import { BrowserServer } from './browserServer';
|
||||
import { LoggerSink } from '../../loggerSink';
|
||||
import { headersObjectToArray, envObjectToArray } from '../serializers';
|
||||
import { headersObjectToArray, envObjectToArray } from '../../converters';
|
||||
import { serializeArgument } from './jsHandle';
|
||||
import { assert } from '../../helper';
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import { TimeoutSettings } from '../../timeoutSettings';
|
|||
import { Waiter } from './waiter';
|
||||
import { Events } from '../../events';
|
||||
import { LoggerSink } from '../../loggerSink';
|
||||
import { envObjectToArray } from '../serializers';
|
||||
import { envObjectToArray } from '../../converters';
|
||||
|
||||
export class Electron extends ChannelOwner<ElectronChannel, ElectronInitializer> {
|
||||
static from(electron: ElectronChannel): Electron {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { Frame } from './frame';
|
|||
import { FuncOn, JSHandle, serializeArgument, parseResult } from './jsHandle';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { helper, assert } from '../../helper';
|
||||
import { normalizeFilePayloads } from '../serializers';
|
||||
import { normalizeFilePayloads } from '../../converters';
|
||||
|
||||
export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
||||
readonly _elementChannel: ElementHandleChannel;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import * as types from '../../types';
|
|||
import { RequestChannel, ResponseChannel, RouteChannel, RequestInitializer, ResponseInitializer, RouteInitializer } from '../channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Frame } from './frame';
|
||||
import { normalizeFulfillParameters, headersArrayToObject, normalizeContinueOverrides } from '../serializers';
|
||||
import { normalizeFulfillParameters, headersArrayToObject, normalizeContinueOverrides } from '../../converters';
|
||||
|
||||
export type NetworkCookie = {
|
||||
name: string,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ import { assert, assertMaxArguments, helper, Listener } from '../../helper';
|
|||
import { TimeoutSettings } from '../../timeoutSettings';
|
||||
import * as types from '../../types';
|
||||
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer, PagePdfParams } from '../channels';
|
||||
import { parseError, headersObjectToArray, serializeError } from '../serializers';
|
||||
import { parseError, serializeError } from '../serializers';
|
||||
import { headersObjectToArray } from '../../converters';
|
||||
import { Accessibility } from './accessibility';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
|
|
|
|||
|
|
@ -14,13 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as mime from 'mime';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import { TimeoutError } from '../errors';
|
||||
import * as types from '../types';
|
||||
import { helper, assert } from '../helper';
|
||||
import { helper } from '../helper';
|
||||
import { SerializedError, AXNode, SerializedValue } from './channels';
|
||||
|
||||
export function serializeError(e: any): SerializedError {
|
||||
|
|
@ -45,107 +41,6 @@ export function parseError(error: SerializedError): Error {
|
|||
return e;
|
||||
}
|
||||
|
||||
export async function normalizeFilePayloads(files: string | types.FilePayload | string[] | types.FilePayload[]): Promise<types.FilePayload[]> {
|
||||
let ff: string[] | types.FilePayload[];
|
||||
if (!Array.isArray(files))
|
||||
ff = [ files ] as string[] | types.FilePayload[];
|
||||
else
|
||||
ff = files;
|
||||
const filePayloads: types.FilePayload[] = [];
|
||||
for (const item of ff) {
|
||||
if (typeof item === 'string') {
|
||||
const file: types.FilePayload = {
|
||||
name: path.basename(item),
|
||||
mimeType: mime.getType(item) || 'application/octet-stream',
|
||||
buffer: await util.promisify(fs.readFile)(item)
|
||||
};
|
||||
filePayloads.push(file);
|
||||
} else {
|
||||
filePayloads.push(item);
|
||||
}
|
||||
}
|
||||
return filePayloads;
|
||||
}
|
||||
|
||||
export async function normalizeFulfillParameters(params: types.FulfillResponse & { path?: string }): Promise<types.NormalizedFulfillResponse> {
|
||||
let body = '';
|
||||
let isBase64 = false;
|
||||
let length = 0;
|
||||
if (params.path) {
|
||||
const buffer = await util.promisify(fs.readFile)(params.path);
|
||||
body = buffer.toString('base64');
|
||||
isBase64 = true;
|
||||
length = buffer.length;
|
||||
} else if (helper.isString(params.body)) {
|
||||
body = params.body;
|
||||
isBase64 = false;
|
||||
length = Buffer.byteLength(body);
|
||||
} else if (params.body) {
|
||||
body = params.body.toString('base64');
|
||||
isBase64 = true;
|
||||
length = params.body.length;
|
||||
}
|
||||
const headers: types.Headers = {};
|
||||
for (const header of Object.keys(params.headers || {}))
|
||||
headers[header.toLowerCase()] = String(params.headers![header]);
|
||||
if (params.contentType)
|
||||
headers['content-type'] = String(params.contentType);
|
||||
else if (params.path)
|
||||
headers['content-type'] = mime.getType(params.path) || 'application/octet-stream';
|
||||
if (length && !('content-length' in headers))
|
||||
headers['content-length'] = String(length);
|
||||
|
||||
return {
|
||||
status: params.status || 200,
|
||||
headers: headersObjectToArray(headers),
|
||||
body,
|
||||
isBase64
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeContinueOverrides(overrides: types.ContinueOverrides): types.NormalizedContinueOverrides {
|
||||
return {
|
||||
method: overrides.method,
|
||||
headers: overrides.headers ? headersObjectToArray(overrides.headers) : undefined,
|
||||
postData: helper.isString(overrides.postData) ? Buffer.from(overrides.postData, 'utf8') : overrides.postData,
|
||||
};
|
||||
}
|
||||
|
||||
export function headersObjectToArray(headers: types.Headers): types.HeadersArray {
|
||||
const result: types.HeadersArray = [];
|
||||
for (const name in headers) {
|
||||
if (!Object.is(headers[name], undefined)) {
|
||||
const value = headers[name];
|
||||
assert(helper.isString(value), `Expected value of header "${name}" to be String, but "${typeof value}" is found.`);
|
||||
result.push({ name, value });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function headersArrayToObject(headers: types.HeadersArray): types.Headers {
|
||||
const result: types.Headers = {};
|
||||
for (const { name, value } of headers)
|
||||
result[name] = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function envObjectToArray(env: types.Env): types.EnvArray {
|
||||
const result: types.EnvArray = [];
|
||||
for (const name in env) {
|
||||
if (!Object.is(env[name], undefined))
|
||||
result.push({ name, value: String(env[name]) });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function envArrayToObject(env: types.EnvArray): types.Env {
|
||||
const result: types.Env = {};
|
||||
for (const { name, value } of env)
|
||||
result[name] = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function axNodeToProtocol(axNode: types.SerializedAXNode): AXNode {
|
||||
const result: AXNode = {
|
||||
...axNode,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import { RouteDispatcher, RequestDispatcher } from './networkDispatchers';
|
|||
import { CRBrowserContext } from '../../chromium/crBrowser';
|
||||
import { CDPSessionDispatcher } from './cdpSessionDispatcher';
|
||||
import { Events as ChromiumEvents } from '../../chromium/events';
|
||||
import { headersArrayToObject } from '../serializers';
|
||||
import { headersArrayToObject } from '../../converters';
|
||||
|
||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, BrowserContextInitializer> implements BrowserContextChannel {
|
||||
private _context: BrowserContextBase;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { CDPSessionDispatcher } from './cdpSessionDispatcher';
|
|||
import { Dispatcher, DispatcherScope } from './dispatcher';
|
||||
import { CRBrowser } from '../../chromium/crBrowser';
|
||||
import { PageDispatcher } from './pageDispatcher';
|
||||
import { headersArrayToObject } from '../serializers';
|
||||
import { headersArrayToObject } from '../../converters';
|
||||
|
||||
export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> implements BrowserChannel {
|
||||
constructor(scope: DispatcherScope, browser: BrowserBase) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import { Dispatcher, DispatcherScope } from './dispatcher';
|
|||
import { BrowserContextBase } from '../../browserContext';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import { BrowserServerDispatcher } from './browserServerDispatcher';
|
||||
import { headersArrayToObject, envArrayToObject } from '../serializers';
|
||||
import { headersArrayToObject, envArrayToObject } from '../../converters';
|
||||
import { parseValue } from './jsHandleDispatcher';
|
||||
|
||||
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeInitializer> implements BrowserTypeChannel {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import { BrowserContextBase } from '../../browserContext';
|
|||
import { PageDispatcher } from './pageDispatcher';
|
||||
import { parseArgument, serializeResult } from './jsHandleDispatcher';
|
||||
import { createHandle } from './elementHandlerDispatcher';
|
||||
import { envArrayToObject } from '../serializers';
|
||||
import { envArrayToObject } from '../../converters';
|
||||
|
||||
export class ElectronDispatcher extends Dispatcher<Electron, ElectronInitializer> implements ElectronChannel {
|
||||
constructor(scope: DispatcherScope, electron: Electron) {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { Request, Response, Route } from '../../network';
|
|||
import { RequestChannel, ResponseChannel, RouteChannel, ResponseInitializer, RequestInitializer, RouteInitializer, Binary } from '../channels';
|
||||
import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
import { headersObjectToArray, headersArrayToObject } from '../serializers';
|
||||
import { headersObjectToArray, headersArrayToObject } from '../../converters';
|
||||
import * as types from '../../types';
|
||||
|
||||
export class RequestDispatcher extends Dispatcher<Request, RequestInitializer> implements RequestChannel {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import { Page, Worker } from '../../page';
|
|||
import * as types from '../../types';
|
||||
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary, SerializedArgument, PagePdfParams, SerializedError, PageAccessibilitySnapshotResult, SerializedValue, PageEmulateMediaParams } from '../channels';
|
||||
import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher';
|
||||
import { parseError, serializeError, headersArrayToObject, axNodeToProtocol } from '../serializers';
|
||||
import { parseError, serializeError, axNodeToProtocol } from '../serializers';
|
||||
import { headersArrayToObject } from '../../converters';
|
||||
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
|
||||
import { DialogDispatcher } from './dialogDispatcher';
|
||||
import { DownloadDispatcher } from './downloadDispatcher';
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import * as network from '../network';
|
|||
import * as types from '../types';
|
||||
import { Protocol } from './protocol';
|
||||
import { WKSession } from './wkConnection';
|
||||
import { headersArrayToObject } from '../rpc/serializers';
|
||||
import { headersArrayToObject } from '../converters';
|
||||
|
||||
const errorReasons: { [reason: string]: Protocol.Network.ResourceErrorType } = {
|
||||
'aborted': 'Cancellation',
|
||||
|
|
|
|||
|
|
@ -53,8 +53,12 @@ async function checkDeps() {
|
|||
const rpc = path.join('src', 'rpc');
|
||||
if (!from.includes(rpc) && to.includes(rpc))
|
||||
return false;
|
||||
if (from.includes(rpc) && !to.includes(rpc))
|
||||
const rpcClient = path.join('src', 'rpc', 'client');
|
||||
const rpcServer = path.join('src', 'rpc', 'server');
|
||||
if (from.includes(rpcClient) && to.includes(rpcServer))
|
||||
return false;
|
||||
// if (from.includes(rpcClient) && !to.includes(rpc))
|
||||
// return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue