Table of Contents

Permissions Module

The Permissions module allows you to manage browser permissions for features like geolocation, notifications, and camera access.

Overview

The Permissions module allows you to:

  • Grant or deny browser permissions
  • Manage geolocation, notifications, camera, and microphone permissions
  • Control permission prompts
  • Test permission-dependent functionality

Accessing the Module

PermissionsModule permissions = driver.Permissions;

Timeout and Cancellation

All commands in this module accept optional timeoutOverride and CancellationToken parameters. Use timeoutOverride to set a per-command timeout (defaults to BiDiDriver.DefaultCommandTimeout when omitted). Use CancellationToken for cooperative cancellation. See the API Design Guide for details and examples.

Setting Permissions

Grant Geolocation Permission

SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("geolocation"),
    PermissionState.Granted,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);
Console.WriteLine("Geolocation permission granted");

Deny Permission

SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("geolocation"),
    PermissionState.Denied,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);
Console.WriteLine("Geolocation permission denied");

Permission Types

Notifications

SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("notifications"),
    PermissionState.Granted,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);

Camera

SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("camera"),
    PermissionState.Granted,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);

Microphone

SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("microphone"),
    PermissionState.Granted,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);

MIDI

SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("midi"),
    PermissionState.Granted,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);

Permission States

Permissions can be set to three states:

  • PermissionState.Granted - Permission is granted
  • PermissionState.Denied - Permission is denied
  • PermissionState.Prompt - User will be prompted
// Set permission to prompt user
SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("notifications"),
    PermissionState.Prompt,
    "https://example.com");

await driver.Permissions.SetPermissionAsync(@params);

Common Patterns

Testing Geolocation Functionality

// Grant geolocation permission
SetPermissionCommandParameters permParams = new SetPermissionCommandParameters(
    new PermissionDescriptor("geolocation"),
    PermissionState.Granted,
    "https://example.com");
await driver.Permissions.SetPermissionAsync(permParams);

// Set location
SetGeolocationOverrideCoordinatesCommandParameters geoParams =
    new SetGeolocationOverrideCoordinatesCommandParameters
    {
        Coordinates = new GeolocationCoordinates(37.7749, -122.4194) { Accuracy = 100 },
        Contexts = { contextId }
    };
await driver.Emulation.SetGeolocationOverrideAsync(geoParams);

// Test location access
EvaluateResult result = await driver.Script.EvaluateAsync(
    new EvaluateCommandParameters(
        @"new Promise((resolve) => {
            navigator.geolocation.getCurrentPosition(
                (pos) => resolve(`${pos.coords.latitude},${pos.coords.longitude}`),
                (err) => resolve(`Error: ${err.message}`)
            );
        })",
        new ContextTarget(contextId),
        true));

if (result is EvaluateResultSuccess success &&
    success.Result is StringRemoteValue locationValue)
{
    string location = locationValue.Value;
    Console.WriteLine($"Location: {location}");
}

Testing Notification Permissions

// Grant notification permission
SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("notifications"),
    PermissionState.Granted,
    "https://example.com");
await driver.Permissions.SetPermissionAsync(@params);

// Navigate to page
await driver.BrowsingContext.NavigateAsync(
    new NavigateCommandParameters(contextId, "https://example.com")
    { Wait = ReadinessState.Complete });

// Check permission state in page
EvaluateResult result = await driver.Script.EvaluateAsync(
    new EvaluateCommandParameters(
        "Notification.permission",
        new ContextTarget(contextId),
        true));

if (result is EvaluateResultSuccess success &&
    success.Result is StringRemoteValue permissionValue)
{
    string permissionState = permissionValue.Value;
    Console.WriteLine($"Notification permission: {permissionState}");
}

Testing Permission Denial

// Deny camera permission
SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
    new PermissionDescriptor("camera"),
    PermissionState.Denied,
    "https://example.com");
await driver.Permissions.SetPermissionAsync(@params);

// Try to access camera - should fail
EvaluateResult result = await driver.Script.EvaluateAsync(
    new EvaluateCommandParameters(
        @"navigator.mediaDevices.getUserMedia({ video: true })
            .then(() => 'granted')
            .catch(err => `denied: ${err.name}`)",
        new ContextTarget(contextId),
        true));

if (result is EvaluateResultSuccess success &&
    success.Result is StringRemoteValue accessValue)
{
    string accessResult = accessValue.Value;
    Console.WriteLine($"Camera access: {accessResult}");
}

Testing Multiple Permissions

// Grant multiple permissions
string[] permissionTypes = { "camera", "microphone" };

foreach (string permType in permissionTypes)
{
    SetPermissionCommandParameters @params = new SetPermissionCommandParameters(
        new PermissionDescriptor(permType),
        PermissionState.Granted,
        "https://example.com");
    await driver.Permissions.SetPermissionAsync(@params);
}

// Test accessing both camera and microphone
EvaluateResult result = await driver.Script.EvaluateAsync(
    new EvaluateCommandParameters(
        @"navigator.mediaDevices.getUserMedia({ video: true, audio: true })
            .then(() => 'both granted')
            .catch(err => `error: ${err.name}`)",
        new ContextTarget(contextId),
        true));

if (result is EvaluateResultSuccess success &&
    success.Result is StringRemoteValue accessValue)
{
    string accessResult = accessValue.Value;
    Console.WriteLine($"Media access: {accessResult}");
}

Available Permission Names

Common permission descriptor names:

  • "geolocation" - Location services
  • "notifications" - Push notifications
  • "camera" - Camera access
  • "microphone" - Microphone access
  • "midi" - MIDI device access
  • "background-sync" - Background sync
  • "clipboard-read" - Clipboard read access
  • "clipboard-write" - Clipboard write access
  • "persistent-storage" - Persistent storage quota

Note: Available permissions vary by browser and version.

Some permissions define descriptor members beyond the name — for example, "midi" supports a sysex member and "camera" supports panTiltZoom. Add such members via PermissionDescriptor.AdditionalData (for example, descriptor.AdditionalData["sysex"] = true) and they are serialized as additional members of the descriptor object.

Browser Support

Browser Support Level
Chrome/Edge ✅ Full support
Firefox ✅ Full support
Safari ⚠️ Limited support

Best Practices

  1. Set permissions before navigation: Set permissions before navigating to the page that needs them
  2. Reset permissions between tests: Return each permission to PermissionState.Prompt to ensure test isolation (there is no separate clear command)
  3. Test both granted and denied states: Verify your application handles both cases correctly
  4. Combine with emulation: Use with Emulation module for location testing
  5. Handle errors gracefully: Not all permissions are available in all browsers

Common Issues

Permissions Not Taking Effect

Problem: Permission changes don't apply to the page.

Solution:

  • Set permissions before navigating to the page
  • Refresh the page after changing permissions
  • Ensure you're using the correct permission name

Permission Not Supported

Problem: Module throws "not supported" errors.

Solution:

  • Check browser version and compatibility
  • Enable experimental features if required
  • Verify the permission type is available in your browser

Permission Persists Between Tests

Problem: Permission state carries over to next test.

Solution:

  • Reset permissions to PermissionState.Prompt after each test
  • Use isolated user contexts for test isolation, scoping the permission to one via SetPermissionCommandParameters.UserContextId
  • Clear browser state between test runs

Invalid Permission Name

Problem: Permission descriptor name not recognized.

Solution:

  • Use standard permission names from the Permissions API
  • Check browser documentation for supported permission names
  • Test permission name in browser console first

Next Steps

Further Reading