110 lines
4 KiB
TypeScript
110 lines
4 KiB
TypeScript
/**
|
|
* 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 { BrowserContext } from '../browserContext';
|
|
import { RecorderSupplement } from './recorderSupplement';
|
|
import { debugLogger } from '../../utils/debugLogger';
|
|
import { CallMetadata, InstrumentationListener, SdkObject } from '../instrumentation';
|
|
import { isDebugMode, isUnderTest } from '../../utils/utils';
|
|
|
|
export class InspectorController implements InstrumentationListener {
|
|
private _waitOperations = new Map<string, CallMetadata>();
|
|
|
|
async onContextCreated(context: BrowserContext): Promise<void> {
|
|
if (isDebugMode())
|
|
await RecorderSupplement.getOrCreate(context, { pauseOnNextStatement: true });
|
|
}
|
|
|
|
async onBeforeCall(sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
|
|
const context = sdkObject.attribution.context;
|
|
if (!context)
|
|
return;
|
|
|
|
// Process logs for waitForNavigation/waitForLoadState
|
|
if (metadata.params?.info?.waitId) {
|
|
const info = metadata.params.info;
|
|
switch (info.phase) {
|
|
case 'before':
|
|
metadata.method = info.name;
|
|
metadata.stack = info.stack;
|
|
this._waitOperations.set(info.waitId, metadata);
|
|
break;
|
|
case 'log':
|
|
const originalMetadata = this._waitOperations.get(info.waitId)!;
|
|
originalMetadata.log.push(info.message);
|
|
this.onCallLog('api', info.message, sdkObject, originalMetadata);
|
|
// Fall through.
|
|
case 'after':
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (shouldOpenInspector(sdkObject, metadata))
|
|
await RecorderSupplement.getOrCreate(context, { pauseOnNextStatement: true });
|
|
|
|
const recorder = await RecorderSupplement.getNoCreate(context);
|
|
await recorder?.onBeforeCall(sdkObject, metadata);
|
|
}
|
|
|
|
async onAfterCall(sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
|
|
if (!sdkObject.attribution.context)
|
|
return;
|
|
|
|
// Process logs for waitForNavigation/waitForLoadState
|
|
if (metadata.params?.info?.waitId) {
|
|
const info = metadata.params.info;
|
|
switch (info.phase) {
|
|
case 'before':
|
|
metadata.endTime = 0;
|
|
// Fall through.
|
|
case 'log':
|
|
return;
|
|
case 'after':
|
|
const originalMetadata = this._waitOperations.get(info.waitId)!;
|
|
originalMetadata.endTime = metadata.endTime;
|
|
originalMetadata.error = info.error;
|
|
this._waitOperations.delete(info.waitId);
|
|
metadata = originalMetadata;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const recorder = await RecorderSupplement.getNoCreate(sdkObject.attribution.context);
|
|
await recorder?.onAfterCall(sdkObject, metadata);
|
|
}
|
|
|
|
async onBeforeInputAction(sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
|
|
if (!sdkObject.attribution.context)
|
|
return;
|
|
const recorder = await RecorderSupplement.getNoCreate(sdkObject.attribution.context);
|
|
await recorder?.onBeforeInputAction(sdkObject, metadata);
|
|
}
|
|
|
|
async onCallLog(logName: string, message: string, sdkObject: SdkObject, metadata: CallMetadata): Promise<void> {
|
|
debugLogger.log(logName as any, message);
|
|
if (!sdkObject.attribution.context)
|
|
return;
|
|
const recorder = await RecorderSupplement.getNoCreate(sdkObject.attribution.context);
|
|
await recorder?.updateCallLog([metadata]);
|
|
}
|
|
}
|
|
|
|
function shouldOpenInspector(sdkObject: SdkObject, metadata: CallMetadata): boolean {
|
|
if (!sdkObject.attribution.browser?.options.headful && !isUnderTest())
|
|
return false;
|
|
return metadata.method === 'pause';
|
|
}
|