chore: validate client/server version match for remote connections (#10542)

* chore: validate client/server version match on connect

* only validate major and minor
This commit is contained in:
Max Schmitt 2021-11-30 08:36:00 +01:00 committed by GitHub
parent 90e7a45211
commit 41070a2f55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 14 additions and 1 deletions

View File

@ -40,6 +40,7 @@ import { Artifact } from './artifact';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { JsonPipe } from './jsonPipe'; import { JsonPipe } from './jsonPipe';
import { APIRequestContext } from './fetch'; import { APIRequestContext } from './fetch';
import { getPlaywrightVersion } from '../utils/utils';
class Root extends ChannelOwner<channels.RootChannel> { class Root extends ChannelOwner<channels.RootChannel> {
constructor(connection: Connection) { constructor(connection: Connection) {
@ -49,6 +50,7 @@ class Root extends ChannelOwner<channels.RootChannel> {
async initialize(): Promise<Playwright> { async initialize(): Promise<Playwright> {
return Playwright.from((await this._channel.initialize({ return Playwright.from((await this._channel.initialize({
sdkLanguage: 'javascript', sdkLanguage: 'javascript',
version: getPlaywrightVersion(),
})).playwright); })).playwright);
} }
} }

View File

@ -18,7 +18,7 @@ import { EventEmitter } from 'events';
import * as channels from '../protocol/channels'; import * as channels from '../protocol/channels';
import { serializeError } from '../protocol/serializers'; import { serializeError } from '../protocol/serializers';
import { createScheme, Validator, ValidationError } from '../protocol/validator'; import { createScheme, Validator, ValidationError } from '../protocol/validator';
import { assert, debugAssert, isUnderTest, monotonicTime } from '../utils/utils'; import { assert, debugAssert, getPlaywrightVersion, isUnderTest, monotonicTime } from '../utils/utils';
import { tOptional } from '../protocol/validatorPrimitives'; import { tOptional } from '../protocol/validatorPrimitives';
import { kBrowserOrContextClosedError } from '../utils/errors'; import { kBrowserOrContextClosedError } from '../utils/errors';
import { CallMetadata, SdkObject } from '../server/instrumentation'; import { CallMetadata, SdkObject } from '../server/instrumentation';
@ -132,6 +132,7 @@ export class Root extends Dispatcher<{ guid: '' }, any> {
async initialize(params: channels.RootInitializeParams): Promise<channels.RootInitializeResult> { async initialize(params: channels.RootInitializeParams): Promise<channels.RootInitializeResult> {
assert(this.createPlaywright); assert(this.createPlaywright);
assert(!this._initialized); assert(!this._initialized);
assertPlaywrightVersion(params.version);
this._initialized = true; this._initialized = true;
return { return {
playwright: await this.createPlaywright(this, params), playwright: await this.createPlaywright(this, params),
@ -320,3 +321,10 @@ function formatLogRecording(log: string[]): string {
} }
let lastEventId = 0; let lastEventId = 0;
function assertPlaywrightVersion(givenVersion: string): void {
const expectedVersion = getPlaywrightVersion();
const givenParts = givenVersion.split('.');
const expectedParts = givenVersion.split('.');
assert(givenParts.slice(0, 2).join('.') === expectedParts.slice(0, 2).join('.'), `${expectedVersion} does not match the client version ${givenVersion}.`);
}

View File

@ -346,6 +346,7 @@ export interface RootChannel extends RootEventTarget, Channel {
} }
export type RootInitializeParams = { export type RootInitializeParams = {
sdkLanguage: string, sdkLanguage: string,
version: string,
}; };
export type RootInitializeOptions = { export type RootInitializeOptions = {

View File

@ -415,6 +415,7 @@ Root:
initialize: initialize:
parameters: parameters:
sdkLanguage: string sdkLanguage: string
version: string
returns: returns:
playwright: Playwright playwright: Playwright

View File

@ -188,6 +188,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
scheme.LifecycleEvent = tEnum(['load', 'domcontentloaded', 'networkidle', 'commit']); scheme.LifecycleEvent = tEnum(['load', 'domcontentloaded', 'networkidle', 'commit']);
scheme.RootInitializeParams = tObject({ scheme.RootInitializeParams = tObject({
sdkLanguage: tString, sdkLanguage: tString,
version: tString,
}); });
scheme.PlaywrightSocksConnectedParams = tObject({ scheme.PlaywrightSocksConnectedParams = tObject({
uid: tString, uid: tString,