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:
- Button presses are off by one - if PHONE_KEY_1 is pressed by the user, PHONE_KEY_2 will be reported, and so on.
- PHONE_KEY_0 will be reported when the user stops pressing any buttons.
- PHONE_KEY_POUND will never be reported.
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.
- browser and version support is documented by caniuse.com.
- security and privacy considerations are documented by the Web Platform Incubator Community Group.
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 thedeviceAdded
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 validDeviceType
property and compatible with runtime components falling back to WebHIDDue 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>