Add Brave CDP automation, replace Oracle browser mode
Connects to user's running Brave via Chrome DevTools Protocol to automate ChatGPT interaction. Uses puppeteer-core to open a tab, send the prompt, wait for response, and extract the result. No cookies, no separate profiles, no copy/paste. Just connects to the browser where the user is already logged in. One-time setup: relaunch Brave with --remote-debugging-port=9222 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
37
node_modules/chromium-bidi/lib/cjs/bidiMapper/modules/bluetooth/BluetoothProcessor.d.ts
generated
vendored
Normal file
37
node_modules/chromium-bidi/lib/cjs/bidiMapper/modules/bluetooth/BluetoothProcessor.d.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC.
|
||||
* 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 { type Bluetooth, type EmptyResult } from '../../../protocol/protocol.js';
|
||||
import type { CdpTarget } from '../cdp/CdpTarget.js';
|
||||
import type { BrowsingContextStorage } from '../context/BrowsingContextStorage.js';
|
||||
import type { EventManager } from '../session/EventManager.js';
|
||||
export declare class BluetoothProcessor {
|
||||
#private;
|
||||
constructor(eventManager: EventManager, browsingContextStorage: BrowsingContextStorage);
|
||||
simulateAdapter(params: Bluetooth.SimulateAdapterParameters): Promise<EmptyResult>;
|
||||
disableSimulation(params: Bluetooth.DisableSimulationParameters): Promise<EmptyResult>;
|
||||
simulatePreconnectedPeripheral(params: Bluetooth.SimulatePreconnectedPeripheralParameters): Promise<EmptyResult>;
|
||||
simulateAdvertisement(params: Bluetooth.SimulateAdvertisementParameters): Promise<EmptyResult>;
|
||||
simulateCharacteristic(params: Bluetooth.SimulateCharacteristicParameters): Promise<EmptyResult>;
|
||||
simulateCharacteristicResponse(params: Bluetooth.SimulateCharacteristicResponseParameters): Promise<EmptyResult>;
|
||||
simulateDescriptor(params: Bluetooth.SimulateDescriptorParameters): Promise<EmptyResult>;
|
||||
simulateDescriptorResponse(params: Bluetooth.SimulateDescriptorResponseParameters): Promise<EmptyResult>;
|
||||
simulateGattConnectionResponse(params: Bluetooth.SimulateGattConnectionResponseParameters): Promise<EmptyResult>;
|
||||
simulateGattDisconnection(params: Bluetooth.SimulateGattDisconnectionParameters): Promise<EmptyResult>;
|
||||
simulateService(params: Bluetooth.SimulateServiceParameters): Promise<EmptyResult>;
|
||||
onCdpTargetCreated(cdpTarget: CdpTarget): void;
|
||||
handleRequestDevicePrompt(params: Bluetooth.HandleRequestDevicePromptParameters): Promise<EmptyResult>;
|
||||
}
|
||||
411
node_modules/chromium-bidi/lib/cjs/bidiMapper/modules/bluetooth/BluetoothProcessor.js
generated
vendored
Normal file
411
node_modules/chromium-bidi/lib/cjs/bidiMapper/modules/bluetooth/BluetoothProcessor.js
generated
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Copyright 2024 Google LLC.
|
||||
* 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.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BluetoothProcessor = void 0;
|
||||
const protocol_js_1 = require("../../../protocol/protocol.js");
|
||||
/** Represents a base Bluetooth GATT item. */
|
||||
class BluetoothGattItem {
|
||||
id;
|
||||
uuid;
|
||||
constructor(id, uuid) {
|
||||
this.id = id;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
}
|
||||
/** Represents a Bluetooth descriptor. */
|
||||
class BluetoothDescriptor extends BluetoothGattItem {
|
||||
characteristic;
|
||||
constructor(id, uuid, characteristic) {
|
||||
super(id, uuid);
|
||||
this.characteristic = characteristic;
|
||||
}
|
||||
}
|
||||
/** Represents a Bluetooth characteristic. */
|
||||
class BluetoothCharacteristic extends BluetoothGattItem {
|
||||
descriptors = new Map();
|
||||
service;
|
||||
constructor(id, uuid, service) {
|
||||
super(id, uuid);
|
||||
this.service = service;
|
||||
}
|
||||
}
|
||||
/** Represents a Bluetooth service. */
|
||||
class BluetoothService extends BluetoothGattItem {
|
||||
characteristics = new Map();
|
||||
device;
|
||||
constructor(id, uuid, device) {
|
||||
super(id, uuid);
|
||||
this.device = device;
|
||||
}
|
||||
}
|
||||
/** Represents a Bluetooth device. */
|
||||
class BluetoothDevice {
|
||||
address;
|
||||
services = new Map();
|
||||
constructor(address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
class BluetoothProcessor {
|
||||
#eventManager;
|
||||
#browsingContextStorage;
|
||||
#bluetoothDevices = new Map();
|
||||
// A map from a characteristic id from CDP to its BluetoothCharacteristic object.
|
||||
#bluetoothCharacteristics = new Map();
|
||||
// A map from a descriptor id from CDP to its BluetoothDescriptor object.
|
||||
#bluetoothDescriptors = new Map();
|
||||
constructor(eventManager, browsingContextStorage) {
|
||||
this.#eventManager = eventManager;
|
||||
this.#browsingContextStorage = browsingContextStorage;
|
||||
}
|
||||
#getDevice(address) {
|
||||
const device = this.#bluetoothDevices.get(address);
|
||||
if (!device) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Bluetooth device with address ${address} does not exist`);
|
||||
}
|
||||
return device;
|
||||
}
|
||||
#getService(device, serviceUuid) {
|
||||
const service = device.services.get(serviceUuid);
|
||||
if (!service) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Service with UUID ${serviceUuid} on device ${device.address} does not exist`);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
#getCharacteristic(service, characteristicUuid) {
|
||||
const characteristic = service.characteristics.get(characteristicUuid);
|
||||
if (!characteristic) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Characteristic with UUID ${characteristicUuid} does not exist for service ${service.uuid} on device ${service.device.address}`);
|
||||
}
|
||||
return characteristic;
|
||||
}
|
||||
#getDescriptor(characteristic, descriptorUuid) {
|
||||
const descriptor = characteristic.descriptors.get(descriptorUuid);
|
||||
if (!descriptor) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Descriptor with UUID ${descriptorUuid} does not exist for characteristic ${characteristic.uuid} on service ${characteristic.service.uuid} on device ${characteristic.service.device.address}`);
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
async simulateAdapter(params) {
|
||||
if (params.state === undefined) {
|
||||
// The bluetooth.simulateAdapter Command
|
||||
// Step 4.2. If params["state"] does not exist, return error with error code invalid argument.
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command
|
||||
throw new protocol_js_1.InvalidArgumentException(`Parameter "state" is required for creating a Bluetooth adapter`);
|
||||
}
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
// Bluetooth spec requires overriding the existing adapter (step 6). From the CDP
|
||||
// perspective, we need to disable the emulation first.
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.disable');
|
||||
this.#bluetoothDevices.clear();
|
||||
this.#bluetoothCharacteristics.clear();
|
||||
this.#bluetoothDescriptors.clear();
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.enable', {
|
||||
state: params.state,
|
||||
leSupported: params.leSupported ?? true,
|
||||
});
|
||||
return {};
|
||||
}
|
||||
async disableSimulation(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.disable');
|
||||
this.#bluetoothDevices.clear();
|
||||
this.#bluetoothCharacteristics.clear();
|
||||
this.#bluetoothDescriptors.clear();
|
||||
return {};
|
||||
}
|
||||
async simulatePreconnectedPeripheral(params) {
|
||||
if (this.#bluetoothDevices.has(params.address)) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Bluetooth device with address ${params.address} already exists`);
|
||||
}
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulatePreconnectedPeripheral', {
|
||||
address: params.address,
|
||||
name: params.name,
|
||||
knownServiceUuids: params.knownServiceUuids,
|
||||
manufacturerData: params.manufacturerData,
|
||||
});
|
||||
this.#bluetoothDevices.set(params.address, new BluetoothDevice(params.address));
|
||||
return {};
|
||||
}
|
||||
async simulateAdvertisement(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulateAdvertisement', {
|
||||
entry: params.scanEntry,
|
||||
});
|
||||
return {};
|
||||
}
|
||||
async simulateCharacteristic(params) {
|
||||
const device = this.#getDevice(params.address);
|
||||
const service = this.#getService(device, params.serviceUuid);
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
switch (params.type) {
|
||||
case 'add': {
|
||||
if (params.characteristicProperties === undefined) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Parameter "characteristicProperties" is required for adding a Bluetooth characteristic`);
|
||||
}
|
||||
if (service.characteristics.has(params.characteristicUuid)) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Characteristic with UUID ${params.characteristicUuid} already exists`);
|
||||
}
|
||||
const response = await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.addCharacteristic', {
|
||||
serviceId: service.id,
|
||||
characteristicUuid: params.characteristicUuid,
|
||||
properties: params.characteristicProperties,
|
||||
});
|
||||
const characteristic = new BluetoothCharacteristic(response.characteristicId, params.characteristicUuid, service);
|
||||
service.characteristics.set(params.characteristicUuid, characteristic);
|
||||
this.#bluetoothCharacteristics.set(characteristic.id, characteristic);
|
||||
return {};
|
||||
}
|
||||
case 'remove': {
|
||||
if (params.characteristicProperties !== undefined) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Parameter "characteristicProperties" should not be provided for removing a Bluetooth characteristic`);
|
||||
}
|
||||
const characteristic = this.#getCharacteristic(service, params.characteristicUuid);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.removeCharacteristic', {
|
||||
characteristicId: characteristic.id,
|
||||
});
|
||||
service.characteristics.delete(params.characteristicUuid);
|
||||
this.#bluetoothCharacteristics.delete(characteristic.id);
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
throw new protocol_js_1.InvalidArgumentException(`Parameter "type" of ${params.type} is not supported`);
|
||||
}
|
||||
}
|
||||
async simulateCharacteristicResponse(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
const device = this.#getDevice(params.address);
|
||||
const service = this.#getService(device, params.serviceUuid);
|
||||
const characteristic = this.#getCharacteristic(service, params.characteristicUuid);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulateCharacteristicOperationResponse', {
|
||||
characteristicId: characteristic.id,
|
||||
type: params.type,
|
||||
code: params.code,
|
||||
...(params.data && {
|
||||
data: btoa(String.fromCharCode(...params.data)),
|
||||
}),
|
||||
});
|
||||
return {};
|
||||
}
|
||||
async simulateDescriptor(params) {
|
||||
const device = this.#getDevice(params.address);
|
||||
const service = this.#getService(device, params.serviceUuid);
|
||||
const characteristic = this.#getCharacteristic(service, params.characteristicUuid);
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
switch (params.type) {
|
||||
case 'add': {
|
||||
if (characteristic.descriptors.has(params.descriptorUuid)) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Descriptor with UUID ${params.descriptorUuid} already exists`);
|
||||
}
|
||||
const response = await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.addDescriptor', {
|
||||
characteristicId: characteristic.id,
|
||||
descriptorUuid: params.descriptorUuid,
|
||||
});
|
||||
const descriptor = new BluetoothDescriptor(response.descriptorId, params.descriptorUuid, characteristic);
|
||||
characteristic.descriptors.set(params.descriptorUuid, descriptor);
|
||||
this.#bluetoothDescriptors.set(descriptor.id, descriptor);
|
||||
return {};
|
||||
}
|
||||
case 'remove': {
|
||||
const descriptor = this.#getDescriptor(characteristic, params.descriptorUuid);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.removeDescriptor', {
|
||||
descriptorId: descriptor.id,
|
||||
});
|
||||
characteristic.descriptors.delete(params.descriptorUuid);
|
||||
this.#bluetoothDescriptors.delete(descriptor.id);
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
throw new protocol_js_1.InvalidArgumentException(`Parameter "type" of ${params.type} is not supported`);
|
||||
}
|
||||
}
|
||||
async simulateDescriptorResponse(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
const device = this.#getDevice(params.address);
|
||||
const service = this.#getService(device, params.serviceUuid);
|
||||
const characteristic = this.#getCharacteristic(service, params.characteristicUuid);
|
||||
const descriptor = this.#getDescriptor(characteristic, params.descriptorUuid);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulateDescriptorOperationResponse', {
|
||||
descriptorId: descriptor.id,
|
||||
type: params.type,
|
||||
code: params.code,
|
||||
...(params.data && {
|
||||
data: btoa(String.fromCharCode(...params.data)),
|
||||
}),
|
||||
});
|
||||
return {};
|
||||
}
|
||||
async simulateGattConnectionResponse(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulateGATTOperationResponse', {
|
||||
address: params.address,
|
||||
type: 'connection',
|
||||
code: params.code,
|
||||
});
|
||||
return {};
|
||||
}
|
||||
async simulateGattDisconnection(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulateGATTDisconnection', {
|
||||
address: params.address,
|
||||
});
|
||||
return {};
|
||||
}
|
||||
async simulateService(params) {
|
||||
const device = this.#getDevice(params.address);
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
switch (params.type) {
|
||||
case 'add': {
|
||||
if (device.services.has(params.uuid)) {
|
||||
throw new protocol_js_1.InvalidArgumentException(`Service with UUID ${params.uuid} already exists`);
|
||||
}
|
||||
const response = await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.addService', {
|
||||
address: params.address,
|
||||
serviceUuid: params.uuid,
|
||||
});
|
||||
device.services.set(params.uuid, new BluetoothService(response.serviceId, params.uuid, device));
|
||||
return {};
|
||||
}
|
||||
case 'remove': {
|
||||
const service = this.#getService(device, params.uuid);
|
||||
await context.cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.removeService', {
|
||||
serviceId: service.id,
|
||||
});
|
||||
device.services.delete(params.uuid);
|
||||
return {};
|
||||
}
|
||||
default:
|
||||
throw new protocol_js_1.InvalidArgumentException(`Parameter "type" of ${params.type} is not supported`);
|
||||
}
|
||||
}
|
||||
onCdpTargetCreated(cdpTarget) {
|
||||
cdpTarget.cdpClient.on('DeviceAccess.deviceRequestPrompted', (event) => {
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: 'bluetooth.requestDevicePromptUpdated',
|
||||
params: {
|
||||
context: cdpTarget.id,
|
||||
prompt: event.id,
|
||||
devices: event.devices,
|
||||
},
|
||||
}, cdpTarget.id);
|
||||
});
|
||||
cdpTarget.browserCdpClient.on('BluetoothEmulation.gattOperationReceived', async (event) => {
|
||||
switch (event.type) {
|
||||
case 'connection':
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: 'bluetooth.gattConnectionAttempted',
|
||||
params: {
|
||||
context: cdpTarget.id,
|
||||
address: event.address,
|
||||
},
|
||||
}, cdpTarget.id);
|
||||
return;
|
||||
case 'discovery':
|
||||
// Chromium Web Bluetooth simulation generates this GATT discovery event when
|
||||
// a page attempts to get services for a given Bluetooth device for the first time.
|
||||
// This 'get services' operation is put on hold until a GATT discovery response
|
||||
// is sent to the simulation.
|
||||
// Note: Web Bluetooth automation (see https://webbluetoothcg.github.io/web-bluetooth/#automated-testing)
|
||||
// does not support simulating a GATT discovery response. This is because simulated services, characteristics,
|
||||
// or descriptors are immediately visible to the simulation, meaning it doesn't have a distinct
|
||||
// DISCOVERY state. Therefore, this code simulates a successful GATT discovery
|
||||
// response upon receiving this event.
|
||||
await cdpTarget.browserCdpClient.sendCommand('BluetoothEmulation.simulateGATTOperationResponse', {
|
||||
address: event.address,
|
||||
type: 'discovery',
|
||||
code: 0x0,
|
||||
});
|
||||
}
|
||||
});
|
||||
cdpTarget.browserCdpClient.on('BluetoothEmulation.characteristicOperationReceived', (event) => {
|
||||
if (!this.#bluetoothCharacteristics.has(event.characteristicId)) {
|
||||
return;
|
||||
}
|
||||
let type;
|
||||
if (event.type === 'write') {
|
||||
// write-default-deprecated comes from
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue,
|
||||
// which is deprecated so not supported.
|
||||
if (event.writeType === 'write-default-deprecated') {
|
||||
return;
|
||||
}
|
||||
type = event.writeType;
|
||||
}
|
||||
else {
|
||||
type = event.type;
|
||||
}
|
||||
const characteristic = this.#bluetoothCharacteristics.get(event.characteristicId);
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: 'bluetooth.characteristicEventGenerated',
|
||||
params: {
|
||||
context: cdpTarget.id,
|
||||
address: characteristic.service.device.address,
|
||||
serviceUuid: characteristic.service.uuid,
|
||||
characteristicUuid: characteristic.uuid,
|
||||
type,
|
||||
...(event.data && {
|
||||
data: Array.from(atob(event.data), (c) => c.charCodeAt(0)),
|
||||
}),
|
||||
},
|
||||
}, cdpTarget.id);
|
||||
});
|
||||
cdpTarget.browserCdpClient.on('BluetoothEmulation.descriptorOperationReceived', (event) => {
|
||||
if (!this.#bluetoothDescriptors.has(event.descriptorId)) {
|
||||
return;
|
||||
}
|
||||
const descriptor = this.#bluetoothDescriptors.get(event.descriptorId);
|
||||
this.#eventManager.registerEvent({
|
||||
type: 'event',
|
||||
method: 'bluetooth.descriptorEventGenerated',
|
||||
params: {
|
||||
context: cdpTarget.id,
|
||||
address: descriptor.characteristic.service.device.address,
|
||||
serviceUuid: descriptor.characteristic.service.uuid,
|
||||
characteristicUuid: descriptor.characteristic.uuid,
|
||||
descriptorUuid: descriptor.uuid,
|
||||
type: event.type,
|
||||
...(event.data && {
|
||||
data: Array.from(atob(event.data), (c) => c.charCodeAt(0)),
|
||||
}),
|
||||
},
|
||||
}, cdpTarget.id);
|
||||
});
|
||||
}
|
||||
async handleRequestDevicePrompt(params) {
|
||||
const context = this.#browsingContextStorage.getContext(params.context);
|
||||
if (params.accept) {
|
||||
await context.cdpTarget.cdpClient.sendCommand('DeviceAccess.selectPrompt', {
|
||||
id: params.prompt,
|
||||
deviceId: params.device,
|
||||
});
|
||||
}
|
||||
else {
|
||||
await context.cdpTarget.cdpClient.sendCommand('DeviceAccess.cancelPrompt', {
|
||||
id: params.prompt,
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
exports.BluetoothProcessor = BluetoothProcessor;
|
||||
//# sourceMappingURL=BluetoothProcessor.js.map
|
||||
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/modules/bluetooth/BluetoothProcessor.js.map
generated
vendored
Normal file
1
node_modules/chromium-bidi/lib/cjs/bidiMapper/modules/bluetooth/BluetoothProcessor.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user