CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-devtools-protocol

Complete Chrome DevTools Protocol JSON definitions and TypeScript types for building debugging tools and browser automation

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

browser-page-control.mddocs/

Browser and Page Control

Browser-level operations, page navigation, lifecycle management, and target control. This covers domains that manage browser windows, page navigation, and debugging target management.

Capabilities

Browser Domain

Browser-level operations and window management for controlling browser instances and sessions.

namespace Protocol.Browser {
  type BrowserContextID = string;
  type WindowID = integer;
  type WindowState = ('normal' | 'minimized' | 'maximized' | 'fullscreen');

  interface GetVersionResponse {
    protocolVersion: string;
    product: string;
    revision: string;
    userAgent: string;
    jsVersion: string;
  }

  interface GetBrowserContextsResponse {
    browserContextIds: BrowserContextID[];
  }

  interface CreateBrowserContextRequest {
    disposeOnDetach?: boolean;
    proxyServer?: string;
    proxyBypassList?: string;
    originsWithUniversalNetworkAccess?: string[];
  }

  interface CreateBrowserContextResponse {
    browserContextId: BrowserContextID;
  }

  interface GetWindowBoundsRequest {
    windowId: WindowID;
  }

  interface GetWindowBoundsResponse {
    bounds: Bounds;
  }

  interface SetWindowBoundsRequest {
    windowId: WindowID;
    bounds: Bounds;
  }

  interface Bounds {
    left?: integer;
    top?: integer;
    width?: integer;
    height?: integer;
    windowState?: WindowState;
  }

  interface GetWindowForTargetRequest {
    targetId?: Target.TargetID;
  }

  interface GetWindowForTargetResponse {
    windowId: WindowID;
    bounds: Bounds;
  }
}

Usage Example:

import Protocol from "devtools-protocol/types/protocol";

// Get browser version information
function getBrowserInfo(): Promise<Protocol.Browser.GetVersionResponse> {
  // Implementation would send Browser.getVersion command
  return Promise.resolve({
    protocolVersion: "1.3",
    product: "Chrome/91.0.4472.124",
    revision: "@abc123",
    userAgent: "Mozilla/5.0...",
    jsVersion: "9.1.269.38"
  });
}

// Create isolated browser context
const createContextRequest: Protocol.Browser.CreateBrowserContextRequest = {
  disposeOnDetach: true,
  proxyServer: "http://proxy.example.com:8080"
};

// Manage window bounds
const windowBounds: Protocol.Browser.Bounds = {
  left: 100,
  top: 100,
  width: 1200,
  height: 800,
  windowState: 'normal'
};

Page Domain

Page-level operations including navigation, lifecycle management, and resource handling.

namespace Protocol.Page {
  type FrameId = string;
  type LoaderId = string;
  type NavigationId = string;
  type TransitionType = ('link' | 'typed' | 'address_bar' | 'auto_bookmark' | 'auto_subframe' | 'manual_subframe' | 'generated' | 'auto_toplevel' | 'form_submit' | 'reload' | 'keyword' | 'keyword_generated' | 'other');
  type ReferrerPolicy = ('noReferrer' | 'noReferrerWhenDowngrade' | 'origin' | 'originWhenCrossOrigin' | 'sameOrigin' | 'strictOrigin' | 'strictOriginWhenCrossOrigin' | 'unsafeUrl');

  interface Frame {
    id: FrameId;
    parentId?: string;
    loaderId: LoaderId;
    name?: string;
    url: string;
    urlFragment?: string;
    domainAndRegistry: string;
    securityOrigin: string;
    mimeType: string;
    unreachableUrl?: string;
    adFrameStatus?: AdFrameStatus;
    secureContextType: SecureContextType;
    crossOriginIsolatedContextType: CrossOriginIsolatedContextType;
    gatedAPIFeatures: GatedAPIFeatures[];
  }

  interface NavigateRequest {
    url: string;
    referrer?: string;
    transitionType?: TransitionType;
    frameId?: FrameId;
    referrerPolicy?: ReferrerPolicy;
  }

  interface NavigateResponse {
    frameId: FrameId;
    loaderId?: LoaderId;
    errorText?: string;
  }

  interface ReloadRequest {
    ignoreCache?: boolean;
    scriptToEvaluateOnLoad?: string;
    loaderId?: LoaderId;
  }

  interface GetResourceTreeResponse {
    frameTree: FrameResourceTree;
  }

  interface FrameResourceTree {
    frame: Frame;
    childFrames?: FrameResourceTree[];
    resources: FrameResource[];
  }

  interface FrameResource {
    url: string;
    type: Network.ResourceType;
    mimeType: string;
    lastModified?: Network.TimeSinceEpoch;
    contentSize?: integer;
    failed?: boolean;
    canceled?: boolean;
  }

  interface DomContentEventFiredEvent {
    timestamp: Network.MonotonicTime;
  }

  interface LoadEventFiredEvent {
    timestamp: Network.MonotonicTime;
  }

  interface FrameNavigatedEvent {
    frame: Frame;
    type: NavigationType;
  }

  interface FrameStartedLoadingEvent {
    frameId: FrameId;
  }

  interface FrameStoppedLoadingEvent {
    frameId: FrameId;
  }

  interface LifecycleEvent {
    frameId: FrameId;
    loaderId: LoaderId;
    name: string;
    timestamp: Network.MonotonicTime;
  }
}

Usage Example:

import Protocol from "devtools-protocol/types/protocol";

// Navigate to a URL
const navigateRequest: Protocol.Page.NavigateRequest = {
  url: "https://example.com",
  referrerPolicy: 'origin',
  transitionType: 'typed'
};

// Handle page lifecycle events
function onDomContentLoaded(event: Protocol.Page.DomContentEventFiredEvent) {
  console.log("DOM content loaded at:", event.timestamp);
}

function onPageLoaded(event: Protocol.Page.LoadEventFiredEvent) {
  console.log("Page fully loaded at:", event.timestamp);
}

function onFrameNavigated(event: Protocol.Page.FrameNavigatedEvent) {
  console.log(`Frame navigated to: ${event.frame.url}`);
}

// Get page resource tree
function analyzePageResources(resourceTree: Protocol.Page.FrameResourceTree) {
  console.log(`Main frame: ${resourceTree.frame.url}`);
  console.log(`Resources: ${resourceTree.resources.length}`);
  
  resourceTree.resources.forEach(resource => {
    console.log(`- ${resource.url} (${resource.type}, ${resource.mimeType})`);
  });
  
  if (resourceTree.childFrames) {
    resourceTree.childFrames.forEach(childFrame => {
      analyzePageResources(childFrame);
    });
  }
}

Target Domain

Debug target management and discovery for controlling multiple debugging contexts.

namespace Protocol.Target {
  type TargetID = string;
  type SessionID = string;
  type BrowserContextID = string;

  interface TargetInfo {
    targetId: TargetID;
    type: string;
    title: string;
    url: string;
    attached: boolean;
    openerId?: TargetID;
    canAccessOpener: boolean;
    openerFrameId?: Page.FrameId;
    browserContextId?: BrowserContextID;
    subtype?: string;
  }

  interface CreateTargetRequest {
    url: string;
    width?: integer;
    height?: integer;
    browserContextId?: BrowserContextID;
    enableBeginFrameControl?: boolean;
    newWindow?: boolean;
    background?: boolean;
    forTab?: boolean;
  }

  interface CreateTargetResponse {
    targetId: TargetID;
  }

  interface AttachToTargetRequest {
    targetId: TargetID;
    flatten?: boolean;
  }

  interface AttachToTargetResponse {
    sessionId: SessionID;
  }

  interface DetachFromTargetRequest {
    sessionId?: SessionID;
    targetId?: TargetID;
  }

  interface GetTargetsResponse {
    targetInfos: TargetInfo[];
  }

  interface CreateBrowserContextRequest {
    disposeOnDetach?: boolean;
    proxyServer?: string;
    proxyBypassList?: string;
    originsWithUniversalNetworkAccess?: string[];
  }

  interface CreateBrowserContextResponse {
    browserContextId: BrowserContextID;
  }

  interface TargetCreatedEvent {
    targetInfo: TargetInfo;
  }

  interface TargetDestroyedEvent {
    targetId: TargetID;
  }

  interface TargetCrashedEvent {
    targetId: TargetID;
    status: string;
    errorCode: integer;
  }

  interface TargetInfoChangedEvent {
    targetInfo: TargetInfo;
  }

  interface AttachedToTargetEvent {
    sessionId: SessionID;
    targetInfo: TargetInfo;
    waitingForDebugger: boolean;
  }

  interface DetachedFromTargetEvent {
    sessionId: SessionID;
    targetId?: TargetID;
  }
}

Usage Example:

import Protocol from "devtools-protocol/types/protocol";

// Create a new target (tab/window)
const createTargetRequest: Protocol.Target.CreateTargetRequest = {
  url: "about:blank",
  width: 1024,
  height: 768,
  newWindow: false,
  background: false
};

// Attach to a target for debugging
async function attachToTarget(targetId: string): Promise<string> {
  const attachRequest: Protocol.Target.AttachToTargetRequest = {
    targetId,
    flatten: true
  };
  
  // Would return session ID for further communication
  return "session_id_123";
}

// Handle target lifecycle events
function onTargetCreated(event: Protocol.Target.TargetCreatedEvent) {
  const { targetInfo } = event;
  console.log(`New target created: ${targetInfo.title} (${targetInfo.url})`);
}

function onTargetDestroyed(event: Protocol.Target.TargetDestroyedEvent) {
  console.log(`Target destroyed: ${event.targetId}`);
}

function onTargetCrashed(event: Protocol.Target.TargetCrashedEvent) {
  console.error(`Target crashed: ${event.targetId}, status: ${event.status}`);
}

// Manage multiple targets
async function listAllTargets(): Promise<Protocol.Target.TargetInfo[]> {
  // Implementation would call Target.getTargets
  return [
    {
      targetId: "target_1",
      type: "page",
      title: "Example Page",
      url: "https://example.com",
      attached: true,
      canAccessOpener: false
    }
  ];
}

Inspector Domain

Inspector connection and session management for controlling debugging sessions.

namespace Protocol.Inspector {
  interface DetachedEvent {
    reason: string;
  }

  interface TargetCrashedEvent {}

  interface TargetReloadedAfterCrashEvent {}
}

Common Usage Patterns

Browser Session Management

import Protocol from "devtools-protocol/types/protocol";

class BrowserSessionManager {
  private contexts: Map<string, Protocol.Browser.BrowserContextID> = new Map();
  private targets: Map<string, Protocol.Target.TargetID> = new Map();

  async createIsolatedContext(name: string): Promise<Protocol.Browser.BrowserContextID> {
    const request: Protocol.Browser.CreateBrowserContextRequest = {
      disposeOnDetach: true
    };
    
    // Implementation would send Browser.createBrowserContext
    const response = { browserContextId: `context_${name}` };
    this.contexts.set(name, response.browserContextId);
    return response.browserContextId;
  }

  async createTabInContext(contextId: Protocol.Browser.BrowserContextID, url: string): Promise<Protocol.Target.TargetID> {
    const request: Protocol.Target.CreateTargetRequest = {
      url,
      browserContextId: contextId,
      newWindow: false,
      background: false
    };
    
    // Implementation would send Target.createTarget
    const response = { targetId: `target_${Date.now()}` };
    this.targets.set(url, response.targetId);
    return response.targetId;
  }

  async navigateTarget(targetId: Protocol.Target.TargetID, url: string): Promise<void> {
    const request: Protocol.Page.NavigateRequest = {
      url
    };
    
    // Implementation would send Page.navigate to the target
  }
}

Page Navigation and Lifecycle

import Protocol from "devtools-protocol/types/protocol";
import { ProtocolMapping } from "devtools-protocol/types/protocol-mapping";

class PageManager {
  private frameTree: Protocol.Page.FrameResourceTree | null = null;
  
  setupPageListeners() {
    // Handle navigation events
    this.onFrameNavigated = (event: ProtocolMapping.Events['Page.frameNavigated'][0]) => {
      console.log(`Navigation: ${event.frame.url}`);
      this.updateFrameTree();
    };
    
    // Handle lifecycle events
    this.onLifecycleEvent = (event: ProtocolMapping.Events['Page.lifecycleEvent'][0]) => {
      console.log(`Lifecycle: ${event.name} for frame ${event.frameId}`);
    };
    
    // Handle load events
    this.onLoadEventFired = (event: ProtocolMapping.Events['Page.loadEventFired'][0]) => {
      console.log(`Page loaded at: ${event.timestamp}`);
    };
  }

  async reloadPage(ignoreCache: boolean = false): Promise<void> {
    const request: Protocol.Page.ReloadRequest = {
      ignoreCache,
      scriptToEvaluateOnLoad: "console.log('Page reloaded');"
    };
    
    // Implementation would send Page.reload
  }

  private async updateFrameTree(): Promise<void> {
    // Implementation would call Page.getResourceTree
    this.frameTree = {
      frame: {
        id: "main_frame",
        loaderId: "loader_123",
        url: "https://example.com",
        domainAndRegistry: "example.com",
        securityOrigin: "https://example.com",
        mimeType: "text/html",
        secureContextType: "Secure",
        crossOriginIsolatedContextType: "NotIsolated",
        gatedAPIFeatures: []
      },
      resources: []
    };
  }
}

Multi-Target Debugging

import Protocol from "devtools-protocol/types/protocol";

class MultiTargetDebugger {
  private sessions: Map<Protocol.Target.SessionID, Protocol.Target.TargetInfo> = new Map();

  async attachToAllTargets(): Promise<void> {
    // Get all available targets
    const targets = await this.getAllTargets();
    
    for (const target of targets) {
      if (target.type === 'page' && !target.attached) {
        const sessionId = await this.attachToTarget(target.targetId);
        this.sessions.set(sessionId, target);
        
        // Enable debugging for this target
        await this.enableDebuggingForSession(sessionId);
      }
    }
  }

  private async getAllTargets(): Promise<Protocol.Target.TargetInfo[]> {
    // Implementation would call Target.getTargets
    return [];
  }

  private async attachToTarget(targetId: Protocol.Target.TargetID): Promise<Protocol.Target.SessionID> {
    const request: Protocol.Target.AttachToTargetRequest = {
      targetId,
      flatten: true
    };
    
    // Implementation would send Target.attachToTarget
    return `session_${Date.now()}`;
  }

  private async enableDebuggingForSession(sessionId: Protocol.Target.SessionID): Promise<void> {
    // Enable domains for this session
    // Implementation would send commands to the specific session
  }

  handleTargetEvents() {
    this.onTargetCreated = (event: Protocol.Target.TargetCreatedEvent) => {
      console.log(`New target: ${event.targetInfo.title}`);
      // Automatically attach to new targets if needed
    };

    this.onTargetDestroyed = (event: Protocol.Target.TargetDestroyedEvent) => {
      console.log(`Target destroyed: ${event.targetId}`);
      // Clean up session if it exists
      for (const [sessionId, targetInfo] of this.sessions.entries()) {
        if (targetInfo.targetId === event.targetId) {
          this.sessions.delete(sessionId);
          break;
        }
      }
    };
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-devtools-protocol

docs

advanced-web-features.md

browser-page-control.md

core-debugging.md

device-testing.md

dom-styling.md

index.md

network-performance.md

storage-data.md

tile.json