Overview
The TargetHandler module manages browser tabs and browser contexts through the Chrome DevTools Protocol Target domain, providing target discovery, creation, closure, switching, registration, and matching capabilities.
Description
TargetHandler is the central module for managing the lifecycle of browser tabs (targets) and their associated browser contexts. It maintains two core registries: a targetRegistry (Map of user-assigned names to target IDs) and a browserRegistry (Map of target IDs to browser context IDs). These registries enable Taiko's named tab API, allowing users to assign friendly names to tabs and switch between them.
The module establishes two CDP connections: one through the session-level client (for Target.getTargetInfo and Target.setDiscoverTargets) and one through the browser-level debug URL (for Target.createTarget, Target.closeTarget, Target.createBrowserContext, Target.disposeBrowserContext, and Target.activateTarget). This dual-connection design is necessary because certain Target domain commands (like createBrowserContext) are only available at the browser level.
Target matching supports three strategies for identifying tabs: URL matching (exact or partial URL comparison), regex matching (against the target's title, URL path, or full href), and named target matching (looking up a previously registered name in the target registry). The getCriTargets function partitions all page targets into "matching" and "others" based on these strategies, which is used by the tab-switching API.
Usage
Use TargetHandler to open new tabs, close tabs, switch between tabs, create isolated browser contexts (for incognito-like sessions), and look up targets by URL, regex, or registered name. These operations are exposed through Taiko's top-level API methods such as openTab, closeTab, switchTo, and openIncognitoWindow.
Code Reference
Source Location
Signature
async function getCriTargets(identifier) -> {matching: Array, others: Array}
function isMatchingUrl(target, identifier) -> boolean
function isMatchingRegex(target, targetRegex) -> boolean
function isMatchingTarget(target, identifier) -> boolean
function register(name, target) -> void | string
function unregister(name) -> void
function clearRegister() -> void
async function createBrowserContext(url) -> string
async function createTarget(url) -> string
async function closeTarget(targetId) -> void
async function closeBrowserContext(targetId) -> boolean
async function switchBrowserContext(targetId) -> void
async function getBrowserContextIdForTarget(targetId) -> string
async function waitForTargetToBeCreated(n) -> string
async function getFirstAvailablePageTarget() -> Array<TargetInfo>
Import
const {
getCriTargets,
isMatchingUrl,
isMatchingRegex,
isMatchingTarget,
register,
unregister,
clearRegister,
createBrowserContext,
closeBrowserContext,
switchBrowserContext,
waitForTargetToBeCreated,
createTarget,
getFirstAvailablePageTarget,
closeTarget,
} = require("./handlers/targetHandler");
I/O Contract
getCriTargets(identifier)
| Parameter |
Type |
Description
|
identifier |
RegExp | Object | undefined |
A URL string, a regex, an object with name property, or undefined (returns the active target).
|
| Return |
Type |
Description
|
{matching, others} |
Object |
matching: array of TargetInfo objects that match the identifier. others: array of remaining page targets.
|
isMatchingUrl(target, identifier)
| Parameter |
Type |
Description
|
target |
TargetInfo |
CDP target info object with url and title properties.
|
identifier |
string |
URL or page title to match against.
|
| Return |
Type |
Description
|
| result |
boolean |
true if the target matches by title, URL path, or full href.
|
register(name, target) / unregister(name)
| Parameter |
Type |
Description
|
name |
string |
User-assigned name for the target.
|
target |
string |
Target ID to associate with the name. When omitted, register acts as a getter.
|
createBrowserContext(url)
| Parameter |
Type |
Description
|
url |
string |
URL to open in the new browser context.
|
| Return |
Type |
Description
|
| targetId |
string |
The target ID of the newly created page within the new browser context.
|
closeBrowserContext(targetId)
| Parameter |
Type |
Description
|
targetId |
string |
Target ID whose browser context should be disposed.
|
| Return |
Type |
Description
|
| wasActive |
boolean |
true if the disposed context was the currently active browser context.
|
waitForTargetToBeCreated(n)
| Parameter |
Type |
Description
|
n |
number |
Maximum number of retry attempts (each with 100ms delay).
|
| Return |
Type |
Description
|
| targetId |
string |
Target ID of the first available page target.
|
| Throws |
|
When no page target is found after all retries.
|
Algorithm
URL Matching
The isMatchingUrl function normalizes both the target URL and the identifier using Node.js url.parse. It prepends http:// to identifiers missing a protocol. Matching occurs on three levels:
- Title match -- The target's title equals the HTML-escaped identifier.
- Path match -- The target's
host + pathname equals the identifier's host + pathname.
- Full href match -- The target's
parsedUrl.href exactly equals the identifier.
URL redirections are normalized by stripping trailing slashes and removing www. prefixes via handleUrlRedirection.
Regex Matching
The isMatchingRegex function tests the regex against four representations of the target:
target.title
host/pathname joined as a path
parsedUrl.href
protocol + host (URL without path)
Browser Context Lifecycle
Browser contexts provide isolation similar to incognito windows. The flow is:
createBrowserContext calls Target.createBrowserContext at the browser level.
- The returned
browserContextId becomes the active context.
createTarget creates a new page within that context.
- If context creation fails (e.g., stale context ID), the fallback creates a target without a context.
closeBrowserContext disposes the context and returns whether it was the active one.
Target Discovery and Retry
waitForTargetToBeCreated implements a retry loop with up to n attempts, each separated by 100ms. It calls getFirstAvailablePageTarget which re-establishes a browser-level CRI connection and filters for type === "page" targets. This re-connection on each call ensures fresh target data.
CDP Domain
This handler uses the Target domain with the following commands and events:
Target.setDiscoverTargets -- Enables target discovery notifications.
Target.targetCreated (event) -- Fired when a new target is created; filtered for page-type targets with an opener.
Target.getTargets -- Retrieves all known targets.
Target.getTargetInfo -- Retrieves info for a specific target, including its browser context ID.
Target.createTarget -- Creates a new page target.
Target.closeTarget -- Closes a target.
Target.createBrowserContext -- Creates a new isolated browser context.
Target.disposeBrowserContext -- Disposes an isolated browser context.
Target.activateTarget -- Brings a target to the foreground.
Usage Examples
// Find targets matching a URL
const { getCriTargets } = require("./handlers/targetHandler");
const targets = await getCriTargets("https://example.com");
// targets.matching => [{ targetId: "...", url: "https://example.com", ... }]
// Register a named tab
const { register, getCriTargets } = require("./handlers/targetHandler");
register("loginTab", targetId);
// Create an incognito-like browsing context
const { createBrowserContext } = require("./handlers/targetHandler");
const newTargetId = await createBrowserContext("https://example.com/private");
// Switch to a different browser context
const { switchBrowserContext } = require("./handlers/targetHandler");
await switchBrowserContext(targetId);
// Close a tab
const { closeTarget } = require("./handlers/targetHandler");
await closeTarget(targetId);
Related Pages