Appendix

Additional details

All Jabra devices have complex firmware that can handle many different scenarios. This means that depending on the device's context, sending a command can have different effects.

For example, if you send a Mute command to a device but it does not consider itself in a call, the command has no effect.

Similarly, if the user indicates they want to mute the headset, but the device is not in a call state, a mute signal is not sent from the device to the computer.

Special case (Number pad)

Some devices come with a numeric keyboard for easier dialing, dealing with automated answering systems, or call forwarding. Examples include Jabra Dial 550 and Jabra Pro 9470.

If you use the Browser Extensions transport instead of WebHID, you should be aware that these buttons do not work correctly on Mac OS and Linux. This is due to known issues with Human Interface Devices (HID).

The result is as follows:

About WebHID API

The WebHID API enables web browser applications to communicate directly with USB-connected devices over the HID-protocol. It is enabled by default in Chromium-based browsers.

Using WebHID to access Jabra devices

By default, the Jabra library attempts to use the runtime components when communicating with headsets.

Instead, using WebHID as your exclusive transport method lets you develop call-control capable applications without installing runtime components on every computer running your application.

Implications on choosing between transport methods is detailed in Connecting and managing devices requires end-user consent.

End-users that do not install the runtime components are channeled automatically through the substitute transport method, using the WebHID API.

Caveats when using WebHID

Although the WebHID specification facilitates access to Jabra devices from browser-based applications, the API comes with inherent technical restrictions that limit the use of advanced features.

Initializing the Jabra library using WebHID requires you to consider the following caveats:

Limitations with devices

  • Dial tone and redial functionalities cannot be triggered directly from a Jabra device

  • End-user consent is required before a device can communicate through the WebHID API

  • Child devices connected through a Jabra Bluetooth dongle or Jabra deskstand do not display in the IDevice interface, as they do not emit the deviceAdded observable.

As elaborated in Connecting and managing devices, only devices with a direct USB connection (parent devices) are discoverable (e.g., the dongle, Jabra Link 380 instead of the headset, Jabra Evolve2 85)

Considerations with devices

  • When using WebHID, the Jabra library always reports the device type as OTHER. OTHER is a valid DeviceType property and compatible with runtime components falling back to WebHID

  • Due to security concerns in the WebHID specification, for a Jabra device, its Device ID differs across multiple browser tabs. When setting event listeners to manage devices, a variable DeviceId mitigates malicious access, but affects your reporting

Limitations with application co-existence

  • The Preferred Softphone feature in Jabra Direct cannot communicate with WebHID; consequently, an end-user cannot choose your web application as their default application

  • Acquiring a call lock intends to lock a Jabra device to an application. However, when using WebHID as the chosen transport method, there are technical limitations with the Web Locks standard that inhibit application co-existence.

Behind the scenes, the WebHID transport uses the Web Locks API, which is limited to locking applications on the same domain name and browser. Consequently, other applications can interfere with a Jabra device.

Connecting and managing devices requires end-user consent

An intricacy when using WebHID, due to security and privacy protocols, requires consent from end-users before your browser-based application can access Jabra devices.

This consent is granted via a user action on a visible UI element (e.g., clicking a button); attempting to grant consent programmatically results in an exception.

Once an end-user connects a new device, the device only appears if consent was previously granted to the specific device.

The Jabra library provides an access point for the necessary consent via the webHidPairing helper function. However, your browser-based application must use it only as a response to user interaction with your application (e.g., clicking a Start call button).

Transport method set to runtime components with WebHID as the fallback

Since the transport method is only known at runtime, be aware that choosing the CHROME_EXTENSION_WITH_WEB_HID_FALLBACK method can increase the complexity of your integration.

For example, you must only show the consent button when the transport method is falling back to WebHID as the runtime components are unavailable.

As shown in the code sample in Contingency installation -- WebHID fallback, you must explicitly add an if statement to trigger the end-user consent if the transport in use at runtime is WebHID.

Compared to WEB_HID only, the only difference for the integration is the inclusion of an if statement.

Discovering devices

Once the end-user gives consent, the Jabra device connection triggers an event as a new IDevice is emitted on the deviceAdded observable. Moreover, a new set of connected devices is emitted on the deviceList observable, letting you manage your Jabra devices..

Module Import Strategies

In addition to the strategies listed in Initializing the core module, there are three additional ways of importing modules in JavaScript. The ECMAScript import-syntax is the default way of loading the jabra-js library and is supported in both Node and Chromium browsers.

The jabra-js codebase is very similar to use in Node and the browser, and unless stated otherwise, APIs are available in both contexts. To avoid importing unnecessary code, Jabra provides different bundles for Node and the browser.

The ECMAScript import syntax (no bundling) is the preferred importing option in both Node and the browser. However, most third-party tooling does not offer full support for the native implementations of the ECMAScript specification.

In many cases, you would need a bundler or transpiler, and these tools favor the ECMAScript module (browser with a bundler) and CommonJS module (Node) options.

ECMAScript module (browser without a bundler)

Chromium-based browsers support the ECMAScript import syntax natively. However, it has a few caveats compared to what you may be used to if transpiling code via a bundler.

Firstly, the script tag must have the type="module" attribute. Secondly, the import path must point to the actual JavaScript file, including the file extension.

The same applies for node_modules, which do not resolve automatically as if the script was bundled.

See the following code sample.

// index.js

import { init } from './node_modules/@gnaudio/jabra-js/browser-esm/index.js'; // Note the explicit .js file extension

init().then((api) => {
  // Library initialized...
});
<!-- index.html -->

<html>
  <head>
    <script src="index.js" type="module"></script>
  </head>
</html>

** UMD module (browser)**

An additional importing option is through a Unified Module Definition (UMD) build. This format is useful if you load the library directly on a website through a script tag.

The UMD format protects the global namespace by collecting all package exports under jabra.

See the following code sample.

<html>
  <head>
    <script src="./node_modules/@gnaudio/jabra-js/browser-umd/index.js"\></script>

    <script>
      // The module will be loaded into global scope as `jabra`
      jabra.init().then((api) => {
      // Library initialized...
    });
    </script>
  </head>
</html>

ECMAScript module (Node)

Version 13.0 or later of Node.js natively supports the ECMAScript syntax. To use this import strategy, you must add the "type": "module" to your package.json file.

However, be aware that other third-party vendors may not support it, so it is essential that you check dependency compatibility before choosing this importing option.

Like the browser importing option, the module needs to point to the index.js file, however, Node can resolve the node_modules path as follows:

import { init } from '@gnaudio/jabra-js/node-esm/index.js'

Namespaces

Be aware that the ECMAScript format offers an easy syntax for handling namespaces, so if the jabra-js names clash with the namespace of your app, you can use the import-as syntax in the following two ways:

import { init as jabraInit } from '@gnaudio/jabra-js';

or

import * as jabra from '@gnaudio/jabra-js';

iframe

If you load the library in an iframe from another domain, and you want to use the WebHID transport method, then hid must be added to the allow property as follows:

<iframe src="https://example.com..." allow="hid"></iframe>