A command line tool to help build, run, and test web extensions
—
ADB integration for developing and testing extensions on Firefox for Android devices. Provides device management, file transfer, APK handling, and remote debugging capabilities.
Comprehensive Android Debug Bridge integration for Firefox extension development on mobile devices.
class ADBUtils {
constructor(params: ADBParams);
/** Discover connected Android devices */
discoverDevices(): Promise<string[]>;
/** Get current user ID on device */
getCurrentUser(deviceId: string): Promise<string>;
/** Execute shell command on device */
runShellCommand(deviceId: string, cmd: string): Promise<string>;
/** Find installed Firefox APKs on device */
discoverInstalledFirefoxAPKs(deviceId: string, firefoxApk?: string): Promise<string[]>;
/** Force stop an APK on device */
amForceStopAPK(deviceId: string, apk: string): Promise<void>;
/** Create or get artifacts directory on device */
getOrCreateArtifactsDir(deviceId: string): Promise<string>;
/** Detect or remove old artifacts from device */
detectOrRemoveOldArtifacts(deviceId: string, removeArtifactDirs?: boolean): Promise<string[]>;
/** Clear artifacts directory on device */
clearArtifactsDir(deviceId: string): Promise<void>;
/** Upload file from computer to device */
pushFile(deviceId: string, localPath: string, devicePath: string): Promise<void>;
/** Launch Firefox APK with extension */
startFirefoxAPK(deviceId: string, apk: string, apkComponent?: string, deviceProfileDir?: string): Promise<void>;
/** Control discovery abort mechanism */
setUserAbortDiscovery(value: boolean): void;
/** Discover remote debugging Unix socket */
discoverRDPUnixSocket(deviceId: string, apk: string, options?: DiscoveryOptions): Promise<string>;
/** Set up ADB port forwarding */
setupForward(deviceId: string, remote: string, local: string): Promise<void>;
}
interface ADBParams {
/** Path to adb binary */
adbBin?: string;
/** ADB host to connect to */
adbHost?: string;
/** ADB port number */
adbPort?: string;
/** Target device ID */
adbDevice?: string;
/** Discovery timeout in milliseconds */
adbDiscoveryTimeout?: number;
/** Enable verbose logging */
verbose?: boolean;
}
interface DiscoveryOptions {
/** Maximum retry attempts */
maxTries?: number;
/** Retry delay in milliseconds */
retryInterval?: number;
}Usage Examples:
import { ADBUtils } from "web-ext/util/adb";
// Initialize ADB utilities
const adb = new ADBUtils({
adbBin: '/usr/local/bin/adb',
adbDevice: 'emulator-5554',
adbDiscoveryTimeout: 30000
});
// Discover and connect to devices
const devices = await adb.discoverDevices();
console.log('Found devices:', devices);
// Upload extension to device
await adb.pushFile('emulator-5554', './extension.xpi', '/data/local/tmp/extension.xpi');
// Start Firefox with extension
await adb.startFirefoxAPK('emulator-5554', 'org.mozilla.fenix');Standalone functions for device and APK discovery without class instantiation.
/**
* List all connected ADB devices
* @param adbBin - Path to adb binary
* @returns Promise resolving to array of device IDs
*/
function listADBDevices(adbBin?: string): Promise<string[]>;
/**
* List Firefox APKs installed on a device
* @param deviceId - Target device identifier
* @param adbBin - Path to adb binary
* @returns Promise resolving to array of APK package names
*/
function listADBFirefoxAPKs(deviceId: string, adbBin?: string): Promise<string[]>;Usage Examples:
import { listADBDevices, listADBFirefoxAPKs } from "web-ext/util/adb";
// Quick device discovery
const devices = await listADBDevices();
if (devices.length === 0) {
console.log('No Android devices found');
return;
}
// Find Firefox installations
const firefoxApks = await listADBFirefoxAPKs(devices[0]);
console.log('Firefox APKs:', firefoxApks);
// Output: ['org.mozilla.firefox', 'org.mozilla.fenix', 'org.mozilla.firefox_beta']Constants and utilities for managing file paths on Android devices.
/** Base directory for temporary files on Android device */
const DEVICE_DIR_BASE: string = "/data/local/tmp/";
/** Prefix for web-ext artifact directories */
const ARTIFACTS_DIR_PREFIX: string = "web-ext-artifacts-";Set up remote debugging connections for Firefox Android extensions.
/**
* Discover and connect to Firefox remote debugging socket
* @param deviceId - Target Android device
* @param apk - Firefox APK package name
* @param options - Discovery configuration
* @returns Promise resolving to Unix socket path
*/
async function discoverRDPUnixSocket(
deviceId: string,
apk: string,
options?: DiscoveryOptions
): Promise<string>;
/**
* Set up port forwarding for remote debugging
* @param deviceId - Target device
* @param remote - Remote socket/port on device
* @param local - Local port on development machine
* @returns Promise that resolves when forwarding is established
*/
async function setupForward(
deviceId: string,
remote: string,
local: string
): Promise<void>;Usage Example:
// Set up remote debugging
const socket = await adb.discoverRDPUnixSocket('emulator-5554', 'org.mozilla.fenix', {
maxTries: 10,
retryInterval: 1000
});
// Forward remote debugging port
await adb.setupForward('emulator-5554', socket, '6000');
console.log('Remote debugging available at localhost:6000');Manage files and directories on Android devices.
/**
* Upload file from local system to Android device
* @param deviceId - Target device
* @param localPath - Source file path on computer
* @param devicePath - Destination path on device
* @returns Promise that resolves when transfer completes
*/
async function pushFile(
deviceId: string,
localPath: string,
devicePath: string
): Promise<void>;
/**
* Create artifacts directory on device
* @param deviceId - Target device
* @returns Promise resolving to created directory path
*/
async function getOrCreateArtifactsDir(deviceId: string): Promise<string>;
/**
* Clean up old artifact directories
* @param deviceId - Target device
* @param removeArtifactDirs - Whether to remove old directories
* @returns Promise resolving to list of old directories
*/
async function detectOrRemoveOldArtifacts(
deviceId: string,
removeArtifactDirs?: boolean
): Promise<string[]>;Handle Firefox APK operations on Android devices.
/**
* Force stop a running APK
* @param deviceId - Target device
* @param apk - APK package name to stop
* @returns Promise that resolves when APK is stopped
*/
async function amForceStopAPK(deviceId: string, apk: string): Promise<void>;
/**
* Launch Firefox APK with optional extension
* @param deviceId - Target device
* @param apk - Firefox APK package name
* @param apkComponent - Specific APK component (optional)
* @param deviceProfileDir - Profile directory on device (optional)
* @returns Promise that resolves when APK is started
*/
async function startFirefoxAPK(
deviceId: string,
apk: string,
apkComponent?: string,
deviceProfileDir?: string
): Promise<void>;Firefox APK Examples:
org.mozilla.firefox - Firefox Releaseorg.mozilla.firefox_beta - Firefox Betaorg.mozilla.fenix - Firefox Nightlyorg.mozilla.fenix.nightly - Firefox Nightly (alternative)org.mozilla.fennec_aurora - Firefox Developer Edition (legacy)Execute arbitrary shell commands on Android devices.
/**
* Execute shell command on Android device
* @param deviceId - Target device identifier
* @param cmd - Shell command to execute
* @returns Promise resolving to command output
*/
async function runShellCommand(deviceId: string, cmd: string): Promise<string>;
/**
* Get current user ID on Android device
* @param deviceId - Target device
* @returns Promise resolving to user ID string
*/
async function getCurrentUser(deviceId: string): Promise<string>;Usage Examples:
// Check device storage
const storage = await adb.runShellCommand('emulator-5554', 'df -h');
console.log('Device storage:', storage);
// Get device info
const userInfo = await adb.getCurrentUser('emulator-5554');
console.log('Current user:', userInfo);
// Check running processes
const processes = await adb.runShellCommand('emulator-5554', 'ps | grep firefox');
console.log('Firefox processes:', processes);Common error scenarios and solutions:
interface ADBError extends Error {
/** ADB-specific error code */
code: string;
/** Device ID where error occurred */
deviceId?: string;
/** ADB command that failed */
command?: string;
}Common Error Codes:
DEVICE_NOT_FOUND - Device not connected or not recognizedADB_NOT_FOUND - ADB binary not found in PATHPERMISSION_DENIED - Insufficient permissions for device accessTIMEOUT - Operation timed outAPK_NOT_FOUND - Firefox APK not installed on deviceCONNECTION_FAILED - Cannot establish ADB connectionUsage Example with Error Handling:
try {
const adb = new ADBUtils({
adbDevice: 'emulator-5554',
adbDiscoveryTimeout: 30000
});
const devices = await adb.discoverDevices();
if (devices.length === 0) {
throw new Error('No Android devices found. Please connect a device or start an emulator.');
}
await adb.startFirefoxAPK(devices[0], 'org.mozilla.fenix');
console.log('Firefox started successfully on device');
} catch (error) {
if (error.code === 'DEVICE_NOT_FOUND') {
console.error('Device not found. Check USB debugging is enabled.');
} else if (error.code === 'APK_NOT_FOUND') {
console.error('Firefox not installed. Install Firefox from Play Store or APK.');
} else {
console.error('ADB operation failed:', error.message);
}
}ADB utilities integrate seamlessly with web-ext's extension runner system:
// Android-specific run parameters
await cmd.run({
sourceDir: './extension',
target: ['firefox-android'],
adbDevice: 'emulator-5554',
firefoxApk: 'org.mozilla.fenix',
adbRemoveOldArtifacts: true
});This automatically uses ADBUtils internally to:
Install with Tessl CLI
npx tessl i tessl/npm-web-ext