chromium-bidi
Advanced tools
Comparing version 0.5.17 to 0.5.18
@@ -238,3 +238,3 @@ "use strict"; | ||
this.#url = params.url; | ||
this.#navigation.withinDocument.resolve(params); | ||
this.#navigation.withinDocument.resolve(); | ||
this.#eventManager.registerEvent({ | ||
@@ -301,3 +301,3 @@ type: 'event', | ||
}, this.id); | ||
this.#lifecycle.DOMContentLoaded.resolve(params); | ||
this.#lifecycle.DOMContentLoaded.resolve(); | ||
break; | ||
@@ -315,3 +315,3 @@ case 'load': | ||
}, this.id); | ||
this.#lifecycle.load.resolve(params); | ||
this.#lifecycle.load.resolve(); | ||
break; | ||
@@ -393,4 +393,3 @@ } | ||
if (this.#navigation.withinDocument.isFinished) { | ||
this.#navigation.withinDocument = | ||
new Deferred_js_1.Deferred(); | ||
this.#navigation.withinDocument = new Deferred_js_1.Deferred(); | ||
} | ||
@@ -407,4 +406,3 @@ else { | ||
if (this.#lifecycle.DOMContentLoaded.isFinished) { | ||
this.#lifecycle.DOMContentLoaded = | ||
new Deferred_js_1.Deferred(); | ||
this.#lifecycle.DOMContentLoaded = new Deferred_js_1.Deferred(); | ||
} | ||
@@ -754,3 +752,3 @@ else { | ||
} | ||
#getLocatorDelegate(locator, maxNodeCount, startNodes) { | ||
async #getLocatorDelegate(realm, locator, maxNodeCount, startNodes) { | ||
switch (locator.type) { | ||
@@ -901,6 +899,83 @@ case 'css': | ||
}; | ||
case 'accessibility': { | ||
// https://w3c.github.io/webdriver-bidi/#locate-nodes-using-accessibility-attributes | ||
if (!locator.value.name && !locator.value.role) { | ||
throw new protocol_js_1.InvalidSelectorException('Either name or role has to be specified'); | ||
} | ||
const bindings = await realm.evaluate( | ||
/* expression=*/ '({getAccessibleName, getAccessibleRole})', | ||
/* awaitPromise=*/ false, "root" /* Script.ResultOwnership.Root */, | ||
/* serializationOptions= */ undefined, | ||
/* userActivation=*/ false, | ||
/* includeCommandLineApi=*/ true); | ||
if (bindings.type !== 'success') { | ||
throw new Error('Could not get bindings'); | ||
} | ||
if (bindings.result.type !== 'object') { | ||
throw new Error('Could not get bindings'); | ||
} | ||
return { | ||
functionDeclaration: String((name, role, bindings, maxNodeCount, ...startNodes) => { | ||
const returnedNodes = []; | ||
let aborted = false; | ||
function collect(contextNodes, selector) { | ||
if (aborted) { | ||
return; | ||
} | ||
for (const contextNode of contextNodes) { | ||
let match = true; | ||
if (selector.role) { | ||
const role = bindings.getAccessibleRole(contextNode); | ||
if (selector.role !== role) { | ||
match = false; | ||
} | ||
} | ||
if (selector.name) { | ||
const name = bindings.getAccessibleName(contextNode); | ||
if (selector.name !== name) { | ||
match = false; | ||
} | ||
} | ||
if (match) { | ||
if (maxNodeCount !== 0 && | ||
returnedNodes.length === maxNodeCount) { | ||
aborted = true; | ||
break; | ||
} | ||
returnedNodes.push(contextNode); | ||
} | ||
const childNodes = []; | ||
for (const child of contextNode.children) { | ||
if (child instanceof HTMLElement) { | ||
childNodes.push(child); | ||
} | ||
} | ||
collect(childNodes, selector); | ||
} | ||
} | ||
startNodes = startNodes.length > 0 ? startNodes : [document.body]; | ||
collect(startNodes, { | ||
role, | ||
name, | ||
}); | ||
return returnedNodes; | ||
}), | ||
argumentsLocalValues: [ | ||
// `name` | ||
{ type: 'string', value: locator.value.name || '' }, | ||
// `role` | ||
{ type: 'string', value: locator.value.role || '' }, | ||
// `bindings`. | ||
{ handle: bindings.result.handle }, | ||
// `maxNodeCount` with `0` means no limit. | ||
{ type: 'number', value: maxNodeCount ?? 0 }, | ||
// `startNodes` | ||
...startNodes, | ||
], | ||
}; | ||
} | ||
} | ||
} | ||
async #locateNodesByLocator(realm, locator, startNodes, maxNodeCount, serializationOptions) { | ||
const locatorDelegate = this.#getLocatorDelegate(locator, maxNodeCount, startNodes); | ||
const locatorDelegate = await this.#getLocatorDelegate(realm, locator, maxNodeCount, startNodes); | ||
serializationOptions = { | ||
@@ -920,3 +995,3 @@ ...serializationOptions, | ||
locatorResult.exceptionDetails.text?.endsWith('is not a valid XPath expression.')) { | ||
throw new protocol_js_1.InvalidSelectorException(`Not valid selector ${locator.value}`); | ||
throw new protocol_js_1.InvalidSelectorException(`Not valid selector ${typeof locator.value === 'string' ? locator.value : JSON.stringify(locator.value)}`); | ||
} | ||
@@ -923,0 +998,0 @@ // Heuristic to detect if the `startNode` is not an `HTMLElement` in css selector. |
@@ -33,2 +33,5 @@ "use strict"; | ||
} | ||
const existingContexts = this.#browsingContextStorage | ||
.getAllContexts() | ||
.filter((context) => context.userContext === userContext); | ||
let newWindow = false; | ||
@@ -43,11 +46,6 @@ switch (params.type) { | ||
} | ||
if (userContext !== 'default') { | ||
const existingContexts = this.#browsingContextStorage | ||
.getAllContexts() | ||
.filter((context) => context.userContext === userContext); | ||
if (!existingContexts.length) { | ||
// If there are no contexts in the given user context, we need to set | ||
// newWindow to true as newWindow=false will be rejected. | ||
newWindow = true; | ||
} | ||
if (!existingContexts.length) { | ||
// If there are no contexts in the given user context, we need to set | ||
// newWindow to true as newWindow=false will be rejected. | ||
newWindow = true; | ||
} | ||
@@ -54,0 +52,0 @@ let result; |
@@ -54,9 +54,9 @@ /** | ||
count: number; | ||
"__#89229@#x": number; | ||
"__#89229@#y": number; | ||
"__#89229@#time": number; | ||
"__#89377@#x": number; | ||
"__#89377@#y": number; | ||
"__#89377@#time": number; | ||
compare(context: any): boolean; | ||
}; | ||
"__#89229@#DOUBLE_CLICK_TIME_MS": number; | ||
"__#89229@#MAX_DOUBLE_CLICK_RADIUS": number; | ||
"__#89377@#DOUBLE_CLICK_TIME_MS": number; | ||
"__#89377@#MAX_DOUBLE_CLICK_RADIUS": number; | ||
}; | ||
@@ -63,0 +63,0 @@ setClickCount(button: number, context: InstanceType<typeof PointerSource.ClickContext>): number; |
@@ -191,2 +191,11 @@ "use strict"; | ||
onResponseReceivedExtraInfoEvent(event) { | ||
if (event.statusCode >= 300 && | ||
event.statusCode <= 399 && | ||
this.#request.info && | ||
event.headers['location'] === this.#request.info.request.url) { | ||
// We received the Response Extra info for the redirect | ||
// Too late so we need to skip it as it will | ||
// fire wrongly for the last one | ||
return; | ||
} | ||
this.#response.extraInfo = event; | ||
@@ -193,0 +202,0 @@ this.#emitEventsIfReady(); |
@@ -49,3 +49,3 @@ /** | ||
abstract get realmInfo(): Script.RealmInfo; | ||
evaluate(expression: string, awaitPromise: boolean, resultOwnership?: Script.ResultOwnership, serializationOptions?: Script.SerializationOptions, userActivation?: boolean): Promise<Script.EvaluateResult>; | ||
evaluate(expression: string, awaitPromise: boolean, resultOwnership?: Script.ResultOwnership, serializationOptions?: Script.SerializationOptions, userActivation?: boolean, includeCommandLineApi?: boolean): Promise<Script.EvaluateResult>; | ||
protected initialize(): void; | ||
@@ -52,0 +52,0 @@ /** |
@@ -112,3 +112,3 @@ "use strict"; | ||
} | ||
async evaluate(expression, awaitPromise, resultOwnership = "none" /* Script.ResultOwnership.None */, serializationOptions = {}, userActivation = false) { | ||
async evaluate(expression, awaitPromise, resultOwnership = "none" /* Script.ResultOwnership.None */, serializationOptions = {}, userActivation = false, includeCommandLineApi = false) { | ||
const cdpEvaluateResult = await this.cdpClient.sendCommand('Runtime.evaluate', { | ||
@@ -120,2 +120,3 @@ contextId: this.executionContextId, | ||
userGesture: userActivation, | ||
includeCommandLineAPI: includeCommandLineApi, | ||
}); | ||
@@ -122,0 +123,0 @@ if (cdpEvaluateResult.exceptionDetails) { |
@@ -37,4 +37,4 @@ /** | ||
deserializeForCdp(localValue: Script.LocalValue): Promise<Protocol.Runtime.CallArgument>; | ||
evaluate(expression: string, awaitPromise: boolean, resultOwnership: Script.ResultOwnership, serializationOptions: Script.SerializationOptions, userActivation?: boolean): Promise<Script.EvaluateResult>; | ||
evaluate(expression: string, awaitPromise: boolean, resultOwnership: Script.ResultOwnership, serializationOptions: Script.SerializationOptions, userActivation?: boolean, includeCommandLineApi?: boolean): Promise<Script.EvaluateResult>; | ||
callFunction(functionDeclaration: string, awaitPromise: boolean, thisLocalValue: Script.LocalValue, argumentsLocalValues: Script.LocalValue[], resultOwnership: Script.ResultOwnership, serializationOptions: Script.SerializationOptions, userActivation?: boolean): Promise<Script.EvaluateResult>; | ||
} |
@@ -126,7 +126,7 @@ "use strict"; | ||
} | ||
async evaluate(expression, awaitPromise, resultOwnership, serializationOptions, userActivation) { | ||
async evaluate(expression, awaitPromise, resultOwnership, serializationOptions, userActivation, includeCommandLineApi) { | ||
await this.#browsingContextStorage | ||
.getContext(this.#browsingContextId) | ||
.targetUnblockedOrThrow(); | ||
return await super.evaluate(expression, awaitPromise, resultOwnership, serializationOptions, userActivation); | ||
return await super.evaluate(expression, awaitPromise, resultOwnership, serializationOptions, userActivation, includeCommandLineApi); | ||
} | ||
@@ -133,0 +133,0 @@ async callFunction(functionDeclaration, awaitPromise, thisLocalValue, argumentsLocalValues, resultOwnership, serializationOptions, userActivation) { |
@@ -22,28 +22,3 @@ "use strict"; | ||
/** HTML source code for the user-facing Mapper tab. */ | ||
const mapperPageSource = '<!DOCTYPE html><title>BiDi-CDP Mapper</title><style>body{font-family: Roboto, serif; font-size: 13px; color: #202124;}.log{padding: 12px; font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace; font-size: 11px; line-height: 180%; background: #f1f3f4; border-radius: 4px;}.pre{overflow-wrap: break-word; padding: 10px;}.card{margin: 60px auto; padding: 2px 0; max-width: 900px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15), 0 1px 6px rgba(0, 0, 0, 0.2); border-radius: 8px;}.divider{height: 1px; background: #f0f0f0;}.item{padding: 16px 20px;}</style><div class="card"><div class="item"><h1>BiDi-CDP Mapper is controlling this tab</h1><p>Closing or reloading it will stop the BiDi process. <a target="_blank" title="BiDi-CDP Mapper GitHub Repository" href="https://github.com/GoogleChromeLabs/chromium-bidi">Details.</a></p></div><div class="divider"></div><details id="details"><summary class="item">Debug information</summary></details></div>'; | ||
/** | ||
* The following piece of HTML should be added to the `debug` element: | ||
* | ||
* <div class="divider"></div> | ||
* <div class="item"> | ||
* <h3>${name}</h3> | ||
* <div id="${name}_log" class="log"> | ||
*/ | ||
function findOrCreateTypeLogContainer(logPrefix) { | ||
const logType = logPrefix.split(':')[0]; | ||
const containerId = `${logType}_log`; | ||
const existingContainer = document.getElementById(containerId); | ||
if (existingContainer) { | ||
return existingContainer; | ||
} | ||
const debugElement = document.getElementById('details'); | ||
const divider = document.createElement('div'); | ||
divider.className = 'divider'; | ||
debugElement.appendChild(divider); | ||
const htmlItem = document.createElement('div'); | ||
htmlItem.className = 'item'; | ||
htmlItem.innerHTML = `<h3>${logType}</h3><div id="${containerId}" class="log"></div>`; | ||
debugElement.appendChild(htmlItem); | ||
return document.getElementById(containerId); | ||
} | ||
const mapperPageSource = '<!DOCTYPE html><title>BiDi-CDP Mapper</title><style>body{font-family: Roboto,serif;font-size:13px;color:#202124;}.log{padding: 10px;font-family:Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;font-size:11px;line-height:180%;background: #f1f3f4;border-radius:4px;}.pre{overflow-wrap: break-word; margin:10px;}.card{margin:60px auto;padding:2px 0;max-width:900px;box-shadow:0 1px 4px rgba(0,0,0,0.15),0 1px 6px rgba(0,0,0,0.2);border-radius:8px;}.divider{height:1px;background:#f0f0f0;}.item{padding:16px 20px;}</style><div class="card"><div class="item"><h1>BiDi-CDP Mapper is controlling this tab</h1><p>Closing or reloading it will stop the BiDi process. <a target="_blank" title="BiDi-CDP Mapper GitHub Repository" href="https://github.com/GoogleChromeLabs/chromium-bidi">Details.</a></p></div><div class="item"><div id="logs" class="log"></div></div></div></div>'; | ||
function generatePage() { | ||
@@ -55,6 +30,2 @@ // If run not in browser (e.g. unit test), do nothing. | ||
globalThis.document.documentElement.innerHTML = mapperPageSource; | ||
// Create main log containers in proper order. | ||
findOrCreateTypeLogContainer(log_js_1.LogType.debugInfo); | ||
findOrCreateTypeLogContainer(log_js_1.LogType.bidi); | ||
findOrCreateTypeLogContainer(log_js_1.LogType.cdp); | ||
} | ||
@@ -76,5 +47,8 @@ exports.generatePage = generatePage; | ||
// If `sendDebugMessage` is defined, send the log message there. | ||
globalThis.window?.sendDebugMessage?.(JSON.stringify({ logType: logPrefix, messages })); | ||
globalThis.window?.sendDebugMessage?.(JSON.stringify({ logType: logPrefix, messages }, null, 2)); | ||
} | ||
const typeLogContainer = findOrCreateTypeLogContainer(logPrefix); | ||
const debugContainer = document.getElementById('logs'); | ||
if (!debugContainer) { | ||
return; | ||
} | ||
// This piece of HTML should be added: | ||
@@ -85,5 +59,5 @@ // <div class="pre">...log message...</div> | ||
lineElement.textContent = [logPrefix, ...messages].map(stringify).join(' '); | ||
typeLogContainer.appendChild(lineElement); | ||
if (typeLogContainer.childNodes.length > 200) { | ||
typeLogContainer.removeChild(typeLogContainer.childNodes[0]); | ||
debugContainer.appendChild(lineElement); | ||
if (debugContainer.childNodes.length > 400) { | ||
debugContainer.removeChild(debugContainer.childNodes[0]); | ||
} | ||
@@ -90,0 +64,0 @@ } |
@@ -275,5 +275,14 @@ /** | ||
export declare namespace BrowsingContext { | ||
type Locator = BrowsingContext.CssLocator | BrowsingContext.InnerTextLocator | BrowsingContext.XPathLocator; | ||
type Locator = BrowsingContext.AccessibilityLocator | BrowsingContext.CssLocator | BrowsingContext.InnerTextLocator | BrowsingContext.XPathLocator; | ||
} | ||
export declare namespace BrowsingContext { | ||
type AccessibilityLocator = { | ||
type: 'accessibility'; | ||
value: { | ||
name?: string; | ||
role?: string; | ||
}; | ||
}; | ||
} | ||
export declare namespace BrowsingContext { | ||
type CssLocator = { | ||
@@ -280,0 +289,0 @@ type: 'css'; |
{ | ||
"name": "chromium-bidi", | ||
"version": "0.5.17", | ||
"version": "0.5.18", | ||
"description": "An implementation of the WebDriver BiDi protocol for Chromium implemented as a JavaScript layer translating between BiDi and CDP, running inside a Chrome tab.", | ||
@@ -168,3 +168,3 @@ "scripts": { | ||
"debug": "4.3.4", | ||
"devtools-protocol": "0.0.1282316", | ||
"devtools-protocol": "0.0.1286932", | ||
"eslint": "8.57.0", | ||
@@ -171,0 +171,0 @@ "eslint-config-prettier": "9.1.0", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
8057634
110156