@webex/internal-plugin-device 2.4.2 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/device.js CHANGED
@@ -394,14 +394,17 @@ var Device = _webexCore.WebexPlugin.extend((_dec = (0, _webexCore.waitForValue)(
394
394
 
395
395
 
396
396
  delete body.features;
397
- delete body.mediaCluster; // Append a ttl value if the device is marked as ephemeral.
397
+ delete body.mediaCluster;
398
+ delete body.etag; // Append a ttl value if the device is marked as ephemeral.
398
399
 
399
400
  if (_this.config.ephemeral) {
400
401
  body.ttl = _this.config.ephemeralDeviceTTL;
401
402
  } // Merge header configurations, overriding defaults.
402
403
 
403
404
 
404
- var headers = _objectSpread(_objectSpread({}, _this.config.defaults.headers ? _this.config.defaults.headers : {}), _this.config.headers ? _this.config.headers : {});
405
+ var headers = _objectSpread(_objectSpread(_objectSpread({}, _this.config.defaults.headers ? _this.config.defaults.headers : {}), _this.config.headers ? _this.config.headers : {}), _this.etag ? {
406
+ 'If-None-Match': _this.etag
407
+ } : {});
405
408
 
406
409
  return _this.request({
407
410
  method: 'PUT',
@@ -628,9 +631,26 @@ var Device = _webexCore.WebexPlugin.extend((_dec = (0, _webexCore.waitForValue)(
628
631
 
629
632
 
630
633
  delete body.services;
631
- delete body.serviceHostMap; // Assign the recieved DTO from **WDM** to this device.
634
+ delete body.serviceHostMap;
635
+ var etag = response.headers.etag;
632
636
 
633
- this.set(body); // Validate if device is ephemeral and setup refresh timer.
637
+ if (this.etag && this.etag === etag) {
638
+ // If current etag matches the previous one and we have sent
639
+ // If-None-Match header the developer and entitlement feature
640
+ // toggles will not be returned
641
+ var features = body.features;
642
+ delete body.features; // When using the etag feature cache, user and entitlement features are still returned
643
+
644
+ this.features.user.reset(features.user);
645
+ this.features.entitlement.reset(features.entitlement);
646
+ } // Assign the recieved DTO from **WDM** to this device.
647
+
648
+
649
+ this.set(body); // Assign the new etag to this device.
650
+
651
+ this.set({
652
+ etag: etag
653
+ }); // Validate if device is ephemeral and setup refresh timer.
634
654
 
635
655
  if (this.config.ephemeral) {
636
656
  this.logger.info('device: enqueuing device refresh');
@@ -772,7 +792,7 @@ var Device = _webexCore.WebexPlugin.extend((_dec = (0, _webexCore.waitForValue)(
772
792
  }
773
793
  /* eslint-enable require-jsdoc */
774
794
  ,
775
- version: "2.4.2"
795
+ version: "2.7.0"
776
796
  }, ((0, _applyDecoratedDescriptor2.default)(_obj, "refresh", [_common.oneFlight, _dec], (0, _getOwnPropertyDescriptor.default)(_obj, "refresh"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "register", [_common.oneFlight, _dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "register"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "unregister", [_common.oneFlight, _dec3], (0, _getOwnPropertyDescriptor.default)(_obj, "unregister"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "markUrlFailedAndGetNew", [_dec4], (0, _getOwnPropertyDescriptor.default)(_obj, "markUrlFailedAndGetNew"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "initialize", [_dec5], (0, _getOwnPropertyDescriptor.default)(_obj, "initialize"), _obj)), _obj)));
777
797
 
778
798
  var _default = Device;
@@ -1 +1 @@
1
- {"version":3,"names":["decider","config","ephemeral","Device","WebexPlugin","extend","namespace","extraProperties","idAttribute","children","features","FeaturesModel","props","clientMessagingGiphy","customerCompanyName","customerLogoUrl","deviceType","helpUrl","intranetInactivityDuration","intranetInactivityCheckUrl","inNetworkInactivityDuration","ecmEnabledForAllUsers","ecmSupportedStorageProviders","modificationTime","navigationBarColor","partnerCompanyName","partnerLogoUrl","peopleInsightsEnabled","reportingSiteDesc","reportingSiteUrl","searchEncryptionKeyUrl","showSupportText","supportProviderCompanyName","supportProviderLogoUrl","url","userId","webFileShareControl","webSocketUrl","whiteboardFileShareControl","derived","registered","deps","fn","session","logoutTimer","lastUserActivityDate","isReachabilityChecked","isInMeeting","isInNetwork","meetingStarted","webex","trigger","meetingEnded","refresh","logger","info","canRegister","then","register","body","serialize","mediaCluster","ttl","ephemeralDeviceTTL","headers","defaults","request","method","uri","response","processRegistrationSuccess","catch","reason","statusCode","clear","reject","service","resource","internal","metrics","submitClientMetrics","METRICS","JS_SDK_WDM_REGISTRATION_SUCCESSFUL","error","JS_SDK_WDM_REGISTRATION_FAILED","fields","unregister","warn","resolve","services","waitForCatalog","canRegisterWaitDuration","get","Error","join","checkNetworkReachability","resetLogoutTimer","trackingid","args","prototype","getWebSocketUrl","wait","waitForRegistration","convertUrlToPriorityHostUrl","message","wsUrl","serviceHostMap","set","delay","refreshTimer","DEVICE_EVENT_REGISTRATION_SUCCESS","clearTimeout","off","unset","enableInactivityEnforcement","setLogoutTimer","duration","on","logout","timeout","timeoutTimer","once","markUrlFailedAndGetNew","markFailedUrl","initialize","FEATURE_COLLECTION_NAMES","forEach","collectionName","model","value","options","listenTo","oneFlight"],"sources":["device.js"],"sourcesContent":["// Internal Dependencies\nimport {deprecated, oneFlight} from '@webex/common';\nimport {persist, waitForValue, WebexPlugin} from '@webex/webex-core';\nimport {safeSetTimeout} from '@webex/common-timers';\n\nimport METRICS from './metrics';\nimport {\n FEATURE_COLLECTION_NAMES,\n DEVICE_EVENT_REGISTRATION_SUCCESS\n} from './constants';\nimport FeaturesModel from './features/features-model';\n\n/**\n * Determine if the plugin should be initialized based on cached storage.\n *\n * @returns {boolean} - If the device is ephemeral.\n */\nfunction decider() {\n return !this.config.ephemeral;\n}\n\nconst Device = WebexPlugin.extend({\n\n // Ampersand property members.\n\n namespace: 'Device',\n\n // Allow for extra properties to prevent the plugin from failing due to\n // **WDM** service DTO changes.\n extraProperties: 'allow',\n\n idAttribute: 'url',\n\n children: {\n /**\n * The class object that contains all of the feature collections.\n *\n * @type {FeaturesModel}\n */\n features: FeaturesModel\n },\n\n /**\n * A collection of device properties mostly assigned by the retrieved DTO from\n * the **WDM** service that are mapped against the ampersand properties.\n *\n * @type {Object}\n */\n props: {\n /**\n * This property determines whether or not giphy support is enabled.\n *\n * @type {'ALLOW' | 'BLOCK'}\n */\n clientMessagingGiphy: 'string',\n\n /**\n * This property should store the company name.\n *\n * @type {string}\n */\n customerCompanyName: 'string',\n\n /**\n * This property should store the logo url.\n *\n * @type {string}\n */\n customerLogoUrl: 'string',\n\n /**\n * This property doesn't have any real values, but is sent during device\n * refresh to prevent the **wdm** service from falling back to an iOS device\n * type.\n *\n * @type {string}\n */\n deviceType: 'string',\n\n /**\n * This property should store the help url.\n *\n * @type {string}\n */\n helpUrl: 'string',\n\n /**\n * This property should store the intranet inactivity timer duration.\n *\n * @type {number}\n */\n intranetInactivityDuration: 'number',\n\n /**\n * This property stores the url required to validate if the device is able\n * to actively reach the intranet network.\n *\n * @type {string}\n */\n intranetInactivityCheckUrl: 'string',\n\n /**\n * This property stores the inactivity timer duration, and could possibly\n * deprecate the `intranetInactivityDuration` property.\n *\n * @type {number}\n */\n inNetworkInactivityDuration: 'number',\n\n /**\n * This property stores the ECM (external content management) enabled value\n * for the whole organization.\n *\n * @type {boolean}\n */\n ecmEnabledForAllUsers: ['boolean', false, false],\n\n /**\n * This property stores an array of ECM (external content management)\n * providers that are currently available.\n *\n * @returns {Array<string>}\n */\n ecmSupportedStorageProviders: ['array', false, (() => [])],\n\n /**\n * This property stores the modification time value retrieved from the\n * **WDM** endpoint formatted as ISO 8601.\n *\n * @type {string}\n */\n modificationTime: 'string',\n\n /**\n * This property stores the navigation bar color.\n *\n * @type {string}\n */\n navigationBarColor: 'string',\n\n /**\n * This property stores the partner company's name when available.\n *\n * @type {string}\n */\n partnerCompanyName: 'string',\n\n /**\n * This property stores the partner company's logo when available.\n *\n * @type {string}\n */\n partnerLogoUrl: 'string',\n\n /**\n * This property stores the availability of people data from the **WDM**\n * service.\n *\n * @type {boolean}\n */\n peopleInsightsEnabled: 'boolean',\n\n /**\n * This property stores the reporting site's description when available.\n *\n * @type {string}\n */\n reportingSiteDesc: 'string',\n\n /**\n * This property stores the reporting site's access url when available.\n *\n * @type {string}\n */\n reportingSiteUrl: 'string',\n\n /**\n * This property stores the encryption key url when available.\n *\n * @type {string}\n */\n searchEncryptionKeyUrl: 'string',\n\n /**\n * This property stores the availability of support-provided text from the\n * **WDM** service.\n *\n * @type {boolean}\n */\n showSupportText: 'boolean',\n\n /**\n * This property stores the support provider's company name when available.\n *\n * @type {string}\n */\n supportProviderCompanyName: 'string',\n\n /**\n * This property stores the support provider's logo url when available.\n *\n * @type {string}\n */\n supportProviderLogoUrl: 'string',\n\n /**\n * This property stores the device's url retrieved from a registration\n * request. This property gets set via the initial registration process by a\n * `this.set()` method.\n *\n * @type {string}\n */\n url: 'string',\n\n /**\n * This property stores the device's userId uuid value, which can also be\n * derived from the device's registerd user's userId retrieved from\n * the **Hydra** service.\n *\n * @type {string}\n */\n userId: 'string',\n\n /**\n * This property stores whether or not file sharing is enabled\n *\n * @type {'BLOCK_BOTH' | 'BLOCK_UPLOAD'}\n */\n webFileShareControl: 'string',\n\n /**\n * This property stores the current web socket url used by the registered\n * device.\n *\n * @type {string}\n */\n webSocketUrl: 'string',\n\n /**\n * This property stores the value indicating whether or not white board file\n * sharing is enabled for the current device.\n *\n * @type {'ALLOW' | 'BLOCK'}\n */\n whiteboardFileShareControl: 'string'\n },\n\n /**\n * A list of derived properties that populate based when their parent data\n * available via the device's properties.\n *\n * @type {Object}\n */\n derived: {\n /**\n * This property determines if the current device is registered.\n *\n * @type {boolean}\n */\n registered: {\n deps: ['url'],\n\n /**\n * Checks if the device is registered by validating that the url exists.\n * Amperstand does not allow this to method to be written as an arrow\n * function.\n *\n * @returns {boolean}\n */\n fn() {\n return !!(this.url);\n }\n }\n },\n\n /**\n * Stores timer data as well as other state details.\n *\n * @type {Object}\n */\n session: {\n /**\n * This property stores the logout timer object\n *\n * @type {any}\n */\n logoutTimer: 'any',\n\n /**\n * This property stores the date for the last activity the user made\n * with the current device.\n *\n * @type {number}\n */\n lastUserActivityDate: 'number',\n\n /**\n * This property stores whether or not the reachability check has been\n * performed to prevent the reachability check from performing its\n * operation more than once after a successful check.\n *\n * @returns {boolean}\n */\n isReachabilityChecked: ['boolean', false, false],\n\n /**\n * This property stores whether or not the current device is in a meeting\n * to prevent an unneeded timeout of a meeting due to inactivity.\n *\n * @type {boolean}\n */\n isInMeeting: 'boolean',\n\n /**\n * This property identifies if the device is currently in network to prevent\n * the `resetLogoutTimer()` method from being called repeatedly once its\n * known client is connected to the organization's internal network.\n *\n * @type {boolean}\n */\n isInNetwork: 'boolean'\n },\n\n // Event method members.\n\n /**\n * Trigger meeting started event for webex instance. Used by web-client team.\n *\n * @returns {void}\n */\n meetingStarted() {\n this.webex.trigger('meeting started');\n },\n\n /**\n * Trigger meeting ended event for webex instance. Used by web-client team.\n *\n * @returns {void}\n */\n meetingEnded() {\n this.webex.trigger('meeting ended');\n },\n\n // Registration method members\n\n /* eslint-disable require-jsdoc */\n /**\n * Refresh the current registered device if able.\n *\n * @returns {Promise<void, Error>}\n */\n @oneFlight\n @waitForValue('@')\n refresh() {\n this.logger.info('device: refreshing');\n\n // Validate that the device can be registered.\n return this.canRegister()\n .then(() => {\n // Validate if the device is not registered and register instead.\n if (!this.registered) {\n this.logger.info('device: device not registered, registering');\n\n return this.register();\n }\n\n // Merge body configurations, overriding defaults.\n const body = {\n ...(this.serialize()),\n ...(this.config.body ? this.config.body : {})\n };\n\n // Remove unneeded properties from the body object.\n delete body.features;\n delete body.mediaCluster;\n\n // Append a ttl value if the device is marked as ephemeral.\n if (this.config.ephemeral) {\n body.ttl = this.config.ephemeralDeviceTTL;\n }\n\n // Merge header configurations, overriding defaults.\n const headers = {\n ...(this.config.defaults.headers ? this.config.defaults.headers : {}),\n ...(this.config.headers ? this.config.headers : {})\n };\n\n return this.request({\n method: 'PUT',\n uri: this.url,\n body,\n headers\n })\n .then((response) => this.processRegistrationSuccess(response))\n .catch((reason) => {\n // Handle a 404 error, which indicates that the device is no longer\n // valid and needs to be registered as a new device.\n if (reason.statusCode === 404) {\n this.logger.info('device: refresh failed, device is not valid');\n this.logger.info('device: attempting to register a new device');\n\n this.clear();\n\n return this.register();\n }\n\n return Promise.reject(reason);\n });\n });\n },\n\n /**\n * Register or refresh a device depending on the current device state. Device\n * registration utilizes the services plugin to send the request to the\n * **WDM** service.\n *\n * @returns {Promise<void, Error>}\n */\n @oneFlight\n @waitForValue('@')\n register() {\n this.logger.info('device: registering');\n\n // Validate that the device can be registered.\n return this.canRegister()\n .then(() => {\n // Validate if the device is already registered and refresh instead.\n if (this.registered) {\n this.logger.info('device: device already registered, refreshing');\n\n return this.refresh();\n }\n\n // Merge body configurations, overriding defaults.\n const body = {\n ...(this.config.defaults.body ? this.config.defaults.body : {}),\n ...(this.config.body ? this.config.body : {})\n };\n\n // Merge header configurations, overriding defaults.\n const headers = {\n ...(this.config.defaults.headers ? this.config.defaults.headers : {}),\n ...(this.config.headers ? this.config.headers : {})\n };\n\n // Append a ttl value if the device is marked as ephemeral\n if (this.config.ephemeral) {\n body.ttl = this.config.ephemeralDeviceTTL;\n }\n\n // This will be replaced by a `create()` method.\n return this.request({\n method: 'POST',\n service: 'wdm',\n resource: 'devices',\n body,\n headers\n })\n .then((response) => {\n this.webex.internal.metrics.submitClientMetrics(METRICS.JS_SDK_WDM_REGISTRATION_SUCCESSFUL);\n\n return this.processRegistrationSuccess(response);\n })\n .catch((error) => {\n this.webex.internal.metrics.submitClientMetrics(METRICS.JS_SDK_WDM_REGISTRATION_FAILED, {\n fields: {error}\n });\n throw error;\n });\n });\n },\n\n /**\n * Unregister the current registered device if available. Unregistering a\n * device utilizes the services plugin to send the request to the **WDM**\n * service.\n *\n * @returns {Promise<void, Error>}\n */\n @oneFlight\n @waitForValue('@')\n unregister() {\n this.logger.info('device: unregistering');\n\n if (!this.registered) {\n this.logger.warn('device: not registered');\n\n return Promise.resolve();\n }\n\n return this.request({\n uri: this.url,\n method: 'DELETE'\n })\n .then(() => this.clear());\n },\n /* eslint-enable require-jsdoc */\n\n // Helper method members\n\n /**\n * Determine if registration methods can be performed. This method utilizes\n * the `services` plugin to confirm if the appropriate service urls are\n * available for device registration.\n *\n * @returns {Promise<void, Error>}\n */\n canRegister() {\n this.logger.info('device: validating if registration can occur');\n\n // Destructure the services plugin for ease of reference.\n const {services} = this.webex.internal;\n\n // Wait for the postauth catalog to populate.\n return services.waitForCatalog(\n 'postauth',\n this.config.canRegisterWaitDuration\n )\n .then(() => (\n // Validate that the service exists after waiting for the catalog.\n services.get('wdm') ?\n Promise.resolve() :\n Promise.reject(new Error([\n 'device: cannot register,',\n '\\'wdm\\' service is not available from the postauth catalog'\n ].join(' ')))\n ));\n },\n\n /**\n * Check if the device can currently reach the inactivity check url.\n *\n * @returns {Promise<void, Error>}\n */\n checkNetworkReachability() {\n this.logger.info('device: checking network reachability');\n\n // Validate if the device has been checked and reset the logout timer.\n if (this.isReachabilityChecked) {\n return Promise.resolve(this.resetLogoutTimer());\n }\n\n this.isReachabilityChecked = true;\n\n // Validate if the device has a intranet checking url.\n if (!this.intranetInactivityCheckUrl) {\n this.isInNetwork = false;\n\n return Promise.resolve(this.resetLogoutTimer());\n }\n\n // Clear unnecessary headers for reachability request.\n const headers = {\n 'cisco-no-http-redirect': null,\n 'spark-user-agent': null,\n trackingid: null\n };\n\n // Send the network reachability request.\n return this.request({\n headers,\n method: 'GET',\n uri: this.intranetInactivityCheckUrl\n })\n .then(() => {\n this.isInNetwork = true;\n\n return Promise.resolve(this.resetLogoutTimer());\n })\n .catch(() => {\n this.logger.info('device: did not reach ping endpoint');\n this.logger.info('device: triggering off-network timer');\n\n this.isInNetwork = false;\n\n return Promise.resolve(this.resetLogoutTimer());\n });\n },\n\n /**\n * Clears the registration ttl value if available.\n *\n * @param {Object} options - Values to be cleared.\n * @returns {void}\n */\n clear(...args) {\n this.logger.info('device: clearing registered device');\n\n // Prototype the extended class in order to preserve the parent member.\n Reflect.apply(WebexPlugin.prototype.clear, this, args);\n },\n\n /**\n * Get the current websocket url with the appropriate priority host.\n *\n * @param {boolean} [wait=false] - Willing to wait on a valid url.\n * @returns {Promise<string, Error>} - The priority-mapped web socket url.\n */\n getWebSocketUrl(wait = false) {\n this.logger.info('device: getting the current websocket url');\n\n // Destructure the services plugin for ease of reference.\n const {services} = this.webex.internal;\n\n // Validate if the method should wait for registration.\n if (wait) {\n return this.waitForRegistration()\n .then(() => services.convertUrlToPriorityHostUrl(this.webSocketUrl))\n .catch((error) => {\n this.logger.warn(error.message);\n\n return Promise.reject(new Error(\n 'device: failed to get the current websocket url'\n ));\n });\n }\n\n // Validate if the device is registered.\n if (!this.registered) {\n return Promise.reject(new Error(\n 'device: cannot get websocket url, device is not registered'\n ));\n }\n\n // Attempt to collect the priority-host-mapped web socket URL.\n const wsUrl = services.convertUrlToPriorityHostUrl(this.webSocketUrl);\n\n // Validate that the url was collected.\n if (wsUrl) {\n return Promise.resolve(wsUrl);\n }\n\n return Promise.reject(new Error(\n 'device: failed to get the current websocket url'\n ));\n },\n\n /**\n * Process a successful device registration.\n *\n * @param {Object} response - response object from registration success.\n * @returns {void}\n */\n processRegistrationSuccess(response) {\n this.logger.info('device: received registration payload');\n\n // Clone the response body for service cleaning.\n const body = {...response.body};\n\n // Clean service data.\n delete body.services;\n delete body.serviceHostMap;\n\n // Assign the recieved DTO from **WDM** to this device.\n this.set(body);\n\n // Validate if device is ephemeral and setup refresh timer.\n if (this.config.ephemeral) {\n this.logger.info('device: enqueuing device refresh');\n\n const delay = (this.config.ephemeralDeviceTTL / 2 + 60) * 1000;\n\n this.refreshTimer = safeSetTimeout(() => this.refresh(), delay);\n }\n\n // Emit the registration:success event.\n this.trigger(DEVICE_EVENT_REGISTRATION_SUCCESS, this);\n },\n\n /**\n * Reset the current local logout timer for the registered device if\n * registered.\n *\n * @returns {void}\n */\n resetLogoutTimer() {\n this.logger.info('device: resetting logout timer');\n\n // Clear current logout timer.\n clearTimeout(this.logoutTimer);\n\n // Remove last activity date event listener.\n this.off('change:lastUserActivityDate');\n\n // Remove the logout timer.\n this.unset('logoutTimer');\n\n // Validate if the device is currently in a meeting and is configured to\n // required inactivity enforcement.\n if (!this.isInMeeting && this.config.enableInactivityEnforcement &&\n this.isReachabilityChecked) {\n if (this.isInNetwork) {\n this.setLogoutTimer(this.inNetworkInactivityDuration);\n }\n else {\n this.setLogoutTimer(this.intranetInactivityDuration);\n }\n }\n },\n\n /**\n * Set the value of the logout timer for the current registered device.\n *\n * @param {number} duration - Value in seconds of the new logout timer.\n * @returns {void}\n */\n setLogoutTimer(duration) {\n this.logger.info('device: setting logout timer');\n\n if (!duration || duration <= 0) {\n return;\n }\n\n // Setup user activity date event listener.\n this.on('change:lastUserActivityDate', () => { this.resetLogoutTimer(); });\n\n // Initialize a new timer.\n this.logoutTimer = safeSetTimeout(() => {\n this.webex.logout();\n }, duration * 1000);\n },\n\n /**\n * Wait for the device to be registered.\n *\n * @param {number} [timeout=10] - The maximum duration to wait, in seconds.\n * @returns {Promise<void, Error>}\n */\n waitForRegistration(timeout = 10) {\n this.logger.info('device: waiting for registration');\n\n return new Promise((resolve, reject) => {\n if (this.registered) {\n resolve();\n }\n\n const timeoutTimer = safeSetTimeout(() => reject(\n new Error('device: timeout occured while waiting for registration')\n ), timeout * 1000);\n\n this.once(DEVICE_EVENT_REGISTRATION_SUCCESS, () => {\n clearTimeout(timeoutTimer);\n resolve();\n });\n });\n },\n\n // Deprecated methods.\n\n /**\n * Mark a url as failed and get the next priority host url.\n *\n * @param {string} url - The url to mark as failed.\n * @returns {Promise<string>} - The next priority url.\n */\n @deprecated('device#markUrlFailedAndGetNew(): Use services#markFailedUrl()')\n markUrlFailedAndGetNew(url) {\n return Promise.resolve(this.webex.internal.services.markFailedUrl(url));\n },\n\n // Ampersand method members\n\n /* eslint-disable require-jsdoc */\n /**\n * Initializer method for the device plugin.\n *\n * @override\n * @param {Array<any>} args - An array of items to be mapped as properties.\n * @returns {void}\n */\n @persist('@', decider)\n initialize(...args) {\n // Prototype the extended class in order to preserve the parent member.\n Reflect.apply(WebexPlugin.prototype.initialize, this, args);\n\n // Initialize feature events and listeners.\n FEATURE_COLLECTION_NAMES.forEach((collectionName) => {\n this.features.on(`change:${collectionName}`, (model, value, options) => {\n this.trigger('change', this, options);\n this.trigger('change:features', this, this.features, options);\n });\n });\n\n // Initialize network reachability checking event for url change.\n this.on('change:intranetInactivityCheckUrl', () => {\n this.checkNetworkReachability();\n });\n\n // Initialize network reachability checking event for duration change.\n this.on('change:intranetInactivityDuration', () => {\n this.checkNetworkReachability();\n });\n\n // Initialize network reachability checking event for duration change.\n this.on('change:inNetworkInactivityDuration', () => {\n this.checkNetworkReachability();\n });\n\n // Initialize listener for activity checking.\n this.listenTo(this.webex, 'user-activity', () => {\n this.lastUserActivityDate = Date.now();\n });\n\n // Initialize listener for meeting started event.\n this.listenTo(this.webex, 'meeting started', () => {\n this.isInMeeting = true;\n this.resetLogoutTimer();\n });\n\n // Initialize listener for meeting ended event.\n this.listenTo(this.webex, 'meeting ended', () => {\n this.isInMeeting = false;\n this.resetLogoutTimer();\n });\n }\n /* eslint-enable require-jsdoc */\n});\n\nexport default Device;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;;AACA;;AACA;;AAEA;;AACA;;AAIA;;;;;;;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASA,OAAT,GAAmB;EACjB,OAAO,CAAC,KAAKC,MAAL,CAAYC,SAApB;AACD;;AAED,IAAMC,MAAM,GAAGC,uBAAYC,MAAZ,SA2UZ,6BAAa,GAAb,CA3UY,UA8YZ,6BAAa,GAAb,CA9YY,UA2cZ,6BAAa,GAAb,CA3cY,UA8tBZ,wBAAW,+DAAX,CA9tBY,UA6uBZ,wBAAQ,GAAR,EAAaL,OAAb,CA7uBY,UAAmB;EAEhC;EAEAM,SAAS,EAAE,QAJqB;EAMhC;EACA;EACAC,eAAe,EAAE,OARe;EAUhCC,WAAW,EAAE,KAVmB;EAYhCC,QAAQ,EAAE;IACR;AACJ;AACA;AACA;AACA;IACIC,QAAQ,EAAEC;EANF,CAZsB;;EAqBhC;AACF;AACA;AACA;AACA;AACA;EACEC,KAAK,EAAE;IACL;AACJ;AACA;AACA;AACA;IACIC,oBAAoB,EAAE,QANjB;;IAQL;AACJ;AACA;AACA;AACA;IACIC,mBAAmB,EAAE,QAbhB;;IAeL;AACJ;AACA;AACA;AACA;IACIC,eAAe,EAAE,QApBZ;;IAsBL;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,UAAU,EAAE,QA7BP;;IA+BL;AACJ;AACA;AACA;AACA;IACIC,OAAO,EAAE,QApCJ;;IAsCL;AACJ;AACA;AACA;AACA;IACIC,0BAA0B,EAAE,QA3CvB;;IA6CL;AACJ;AACA;AACA;AACA;AACA;IACIC,0BAA0B,EAAE,QAnDvB;;IAqDL;AACJ;AACA;AACA;AACA;AACA;IACIC,2BAA2B,EAAE,QA3DxB;;IA6DL;AACJ;AACA;AACA;AACA;AACA;IACIC,qBAAqB,EAAE,CAAC,SAAD,EAAY,KAAZ,EAAmB,KAAnB,CAnElB;;IAqEL;AACJ;AACA;AACA;AACA;AACA;IACIC,4BAA4B,EAAE,CAAC,OAAD,EAAU,KAAV,EAAkB;MAAA,OAAM,EAAN;IAAA,CAAlB,CA3EzB;;IA6EL;AACJ;AACA;AACA;AACA;AACA;IACIC,gBAAgB,EAAE,QAnFb;;IAqFL;AACJ;AACA;AACA;AACA;IACIC,kBAAkB,EAAE,QA1Ff;;IA4FL;AACJ;AACA;AACA;AACA;IACIC,kBAAkB,EAAE,QAjGf;;IAmGL;AACJ;AACA;AACA;AACA;IACIC,cAAc,EAAE,QAxGX;;IA0GL;AACJ;AACA;AACA;AACA;AACA;IACIC,qBAAqB,EAAE,SAhHlB;;IAkHL;AACJ;AACA;AACA;AACA;IACIC,iBAAiB,EAAE,QAvHd;;IAyHL;AACJ;AACA;AACA;AACA;IACIC,gBAAgB,EAAE,QA9Hb;;IAgIL;AACJ;AACA;AACA;AACA;IACIC,sBAAsB,EAAE,QArInB;;IAuIL;AACJ;AACA;AACA;AACA;AACA;IACIC,eAAe,EAAE,SA7IZ;;IA+IL;AACJ;AACA;AACA;AACA;IACIC,0BAA0B,EAAE,QApJvB;;IAsJL;AACJ;AACA;AACA;AACA;IACIC,sBAAsB,EAAE,QA3JnB;;IA6JL;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,GAAG,EAAE,QApKA;;IAsKL;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,MAAM,EAAE,QA7KH;;IA+KL;AACJ;AACA;AACA;AACA;IACIC,mBAAmB,EAAE,QApLhB;;IAsLL;AACJ;AACA;AACA;AACA;AACA;IACIC,YAAY,EAAE,QA5LT;;IA8LL;AACJ;AACA;AACA;AACA;AACA;IACIC,0BAA0B,EAAE;EApMvB,CA3ByB;;EAkOhC;AACF;AACA;AACA;AACA;AACA;EACEC,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;IACIC,UAAU,EAAE;MACVC,IAAI,EAAE,CAAC,KAAD,CADI;;MAGV;AACN;AACA;AACA;AACA;AACA;AACA;MACMC,EAVU,gBAUL;QACH,OAAO,CAAC,CAAE,KAAKR,GAAf;MACD;IAZS;EANL,CAxOuB;;EA8PhC;AACF;AACA;AACA;AACA;EACES,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;IACIC,WAAW,EAAE,KANN;;IAQP;AACJ;AACA;AACA;AACA;AACA;IACIC,oBAAoB,EAAE,QAdf;;IAgB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"}
1
+ {"version":3,"names":["decider","config","ephemeral","Device","WebexPlugin","extend","namespace","extraProperties","idAttribute","children","features","FeaturesModel","props","clientMessagingGiphy","customerCompanyName","customerLogoUrl","deviceType","helpUrl","intranetInactivityDuration","intranetInactivityCheckUrl","inNetworkInactivityDuration","ecmEnabledForAllUsers","ecmSupportedStorageProviders","modificationTime","navigationBarColor","partnerCompanyName","partnerLogoUrl","peopleInsightsEnabled","reportingSiteDesc","reportingSiteUrl","searchEncryptionKeyUrl","showSupportText","supportProviderCompanyName","supportProviderLogoUrl","url","userId","webFileShareControl","webSocketUrl","whiteboardFileShareControl","derived","registered","deps","fn","session","logoutTimer","lastUserActivityDate","isReachabilityChecked","isInMeeting","isInNetwork","meetingStarted","webex","trigger","meetingEnded","refresh","logger","info","canRegister","then","register","body","serialize","mediaCluster","etag","ttl","ephemeralDeviceTTL","headers","defaults","request","method","uri","response","processRegistrationSuccess","catch","reason","statusCode","clear","reject","service","resource","internal","metrics","submitClientMetrics","METRICS","JS_SDK_WDM_REGISTRATION_SUCCESSFUL","error","JS_SDK_WDM_REGISTRATION_FAILED","fields","unregister","warn","resolve","services","waitForCatalog","canRegisterWaitDuration","get","Error","join","checkNetworkReachability","resetLogoutTimer","trackingid","args","prototype","getWebSocketUrl","wait","waitForRegistration","convertUrlToPriorityHostUrl","message","wsUrl","serviceHostMap","user","reset","entitlement","set","delay","refreshTimer","DEVICE_EVENT_REGISTRATION_SUCCESS","clearTimeout","off","unset","enableInactivityEnforcement","setLogoutTimer","duration","on","logout","timeout","timeoutTimer","once","markUrlFailedAndGetNew","markFailedUrl","initialize","FEATURE_COLLECTION_NAMES","forEach","collectionName","model","value","options","listenTo","oneFlight"],"sources":["device.js"],"sourcesContent":["// Internal Dependencies\nimport {deprecated, oneFlight} from '@webex/common';\nimport {persist, waitForValue, WebexPlugin} from '@webex/webex-core';\nimport {safeSetTimeout} from '@webex/common-timers';\n\nimport METRICS from './metrics';\nimport {\n FEATURE_COLLECTION_NAMES,\n DEVICE_EVENT_REGISTRATION_SUCCESS\n} from './constants';\nimport FeaturesModel from './features/features-model';\n\n/**\n * Determine if the plugin should be initialized based on cached storage.\n *\n * @returns {boolean} - If the device is ephemeral.\n */\nfunction decider() {\n return !this.config.ephemeral;\n}\n\nconst Device = WebexPlugin.extend({\n\n // Ampersand property members.\n\n namespace: 'Device',\n\n // Allow for extra properties to prevent the plugin from failing due to\n // **WDM** service DTO changes.\n extraProperties: 'allow',\n\n idAttribute: 'url',\n\n children: {\n /**\n * The class object that contains all of the feature collections.\n *\n * @type {FeaturesModel}\n */\n features: FeaturesModel\n },\n\n /**\n * A collection of device properties mostly assigned by the retrieved DTO from\n * the **WDM** service that are mapped against the ampersand properties.\n *\n * @type {Object}\n */\n props: {\n /**\n * This property determines whether or not giphy support is enabled.\n *\n * @type {'ALLOW' | 'BLOCK'}\n */\n clientMessagingGiphy: 'string',\n\n /**\n * This property should store the company name.\n *\n * @type {string}\n */\n customerCompanyName: 'string',\n\n /**\n * This property should store the logo url.\n *\n * @type {string}\n */\n customerLogoUrl: 'string',\n\n /**\n * This property doesn't have any real values, but is sent during device\n * refresh to prevent the **wdm** service from falling back to an iOS device\n * type.\n *\n * @type {string}\n */\n deviceType: 'string',\n\n /**\n * This property should store the help url.\n *\n * @type {string}\n */\n helpUrl: 'string',\n\n /**\n * This property should store the intranet inactivity timer duration.\n *\n * @type {number}\n */\n intranetInactivityDuration: 'number',\n\n /**\n * This property stores the url required to validate if the device is able\n * to actively reach the intranet network.\n *\n * @type {string}\n */\n intranetInactivityCheckUrl: 'string',\n\n /**\n * This property stores the inactivity timer duration, and could possibly\n * deprecate the `intranetInactivityDuration` property.\n *\n * @type {number}\n */\n inNetworkInactivityDuration: 'number',\n\n /**\n * This property stores the ECM (external content management) enabled value\n * for the whole organization.\n *\n * @type {boolean}\n */\n ecmEnabledForAllUsers: ['boolean', false, false],\n\n /**\n * This property stores an array of ECM (external content management)\n * providers that are currently available.\n *\n * @returns {Array<string>}\n */\n ecmSupportedStorageProviders: ['array', false, (() => [])],\n\n /**\n * This property stores the modification time value retrieved from the\n * **WDM** endpoint formatted as ISO 8601.\n *\n * @type {string}\n */\n modificationTime: 'string',\n\n /**\n * This property stores the navigation bar color.\n *\n * @type {string}\n */\n navigationBarColor: 'string',\n\n /**\n * This property stores the partner company's name when available.\n *\n * @type {string}\n */\n partnerCompanyName: 'string',\n\n /**\n * This property stores the partner company's logo when available.\n *\n * @type {string}\n */\n partnerLogoUrl: 'string',\n\n /**\n * This property stores the availability of people data from the **WDM**\n * service.\n *\n * @type {boolean}\n */\n peopleInsightsEnabled: 'boolean',\n\n /**\n * This property stores the reporting site's description when available.\n *\n * @type {string}\n */\n reportingSiteDesc: 'string',\n\n /**\n * This property stores the reporting site's access url when available.\n *\n * @type {string}\n */\n reportingSiteUrl: 'string',\n\n /**\n * This property stores the encryption key url when available.\n *\n * @type {string}\n */\n searchEncryptionKeyUrl: 'string',\n\n /**\n * This property stores the availability of support-provided text from the\n * **WDM** service.\n *\n * @type {boolean}\n */\n showSupportText: 'boolean',\n\n /**\n * This property stores the support provider's company name when available.\n *\n * @type {string}\n */\n supportProviderCompanyName: 'string',\n\n /**\n * This property stores the support provider's logo url when available.\n *\n * @type {string}\n */\n supportProviderLogoUrl: 'string',\n\n /**\n * This property stores the device's url retrieved from a registration\n * request. This property gets set via the initial registration process by a\n * `this.set()` method.\n *\n * @type {string}\n */\n url: 'string',\n\n /**\n * This property stores the device's userId uuid value, which can also be\n * derived from the device's registerd user's userId retrieved from\n * the **Hydra** service.\n *\n * @type {string}\n */\n userId: 'string',\n\n /**\n * This property stores whether or not file sharing is enabled\n *\n * @type {'BLOCK_BOTH' | 'BLOCK_UPLOAD'}\n */\n webFileShareControl: 'string',\n\n /**\n * This property stores the current web socket url used by the registered\n * device.\n *\n * @type {string}\n */\n webSocketUrl: 'string',\n\n /**\n * This property stores the value indicating whether or not white board file\n * sharing is enabled for the current device.\n *\n * @type {'ALLOW' | 'BLOCK'}\n */\n whiteboardFileShareControl: 'string'\n },\n\n /**\n * A list of derived properties that populate based when their parent data\n * available via the device's properties.\n *\n * @type {Object}\n */\n derived: {\n /**\n * This property determines if the current device is registered.\n *\n * @type {boolean}\n */\n registered: {\n deps: ['url'],\n\n /**\n * Checks if the device is registered by validating that the url exists.\n * Amperstand does not allow this to method to be written as an arrow\n * function.\n *\n * @returns {boolean}\n */\n fn() {\n return !!(this.url);\n }\n }\n },\n\n /**\n * Stores timer data as well as other state details.\n *\n * @type {Object}\n */\n session: {\n /**\n * This property stores the logout timer object\n *\n * @type {any}\n */\n logoutTimer: 'any',\n\n /**\n * This property stores the date for the last activity the user made\n * with the current device.\n *\n * @type {number}\n */\n lastUserActivityDate: 'number',\n\n /**\n * This property stores whether or not the reachability check has been\n * performed to prevent the reachability check from performing its\n * operation more than once after a successful check.\n *\n * @returns {boolean}\n */\n isReachabilityChecked: ['boolean', false, false],\n\n /**\n * This property stores whether or not the current device is in a meeting\n * to prevent an unneeded timeout of a meeting due to inactivity.\n *\n * @type {boolean}\n */\n isInMeeting: 'boolean',\n\n /**\n * This property identifies if the device is currently in network to prevent\n * the `resetLogoutTimer()` method from being called repeatedly once its\n * known client is connected to the organization's internal network.\n *\n * @type {boolean}\n */\n isInNetwork: 'boolean'\n },\n\n // Event method members.\n\n /**\n * Trigger meeting started event for webex instance. Used by web-client team.\n *\n * @returns {void}\n */\n meetingStarted() {\n this.webex.trigger('meeting started');\n },\n\n /**\n * Trigger meeting ended event for webex instance. Used by web-client team.\n *\n * @returns {void}\n */\n meetingEnded() {\n this.webex.trigger('meeting ended');\n },\n\n // Registration method members\n\n /* eslint-disable require-jsdoc */\n /**\n * Refresh the current registered device if able.\n *\n * @returns {Promise<void, Error>}\n */\n @oneFlight\n @waitForValue('@')\n refresh() {\n this.logger.info('device: refreshing');\n\n // Validate that the device can be registered.\n return this.canRegister()\n .then(() => {\n // Validate if the device is not registered and register instead.\n if (!this.registered) {\n this.logger.info('device: device not registered, registering');\n\n return this.register();\n }\n\n // Merge body configurations, overriding defaults.\n const body = {\n ...(this.serialize()),\n ...(this.config.body ? this.config.body : {})\n };\n\n // Remove unneeded properties from the body object.\n delete body.features;\n delete body.mediaCluster;\n delete body.etag;\n\n // Append a ttl value if the device is marked as ephemeral.\n if (this.config.ephemeral) {\n body.ttl = this.config.ephemeralDeviceTTL;\n }\n\n // Merge header configurations, overriding defaults.\n const headers = {\n ...(this.config.defaults.headers ? this.config.defaults.headers : {}),\n ...(this.config.headers ? this.config.headers : {}),\n // If etag is sent, WDM will not send developer feature toggles unless they have changed\n ...(this.etag ? {'If-None-Match': this.etag} : {})\n };\n\n return this.request({\n method: 'PUT',\n uri: this.url,\n body,\n headers\n })\n .then((response) => this.processRegistrationSuccess(response))\n .catch((reason) => {\n // Handle a 404 error, which indicates that the device is no longer\n // valid and needs to be registered as a new device.\n if (reason.statusCode === 404) {\n this.logger.info('device: refresh failed, device is not valid');\n this.logger.info('device: attempting to register a new device');\n\n this.clear();\n\n return this.register();\n }\n\n return Promise.reject(reason);\n });\n });\n },\n\n /**\n * Register or refresh a device depending on the current device state. Device\n * registration utilizes the services plugin to send the request to the\n * **WDM** service.\n *\n * @returns {Promise<void, Error>}\n */\n @oneFlight\n @waitForValue('@')\n register() {\n this.logger.info('device: registering');\n\n // Validate that the device can be registered.\n return this.canRegister()\n .then(() => {\n // Validate if the device is already registered and refresh instead.\n if (this.registered) {\n this.logger.info('device: device already registered, refreshing');\n\n return this.refresh();\n }\n\n // Merge body configurations, overriding defaults.\n const body = {\n ...(this.config.defaults.body ? this.config.defaults.body : {}),\n ...(this.config.body ? this.config.body : {})\n };\n\n // Merge header configurations, overriding defaults.\n const headers = {\n ...(this.config.defaults.headers ? this.config.defaults.headers : {}),\n ...(this.config.headers ? this.config.headers : {})\n };\n\n // Append a ttl value if the device is marked as ephemeral\n if (this.config.ephemeral) {\n body.ttl = this.config.ephemeralDeviceTTL;\n }\n\n // This will be replaced by a `create()` method.\n return this.request({\n method: 'POST',\n service: 'wdm',\n resource: 'devices',\n body,\n headers\n })\n .then((response) => {\n this.webex.internal.metrics.submitClientMetrics(METRICS.JS_SDK_WDM_REGISTRATION_SUCCESSFUL);\n\n return this.processRegistrationSuccess(response);\n })\n .catch((error) => {\n this.webex.internal.metrics.submitClientMetrics(METRICS.JS_SDK_WDM_REGISTRATION_FAILED, {\n fields: {error}\n });\n throw error;\n });\n });\n },\n\n /**\n * Unregister the current registered device if available. Unregistering a\n * device utilizes the services plugin to send the request to the **WDM**\n * service.\n *\n * @returns {Promise<void, Error>}\n */\n @oneFlight\n @waitForValue('@')\n unregister() {\n this.logger.info('device: unregistering');\n\n if (!this.registered) {\n this.logger.warn('device: not registered');\n\n return Promise.resolve();\n }\n\n return this.request({\n uri: this.url,\n method: 'DELETE'\n })\n .then(() => this.clear());\n },\n /* eslint-enable require-jsdoc */\n\n // Helper method members\n\n /**\n * Determine if registration methods can be performed. This method utilizes\n * the `services` plugin to confirm if the appropriate service urls are\n * available for device registration.\n *\n * @returns {Promise<void, Error>}\n */\n canRegister() {\n this.logger.info('device: validating if registration can occur');\n\n // Destructure the services plugin for ease of reference.\n const {services} = this.webex.internal;\n\n // Wait for the postauth catalog to populate.\n return services.waitForCatalog(\n 'postauth',\n this.config.canRegisterWaitDuration\n )\n .then(() => (\n // Validate that the service exists after waiting for the catalog.\n services.get('wdm') ?\n Promise.resolve() :\n Promise.reject(new Error([\n 'device: cannot register,',\n '\\'wdm\\' service is not available from the postauth catalog'\n ].join(' ')))\n ));\n },\n\n /**\n * Check if the device can currently reach the inactivity check url.\n *\n * @returns {Promise<void, Error>}\n */\n checkNetworkReachability() {\n this.logger.info('device: checking network reachability');\n\n // Validate if the device has been checked and reset the logout timer.\n if (this.isReachabilityChecked) {\n return Promise.resolve(this.resetLogoutTimer());\n }\n\n this.isReachabilityChecked = true;\n\n // Validate if the device has a intranet checking url.\n if (!this.intranetInactivityCheckUrl) {\n this.isInNetwork = false;\n\n return Promise.resolve(this.resetLogoutTimer());\n }\n\n // Clear unnecessary headers for reachability request.\n const headers = {\n 'cisco-no-http-redirect': null,\n 'spark-user-agent': null,\n trackingid: null\n };\n\n // Send the network reachability request.\n return this.request({\n headers,\n method: 'GET',\n uri: this.intranetInactivityCheckUrl\n })\n .then(() => {\n this.isInNetwork = true;\n\n return Promise.resolve(this.resetLogoutTimer());\n })\n .catch(() => {\n this.logger.info('device: did not reach ping endpoint');\n this.logger.info('device: triggering off-network timer');\n\n this.isInNetwork = false;\n\n return Promise.resolve(this.resetLogoutTimer());\n });\n },\n\n /**\n * Clears the registration ttl value if available.\n *\n * @param {Object} options - Values to be cleared.\n * @returns {void}\n */\n clear(...args) {\n this.logger.info('device: clearing registered device');\n\n // Prototype the extended class in order to preserve the parent member.\n Reflect.apply(WebexPlugin.prototype.clear, this, args);\n },\n\n /**\n * Get the current websocket url with the appropriate priority host.\n *\n * @param {boolean} [wait=false] - Willing to wait on a valid url.\n * @returns {Promise<string, Error>} - The priority-mapped web socket url.\n */\n getWebSocketUrl(wait = false) {\n this.logger.info('device: getting the current websocket url');\n\n // Destructure the services plugin for ease of reference.\n const {services} = this.webex.internal;\n\n // Validate if the method should wait for registration.\n if (wait) {\n return this.waitForRegistration()\n .then(() => services.convertUrlToPriorityHostUrl(this.webSocketUrl))\n .catch((error) => {\n this.logger.warn(error.message);\n\n return Promise.reject(new Error(\n 'device: failed to get the current websocket url'\n ));\n });\n }\n\n // Validate if the device is registered.\n if (!this.registered) {\n return Promise.reject(new Error(\n 'device: cannot get websocket url, device is not registered'\n ));\n }\n\n // Attempt to collect the priority-host-mapped web socket URL.\n const wsUrl = services.convertUrlToPriorityHostUrl(this.webSocketUrl);\n\n // Validate that the url was collected.\n if (wsUrl) {\n return Promise.resolve(wsUrl);\n }\n\n return Promise.reject(new Error(\n 'device: failed to get the current websocket url'\n ));\n },\n\n /**\n * Process a successful device registration.\n *\n * @param {Object} response - response object from registration success.\n * @returns {void}\n */\n processRegistrationSuccess(response) {\n this.logger.info('device: received registration payload');\n\n // Clone the response body for service cleaning.\n const body = {...response.body};\n\n // Clean service data.\n delete body.services;\n delete body.serviceHostMap;\n\n const {etag} = response.headers;\n\n if (this.etag && this.etag === etag) {\n // If current etag matches the previous one and we have sent\n // If-None-Match header the developer and entitlement feature\n // toggles will not be returned\n const {features} = body;\n\n delete body.features;\n // When using the etag feature cache, user and entitlement features are still returned\n this.features.user.reset(features.user);\n this.features.entitlement.reset(features.entitlement);\n }\n\n // Assign the recieved DTO from **WDM** to this device.\n this.set(body);\n\n // Assign the new etag to this device.\n this.set({etag});\n\n // Validate if device is ephemeral and setup refresh timer.\n if (this.config.ephemeral) {\n this.logger.info('device: enqueuing device refresh');\n\n const delay = (this.config.ephemeralDeviceTTL / 2 + 60) * 1000;\n\n this.refreshTimer = safeSetTimeout(() => this.refresh(), delay);\n }\n\n // Emit the registration:success event.\n this.trigger(DEVICE_EVENT_REGISTRATION_SUCCESS, this);\n },\n\n /**\n * Reset the current local logout timer for the registered device if\n * registered.\n *\n * @returns {void}\n */\n resetLogoutTimer() {\n this.logger.info('device: resetting logout timer');\n\n // Clear current logout timer.\n clearTimeout(this.logoutTimer);\n\n // Remove last activity date event listener.\n this.off('change:lastUserActivityDate');\n\n // Remove the logout timer.\n this.unset('logoutTimer');\n\n // Validate if the device is currently in a meeting and is configured to\n // required inactivity enforcement.\n if (!this.isInMeeting && this.config.enableInactivityEnforcement &&\n this.isReachabilityChecked) {\n if (this.isInNetwork) {\n this.setLogoutTimer(this.inNetworkInactivityDuration);\n }\n else {\n this.setLogoutTimer(this.intranetInactivityDuration);\n }\n }\n },\n\n /**\n * Set the value of the logout timer for the current registered device.\n *\n * @param {number} duration - Value in seconds of the new logout timer.\n * @returns {void}\n */\n setLogoutTimer(duration) {\n this.logger.info('device: setting logout timer');\n\n if (!duration || duration <= 0) {\n return;\n }\n\n // Setup user activity date event listener.\n this.on('change:lastUserActivityDate', () => { this.resetLogoutTimer(); });\n\n // Initialize a new timer.\n this.logoutTimer = safeSetTimeout(() => {\n this.webex.logout();\n }, duration * 1000);\n },\n\n /**\n * Wait for the device to be registered.\n *\n * @param {number} [timeout=10] - The maximum duration to wait, in seconds.\n * @returns {Promise<void, Error>}\n */\n waitForRegistration(timeout = 10) {\n this.logger.info('device: waiting for registration');\n\n return new Promise((resolve, reject) => {\n if (this.registered) {\n resolve();\n }\n\n const timeoutTimer = safeSetTimeout(() => reject(\n new Error('device: timeout occured while waiting for registration')\n ), timeout * 1000);\n\n this.once(DEVICE_EVENT_REGISTRATION_SUCCESS, () => {\n clearTimeout(timeoutTimer);\n resolve();\n });\n });\n },\n\n // Deprecated methods.\n\n /**\n * Mark a url as failed and get the next priority host url.\n *\n * @param {string} url - The url to mark as failed.\n * @returns {Promise<string>} - The next priority url.\n */\n @deprecated('device#markUrlFailedAndGetNew(): Use services#markFailedUrl()')\n markUrlFailedAndGetNew(url) {\n return Promise.resolve(this.webex.internal.services.markFailedUrl(url));\n },\n\n // Ampersand method members\n\n /* eslint-disable require-jsdoc */\n /**\n * Initializer method for the device plugin.\n *\n * @override\n * @param {Array<any>} args - An array of items to be mapped as properties.\n * @returns {void}\n */\n @persist('@', decider)\n initialize(...args) {\n // Prototype the extended class in order to preserve the parent member.\n Reflect.apply(WebexPlugin.prototype.initialize, this, args);\n\n // Initialize feature events and listeners.\n FEATURE_COLLECTION_NAMES.forEach((collectionName) => {\n this.features.on(`change:${collectionName}`, (model, value, options) => {\n this.trigger('change', this, options);\n this.trigger('change:features', this, this.features, options);\n });\n });\n\n // Initialize network reachability checking event for url change.\n this.on('change:intranetInactivityCheckUrl', () => {\n this.checkNetworkReachability();\n });\n\n // Initialize network reachability checking event for duration change.\n this.on('change:intranetInactivityDuration', () => {\n this.checkNetworkReachability();\n });\n\n // Initialize network reachability checking event for duration change.\n this.on('change:inNetworkInactivityDuration', () => {\n this.checkNetworkReachability();\n });\n\n // Initialize listener for activity checking.\n this.listenTo(this.webex, 'user-activity', () => {\n this.lastUserActivityDate = Date.now();\n });\n\n // Initialize listener for meeting started event.\n this.listenTo(this.webex, 'meeting started', () => {\n this.isInMeeting = true;\n this.resetLogoutTimer();\n });\n\n // Initialize listener for meeting ended event.\n this.listenTo(this.webex, 'meeting ended', () => {\n this.isInMeeting = false;\n this.resetLogoutTimer();\n });\n }\n /* eslint-enable require-jsdoc */\n});\n\nexport default Device;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA;;AACA;;AACA;;AAEA;;AACA;;AAIA;;;;;;;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASA,OAAT,GAAmB;EACjB,OAAO,CAAC,KAAKC,MAAL,CAAYC,SAApB;AACD;;AAED,IAAMC,MAAM,GAAGC,uBAAYC,MAAZ,SA2UZ,6BAAa,GAAb,CA3UY,UAiZZ,6BAAa,GAAb,CAjZY,UA8cZ,6BAAa,GAAb,CA9cY,UAkvBZ,wBAAW,+DAAX,CAlvBY,UAiwBZ,wBAAQ,GAAR,EAAaL,OAAb,CAjwBY,UAAmB;EAEhC;EAEAM,SAAS,EAAE,QAJqB;EAMhC;EACA;EACAC,eAAe,EAAE,OARe;EAUhCC,WAAW,EAAE,KAVmB;EAYhCC,QAAQ,EAAE;IACR;AACJ;AACA;AACA;AACA;IACIC,QAAQ,EAAEC;EANF,CAZsB;;EAqBhC;AACF;AACA;AACA;AACA;AACA;EACEC,KAAK,EAAE;IACL;AACJ;AACA;AACA;AACA;IACIC,oBAAoB,EAAE,QANjB;;IAQL;AACJ;AACA;AACA;AACA;IACIC,mBAAmB,EAAE,QAbhB;;IAeL;AACJ;AACA;AACA;AACA;IACIC,eAAe,EAAE,QApBZ;;IAsBL;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,UAAU,EAAE,QA7BP;;IA+BL;AACJ;AACA;AACA;AACA;IACIC,OAAO,EAAE,QApCJ;;IAsCL;AACJ;AACA;AACA;AACA;IACIC,0BAA0B,EAAE,QA3CvB;;IA6CL;AACJ;AACA;AACA;AACA;AACA;IACIC,0BAA0B,EAAE,QAnDvB;;IAqDL;AACJ;AACA;AACA;AACA;AACA;IACIC,2BAA2B,EAAE,QA3DxB;;IA6DL;AACJ;AACA;AACA;AACA;AACA;IACIC,qBAAqB,EAAE,CAAC,SAAD,EAAY,KAAZ,EAAmB,KAAnB,CAnElB;;IAqEL;AACJ;AACA;AACA;AACA;AACA;IACIC,4BAA4B,EAAE,CAAC,OAAD,EAAU,KAAV,EAAkB;MAAA,OAAM,EAAN;IAAA,CAAlB,CA3EzB;;IA6EL;AACJ;AACA;AACA;AACA;AACA;IACIC,gBAAgB,EAAE,QAnFb;;IAqFL;AACJ;AACA;AACA;AACA;IACIC,kBAAkB,EAAE,QA1Ff;;IA4FL;AACJ;AACA;AACA;AACA;IACIC,kBAAkB,EAAE,QAjGf;;IAmGL;AACJ;AACA;AACA;AACA;IACIC,cAAc,EAAE,QAxGX;;IA0GL;AACJ;AACA;AACA;AACA;AACA;IACIC,qBAAqB,EAAE,SAhHlB;;IAkHL;AACJ;AACA;AACA;AACA;IACIC,iBAAiB,EAAE,QAvHd;;IAyHL;AACJ;AACA;AACA;AACA;IACIC,gBAAgB,EAAE,QA9Hb;;IAgIL;AACJ;AACA;AACA;AACA;IACIC,sBAAsB,EAAE,QArInB;;IAuIL;AACJ;AACA;AACA;AACA;AACA;IACIC,eAAe,EAAE,SA7IZ;;IA+IL;AACJ;AACA;AACA;AACA;IACIC,0BAA0B,EAAE,QApJvB;;IAsJL;AACJ;AACA;AACA;AACA;IACIC,sBAAsB,EAAE,QA3JnB;;IA6JL;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,GAAG,EAAE,QApKA;;IAsKL;AACJ;AACA;AACA;AACA;AACA;AACA;IACIC,MAAM,EAAE,QA7KH;;IA+KL;AACJ;AACA;AACA;AACA;IACIC,mBAAmB,EAAE,QApLhB;;IAsLL;AACJ;AACA;AACA;AACA;AACA;IACIC,YAAY,EAAE,QA5LT;;IA8LL;AACJ;AACA;AACA;AACA;AACA;IACIC,0BAA0B,EAAE;EApMvB,CA3ByB;;EAkOhC;AACF;AACA;AACA;AACA;AACA;EACEC,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;IACIC,UAAU,EAAE;MACVC,IAAI,EAAE,CAAC,KAAD,CADI;;MAGV;AACN;AACA;AACA;AACA;AACA;AACA;MACMC,EAVU,gBAUL;QACH,OAAO,CAAC,CAAE,KAAKR,GAAf;MACD;IAZS;EANL,CAxOuB;;EA8PhC;AACF;AACA;AACA;AACA;EACES,OAAO,EAAE;IACP;AACJ;AACA;AACA;AACA;IACIC,WAAW,EAAE,KANN;;IAQP;AACJ;AACA;AACA;AACA;AACA;IACIC,oBAAoB,EAAE,QAdf;;IAgB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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/internal-plugin-device",
3
- "version": "2.4.2",
3
+ "version": "2.7.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "author": "Timothy Scheuering <timsch@cisco.com>",
@@ -17,14 +17,14 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@babel/runtime-corejs2": "^7.14.8",
20
- "@webex/internal-plugin-metrics": "2.4.2",
21
- "@webex/webex-core": "2.4.2",
22
- "@webex/common": "2.4.2",
23
- "@webex/common-timers": "2.4.2",
20
+ "@webex/internal-plugin-metrics": "2.7.0",
21
+ "@webex/webex-core": "2.7.0",
22
+ "@webex/common": "2.7.0",
23
+ "@webex/common-timers": "2.7.0",
24
24
  "ampersand-state": "^5.0.3",
25
25
  "ampersand-collection": "^2.0.2",
26
26
  "lodash": "^4.17.21",
27
- "@webex/http-core": "2.4.2",
27
+ "@webex/http-core": "2.7.0",
28
28
  "envify": "^4.1.0"
29
29
  }
30
30
  }
package/src/device.js CHANGED
@@ -373,6 +373,7 @@ const Device = WebexPlugin.extend({
373
373
  // Remove unneeded properties from the body object.
374
374
  delete body.features;
375
375
  delete body.mediaCluster;
376
+ delete body.etag;
376
377
 
377
378
  // Append a ttl value if the device is marked as ephemeral.
378
379
  if (this.config.ephemeral) {
@@ -382,7 +383,9 @@ const Device = WebexPlugin.extend({
382
383
  // Merge header configurations, overriding defaults.
383
384
  const headers = {
384
385
  ...(this.config.defaults.headers ? this.config.defaults.headers : {}),
385
- ...(this.config.headers ? this.config.headers : {})
386
+ ...(this.config.headers ? this.config.headers : {}),
387
+ // If etag is sent, WDM will not send developer feature toggles unless they have changed
388
+ ...(this.etag ? {'If-None-Match': this.etag} : {})
386
389
  };
387
390
 
388
391
  return this.request({
@@ -651,9 +654,26 @@ const Device = WebexPlugin.extend({
651
654
  delete body.services;
652
655
  delete body.serviceHostMap;
653
656
 
657
+ const {etag} = response.headers;
658
+
659
+ if (this.etag && this.etag === etag) {
660
+ // If current etag matches the previous one and we have sent
661
+ // If-None-Match header the developer and entitlement feature
662
+ // toggles will not be returned
663
+ const {features} = body;
664
+
665
+ delete body.features;
666
+ // When using the etag feature cache, user and entitlement features are still returned
667
+ this.features.user.reset(features.user);
668
+ this.features.entitlement.reset(features.entitlement);
669
+ }
670
+
654
671
  // Assign the recieved DTO from **WDM** to this device.
655
672
  this.set(body);
656
673
 
674
+ // Assign the new etag to this device.
675
+ this.set({etag});
676
+
657
677
  // Validate if device is ephemeral and setup refresh timer.
658
678
  if (this.config.ephemeral) {
659
679
  this.logger.info('device: enqueuing device refresh');
@@ -1,9 +1,10 @@
1
1
  import {assert} from '@webex/test-helper-chai';
2
2
  import {cloneDeep} from 'lodash';
3
- import Device from '@webex/internal-plugin-device';
4
3
  import MockWebex from '@webex/test-helper-mock-webex';
5
4
  import sinon from 'sinon';
6
5
 
6
+ import Device from '@webex/internal-plugin-device';
7
+
7
8
  import dto from './wdm-dto';
8
9
 
9
10
  describe('plugin-device', () => {
@@ -178,5 +179,241 @@ describe('plugin-device', () => {
178
179
  );
179
180
  });
180
181
  });
182
+
183
+ describe('#refresh()', () => {
184
+ let requestSpy;
185
+
186
+ const setup = () => {
187
+ sinon.stub(device, 'canRegister').callsFake(() => Promise.resolve());
188
+ sinon.stub(device, 'processRegistrationSuccess').callsFake(() => {});
189
+ requestSpy = sinon.spy(device, 'request');
190
+ device.config.defaults = {};
191
+ device.set('registered', true);
192
+ };
193
+
194
+ it('If-None-Match header is added if etag is set', async () => {
195
+ setup();
196
+
197
+ device.set('etag', 'etag-value');
198
+
199
+ const result = device.refresh();
200
+
201
+ await result;
202
+
203
+ assert.deepEqual(requestSpy.args[0][0].headers, {
204
+ 'If-None-Match': 'etag-value'
205
+ });
206
+ });
207
+
208
+ it('If-None-Match header is not added if etag is not set', async () => {
209
+ setup();
210
+
211
+ const result = device.refresh();
212
+
213
+ await result;
214
+
215
+ assert.deepEqual(requestSpy.args[0][0].headers, {});
216
+ });
217
+ });
218
+
219
+ describe('#processRegistrationSuccess()', () => {
220
+ const getClonedDTO = (overrides) => {
221
+ const clonedDTO = cloneDeep(dto);
222
+
223
+ clonedDTO.features = {
224
+ developer: [
225
+ {
226
+ key: '1',
227
+ type: 'boolean',
228
+ val: 'true',
229
+ value: true,
230
+ mutable: true,
231
+ lastModified: '2015-06-29T20:02:48.033Z'
232
+ },
233
+ ],
234
+ entitlement: [
235
+ {
236
+ key: '2',
237
+ val: 'true',
238
+ value: true,
239
+ mutable: false
240
+ }
241
+ ],
242
+ user: [
243
+ {
244
+ key: '3',
245
+ val: 'true',
246
+ value: true,
247
+ mutable: true
248
+ }
249
+ ],
250
+ ...overrides
251
+ };
252
+
253
+ return clonedDTO;
254
+ };
255
+
256
+ const checkFeatureNotPresent = (type, key) => {
257
+ assert.isUndefined(device.features[type].get(key));
258
+ };
259
+
260
+ const checkFeature = (type, key, expectedValue) => {
261
+ assert.equal(device.features[type].length, 1);
262
+ assert.deepEqual(device.features[type].get(key).get('value'), expectedValue);
263
+ };
264
+
265
+ it('features are set correctly if etag not in headers', () => {
266
+ const clonedDTO = getClonedDTO();
267
+
268
+ const response = {
269
+ body: {
270
+ ...clonedDTO
271
+ },
272
+ headers: {
273
+
274
+ }
275
+ };
276
+
277
+ checkFeatureNotPresent('developer', '1');
278
+ checkFeatureNotPresent('entitlement', '2');
279
+ checkFeatureNotPresent('user', '3');
280
+
281
+ device.processRegistrationSuccess(response);
282
+
283
+ checkFeature('developer', '1', true);
284
+ checkFeature('entitlement', '2', true);
285
+ checkFeature('user', '3', true);
286
+ });
287
+
288
+ it('if the etag matches only the user and entitlement features are updated', () => {
289
+ const clonedDTO = getClonedDTO();
290
+
291
+ device.set('etag', 'etag-value');
292
+
293
+ const response = {
294
+ body: {
295
+ ...clonedDTO
296
+ },
297
+ headers: {
298
+ etag: 'etag-value'
299
+ }
300
+ };
301
+
302
+ checkFeatureNotPresent('developer', '1');
303
+ checkFeatureNotPresent('entitlement', '2');
304
+ checkFeatureNotPresent('user', '3');
305
+
306
+ device.processRegistrationSuccess(response);
307
+
308
+ checkFeatureNotPresent('developer', '1');
309
+ checkFeature('entitlement', '2', true);
310
+ checkFeature('user', '3', true);
311
+
312
+ // confirm that the etag is unchanged
313
+ assert.equal(device.get('etag'), 'etag-value');
314
+ });
315
+
316
+ it('if the etag matches only the user and entitlement features are updated - check when developer features are set', () => {
317
+ const clonedDTO = getClonedDTO();
318
+
319
+ device.set('etag', 'etag-value');
320
+
321
+ const response = {
322
+ body: {
323
+ ...clonedDTO
324
+ },
325
+ headers: {
326
+ etag: 'etag-value'
327
+ }
328
+ };
329
+
330
+ checkFeatureNotPresent('developer', '1');
331
+ checkFeatureNotPresent('entitlement', '2');
332
+ checkFeatureNotPresent('user', '3');
333
+
334
+ device.processRegistrationSuccess(response);
335
+
336
+ checkFeatureNotPresent('developer', '1');
337
+ checkFeature('entitlement', '2', true);
338
+ checkFeature('user', '3', true);
339
+
340
+ // confirm that the etag is unchanged
341
+ assert.equal(device.get('etag'), 'etag-value');
342
+ });
343
+
344
+ it('if the etag does not match all the features are updated', () => {
345
+ const clonedDTO = getClonedDTO();
346
+
347
+ device.set('etag', 'etag-value');
348
+
349
+ const response = {
350
+ body: {
351
+ ...clonedDTO
352
+ },
353
+ headers: {
354
+ etag: 'different-etag-value'
355
+ }
356
+ };
357
+
358
+ checkFeatureNotPresent('developer', '1');
359
+ checkFeatureNotPresent('entitlement', '2');
360
+ checkFeatureNotPresent('user', '3');
361
+
362
+ device.processRegistrationSuccess(response);
363
+
364
+ checkFeature('developer', '1', true);
365
+ checkFeature('entitlement', '2', true);
366
+ checkFeature('user', '3', true);
367
+
368
+ // confirm that the new etag is set
369
+ assert.equal(device.get('etag'), 'different-etag-value');
370
+
371
+ const newClonedDTO = getClonedDTO({
372
+ developer: [
373
+ {
374
+ key: '1',
375
+ type: 'boolean',
376
+ val: 'false',
377
+ value: false,
378
+ mutable: true,
379
+ lastModified: '2015-06-29T20:02:48.033Z'
380
+ },
381
+ ],
382
+ entitlement: [
383
+ {
384
+ key: '2',
385
+ val: 'false',
386
+ value: false,
387
+ mutable: false
388
+ }
389
+ ],
390
+ user: [
391
+ {
392
+ key: '3',
393
+ val: 'false',
394
+ value: false,
395
+ mutable: true
396
+ }
397
+ ],
398
+ });
399
+
400
+
401
+ const newResponse = {
402
+ body: {
403
+ ...newClonedDTO
404
+ },
405
+ headers: {
406
+ etag: 'different-etag-value'
407
+ }
408
+ };
409
+
410
+ device.processRegistrationSuccess(newResponse);
411
+
412
+ // only the entitlement and user features should have been changed to false
413
+ checkFeature('developer', '1', true);
414
+ checkFeature('entitlement', '2', false);
415
+ checkFeature('user', '3', false);
416
+ });
417
+ });
181
418
  });
182
419
  });