| // Copyright 2026 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import '../../ui/components/report_view/report_view.js'; |
| import '../../ui/legacy/components/data_grid/data_grid.js'; |
| |
| import type * as Common from '../../core/common/common.js'; |
| import * as i18n from '../../core/i18n/i18n.js'; |
| import * as Protocol from '../../generated/protocol.js'; |
| import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js'; |
| import * as UI from '../../ui/legacy/legacy.js'; |
| import {Directives, html, nothing, render, type TemplateResult} from '../../ui/lit/lit.js'; |
| import * as VisualLogging from '../../ui/visual_logging/visual_logging.js'; |
| |
| import { |
| DeviceBoundSessionModelEvents, |
| type DeviceBoundSessionsModel, |
| type SessionAndEvents |
| } from './DeviceBoundSessionsModel.js'; |
| import deviceBoundSessionsViewStyles from './deviceBoundSessionsView.css.js'; |
| const {widgetConfig} = UI.Widget; |
| |
| const UIStrings = { |
| /** |
| *@description Label for a site, e.g. https://example.com/. |
| */ |
| keySite: 'Site', |
| /** |
| *@description Label for the ID of a session. |
| */ |
| keyId: 'ID', |
| /** |
| *@description Label that shows the URL that can be used to refresh a session. |
| */ |
| refreshUrl: 'Refresh URL', |
| /** |
| *@description Section header for how a session's scope is defined. |
| */ |
| scope: 'Scope', |
| /** |
| *@description Section header for HTTP cookies. |
| */ |
| cookieCravings: 'Cookies', |
| /** |
| *@description Label for the name of an HTTP cookie. |
| */ |
| name: 'Name', |
| /** |
| *@description Label for an expiration date. |
| */ |
| expiryDate: 'Expiry date', |
| /** |
| *@description Label for a cryptographic string challenge that has been cached for a session. |
| */ |
| cachedChallenge: 'Cached challenge', |
| /** |
| *@description Label for the HTTP initiator that is allowed to trigger a refresh of a session. |
| */ |
| allowedRefreshInitiators: 'Allowed refresh initiators', |
| /** |
| *@description Section header for a session's basic configuration. |
| */ |
| sessionConfig: 'Session config', |
| /** |
| *@description Label for an HTTP origin. |
| */ |
| origin: 'Origin', |
| /** |
| *@description Text for whether a site is included. |
| */ |
| includeSite: 'Include site', |
| /** |
| *@description Value for a label that indicates that a site is included. |
| */ |
| yes: 'Yes', |
| /** |
| *@description Value for a label that indicates that a site is not included. |
| */ |
| no: 'No', |
| /** |
| *@description Label the host pattern of a URL, e.g. *.example.com |
| */ |
| ruleHostPattern: 'Host pattern', |
| /** |
| *@description Label for the path prefix of a URL, e.g. /path/1/2/3 |
| */ |
| rulePathPrefix: 'Path prefix', |
| /** |
| *@description The type of a rule. The possible types are "exclude" or "include". |
| */ |
| ruleType: 'Rule type', |
| /** |
| *@description Text describing that a rule excludes something. |
| */ |
| ruleTypeExclude: 'Exclude', |
| /** |
| *@description Text describing that a rule includes something. |
| */ |
| ruleTypeInclude: 'Include', |
| /** |
| *@description Label for an event that has created something. |
| */ |
| creation: 'Creation', |
| /** |
| *@description Label for an event that has refreshed something. |
| */ |
| refresh: 'Refresh', |
| /** |
| *@description Label for an event that has set a cryptographic string challenge. |
| */ |
| challenge: 'Challenge', |
| /** |
| *@description Label for an event that has terminated something. |
| */ |
| termination: 'Termination', |
| /** |
| *@description Label for an event whose type is not known. |
| */ |
| unknown: 'Unknown', |
| /** |
| *@description Heading for a section that will display events that have occurred. |
| */ |
| events: 'Events', |
| /** |
| *@description Section header for details about an event. |
| */ |
| eventDetails: 'Event details', |
| /** |
| *@description Accessible label for the main area containing session details. |
| */ |
| sessionDetails: 'Session details', |
| /** |
| *@description Placeholder text when no row is selected in a table of events. |
| */ |
| selectEventToViewDetails: 'Select an event row to view more details.', |
| /** |
| *@description Column heading for the type of event that has occurred. |
| */ |
| type: 'Type', |
| /** |
| *@description Column heading for the date + time that an event occurred. |
| */ |
| timestamp: 'Date', |
| /** |
| *@description Column heading for the result of an event (whether it succeeded or had an error). |
| */ |
| result: 'Result', |
| /** |
| *@description Notes the result status of an event was that it succeeded. |
| */ |
| success: 'Success', |
| /** |
| *@description Notes the result status of an event was that it had an error. |
| */ |
| error: 'Error', |
| /** |
| *@description Default message when no events have appeared yet. |
| */ |
| noEvents: 'No events have been logged yet.', |
| /** |
| *@description Text to preserve the log of events after refreshing. |
| */ |
| preserveLog: 'Preserve log', |
| /** |
| *@description Tooltip text that appears on the preserve log setting when hovering over it. |
| */ |
| doNotClearLogOnPageReload: 'Do not clear log on page reload/navigation.', |
| /** |
| *@description Label for the ID of a session. |
| */ |
| sessionId: 'Session ID', |
| /** |
| *@description Label for the result of an event (whether it succeeded or had an error). |
| */ |
| eventResult: 'Event result', |
| /** |
| *@description Label for the result of fetching new session information. |
| */ |
| fetchResult: 'Fetch result', |
| /** |
| *@description Label for whether a session's basic configuration was updated. The corresponding value is yes or no. |
| */ |
| updatedSessionConfig: 'Updated session config', |
| /** |
| *@description Label for the result of an attempted refresh. |
| */ |
| refreshResult: 'Refresh result', |
| /** |
| *@description Label for whether a particular event caused any HTTP request to be deferred (i.e. paused and |
| * later unpaused). The corresponding value is yes or no. |
| */ |
| causedAnyRequestDeferrals: 'Caused any request deferrals', |
| /** |
| *@description Label for the result of attempting to set a cryptographic string challenge. |
| */ |
| challengeResult: 'Challenge result', |
| /** |
| *@description Label for the reason why a session was deleted. |
| */ |
| deletionReason: 'Deletion reason', |
| /** |
| *@description Label for the URL of a failed network request. |
| */ |
| failedRequestUrl: 'Failed request URL', |
| /** |
| *@description Label for the network error of a failed network request. |
| */ |
| failedRequestNetError: 'Net error', |
| /** |
| *@description Label for the HTTP response error code of a failed network request. |
| */ |
| failedRequestResponseCode: 'Response error code', |
| /** |
| *@description Label for the response body of a failed network request. |
| */ |
| failedRequestResponseBody: 'Response body', |
| /** |
| *@description Explanation for an event outcome. Key refers to a cryptographic key. |
| */ |
| keyError: 'Key error', |
| /** |
| *@description Explanation for an event outcome. Signing refers to cryptographic signing. |
| */ |
| signingError: 'Signing error', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| serverRequestedTermination: 'Server requested termination', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidSessionId: 'Invalid session ID', |
| /** |
| *@description Explanation for an event outcome. Challenge refers to a cryptographic string challenge. |
| */ |
| invalidChallenge: 'Invalid challenge', |
| /** |
| *@description Explanation for an event outcome. Challenge refers to a cryptographic string challenge. |
| */ |
| tooManyChallenges: 'Too many challenges', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidFetcherUrl: 'Invalid fetcher URL', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidRefreshUrl: 'Invalid refresh URL', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| transientHttpError: 'Transient HTTP error', |
| /** |
| *@description Explanation for an event outcome. This means there is a URL origin written into a session configuration's scope that is causing failures because it's for a different site. |
| */ |
| scopeOriginSameSiteMismatch: 'Same-site mismatch scope origin', |
| /** |
| *@description Explanation for an event outcome. This means the session configuration's URL for refreshing is causing failures because it's for a different site. |
| */ |
| refreshUrlSameSiteMismatch: 'Same-site mismatch refresh URL', |
| /** |
| *@description Explanation for an event outcome. This means the session configuration's session ID does not match the relevant session ID. |
| */ |
| mismatchedSessionId: 'Mismatched session ID', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| missingScope: 'Missing scope', |
| /** |
| *@description Explanation for an event outcome. This means the credentials field in the session configuration is missing. |
| */ |
| noCredentials: 'No credentials', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| subdomainRegistrationWellKnownUnavailable: 'Subdomain registration .well-known unavailable', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| subdomainRegistrationUnauthorized: '.well-known did not authorize registration by subdomain', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| subdomainRegistrationWellKnownMalformed: 'Subdomain registration .well-known content malformed', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| sessionProviderWellKnownUnavailable: 'Session provider .well-known unavailable', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| relyingPartyWellKnownUnavailable: 'Relying party .well-known unavailable', |
| /** |
| *@description Explanation for an event outcome. This refers to a JSON Web Key thumbprint (https://www.rfc-editor.org/rfc/rfc7638). Federated sessions are described in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| federatedKeyThumbprintMismatch: 'Federated key had incorrect thumbprint', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are described in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidFederatedSessionUrl: 'Federated provider URL not valid', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are described in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidFederatedKey: 'Federated key invalid', |
| /** |
| *@description Explanation for an event outcome. Origin labels are described in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| tooManyRelyingOriginLabels: 'Too many relying origin labels in .well-known', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| boundCookieSetForbidden: 'Registration in a context that cannot set bound cookies', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| netError: 'Network error', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| proxyError: 'Proxy error', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| emptySessionConfig: 'Empty session configuration for registration', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsConfig: 'Invalid credentials configuration', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsType: 'Invalid credentials - empty or non-cookie type', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsEmptyName: 'Invalid credentials - empty name', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookie: 'Invalid credentials - cookie invalid', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| persistentHttpError: 'Persistent HTTP error', |
| /** |
| *@description Explanation for an event outcome. Challenge refers to a cryptographic string challenge. |
| */ |
| registrationAttemptedChallenge: 'Registration returned challenge error response code', |
| /** |
| *@description Explanation for an event outcome. This refers to a URL's origin. |
| */ |
| invalidScopeOrigin: 'Invalid scope origin', |
| /** |
| *@description Explanation for an event outcome. This refers to an URL's path / origin. |
| */ |
| scopeOriginContainsPath: 'Scope origin contains a path', |
| /** |
| *@description Explanation for an event outcome. This refers to an HTTP request's initiator. |
| */ |
| refreshInitiatorNotString: 'Allowed refresh initiator is not a string', |
| /** |
| *@description Explanation for an event outcome. This refers to an HTTP request's initiator and a URL's host. |
| */ |
| refreshInitiatorInvalidHostPattern: 'Allowed refresh initiator has invalid host pattern', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidScopeSpecification: 'Invalid scope specification', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| missingScopeSpecificationType: 'Missing scope specification type', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| emptyScopeSpecificationDomain: 'Empty scope specification domain', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| emptyScopeSpecificationPath: 'Empty scope specification path', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidScopeSpecificationType: 'Scope specification type is neiher include or exclude', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidScopeIncludeSite: 'Invalid include_site in scope', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| missingScopeIncludeSite: 'Missing include_site in scope', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| federatedNotAuthorizedByProvider: 'Federated session not authorized by provider .well-known', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| federatedNotAuthorizedByRelyingParty: 'Federated session not authorized by relying party .well-known', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| sessionProviderWellKnownMalformed: 'Session provider .well-known content malformed', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| sessionProviderWellKnownHasProviderOrigin: 'Session provider .well-known content has provider_origin', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| relyingPartyWellKnownMalformed: 'Relying party .well-known content malformed', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| relyingPartyWellKnownHasRelyingOrigins: 'Relying party .well-known content has relying_origins', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidFederatedSessionProviderSessionMissing: 'Federated session invalid due to provider session not found', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidFederatedSessionWrongProviderOrigin: 'Federated session invalid due to provider origin mismatch', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookieCreationTime: 'Invalid credentials - cookie creation time invalid', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookieName: 'Invalid credentials - cookie name invalid', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookieParsing: 'Invalid credentials - cookie parsing failed', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookieUnpermittedAttribute: 'Invalid credentials - cookie attribute not permitted', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookieInvalidDomain: 'Invalid credentials - cookie invalid domain', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidCredentialsCookiePrefix: 'Invalid credentials - cookie invalid prefix', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidScopeRulePath: 'Invalid scope rule path', |
| /** |
| *@description Explanation for an event outcome. Scope specification is defined in https://w3c.github.io/webappsec-dbsc/. |
| */ |
| invalidScopeRuleHostPattern: 'Invalid scope rule host pattern', |
| /** |
| *@description Explanation for an event outcome. A session can be scoped to just a specific URL origin. This error means that the session's origin does not match the provided URL host pattern. |
| */ |
| scopeRuleOriginScopedHostPatternMismatch: 'Origin-scoped session has mismatch between host pattern and origin', |
| /** |
| *@description Explanation for an event outcome. A session can be scoped to an entire site. This error means that the session's site does not match the provided URL host pattern. |
| */ |
| scopeRuleSiteScopedHostPatternMismatch: 'Site-scoped session has mismatch between host pattern and site', |
| /** |
| *@description Explanation for an event outcome. This refers to cryptographic signing. |
| */ |
| signingQuotaExceeded: 'Signing quota exceeded', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidConfigJson: 'Invalid session configuration JSON', |
| /** |
| *@description Explanation for an event outcome. Federated sessions are defined in https://w3c.github.io/webappsec-dbsc/. Key refers to a cryptographic key. |
| */ |
| invalidFederatedSessionProviderFailedToRestoreKey: |
| 'Federated session invalid due to failure to restore session provider key', |
| /** |
| *@description Explanation for an event outcome. Key refers to a cryptographic key. |
| */ |
| failedToUnwrapKey: 'Failed to unwrap key', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| sessionDeletedDuringRefresh: 'Session deleted during refresh', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| refreshed: 'Refreshed', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| initializedService: 'Service initialized', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| unreachable: 'Endpoint unreachable', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| serverError: 'Endpoint transient error', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| refreshQuotaExceeded: 'Refresh quota exceeded', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| fatalError: 'Fatal error', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| noSessionId: 'No session ID', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| noSessionMatch: 'No matching session ID', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| cantSetBoundCookie: 'Not allowed to set bound cookie', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| expired: 'Expired', |
| /** |
| *@description Explanation for an event outcome. Key refers to a cryptographic key. This means there was an attempt to read a key from disk but it failed. |
| */ |
| failedToRestoreKey: 'Failed to restore key from disk', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| storagePartitionCleared: 'Removed from storage partition', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| clearBrowsingData: 'User-initiated browser data removal', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| invalidSessionParams: 'Invalid session parameters', |
| /** |
| *@description Explanation for an event outcome. |
| */ |
| refreshFatalError: 'Fatal error during refresh', |
| } as const; |
| |
| const str_ = i18n.i18n.registerUIStrings('panels/application/DeviceBoundSessionsView.ts', UIStrings); |
| const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); |
| |
| interface ViewInput { |
| sessionAndEvents?: SessionAndEvents; |
| preserveLogSetting?: Common.Settings.Setting<boolean>; |
| defaultTitle?: string; |
| defaultDescription?: string; |
| selectedEvent?: Protocol.Network.DeviceBoundSessionEventOccurredEvent; |
| onEventRowSelected?(selectedEvent?: Protocol.Network.DeviceBoundSessionEventOccurredEvent|undefined): void; |
| } |
| |
| type ViewOutput = object; |
| |
| export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTMLElement): void => { |
| const {sessionAndEvents, preserveLogSetting, defaultTitle, defaultDescription, selectedEvent, onEventRowSelected} = |
| input; |
| |
| const toolbarHtml = preserveLogSetting ? |
| html` |
| <devtools-toolbar class="device-bound-sessions-toolbar"> |
| <devtools-checkbox title=${i18nString(UIStrings.doNotClearLogOnPageReload)} ${ |
| UI.UIUtils.bindToSetting(preserveLogSetting)}>${i18nString(UIStrings.preserveLog)}</devtools-checkbox> |
| </devtools-toolbar> |
| ` : |
| nothing; |
| |
| if (!sessionAndEvents) { |
| if (!defaultTitle || !defaultDescription) { |
| render(nothing, target); |
| return; |
| } |
| render( |
| html` |
| <style>${UI.inspectorCommonStyles}</style> |
| <style>${deviceBoundSessionsViewStyles}</style> |
| ${toolbarHtml} |
| <devtools-widget .widgetConfig=${widgetConfig(UI.EmptyWidget.EmptyWidget, { |
| header: defaultTitle, |
| text: defaultDescription |
| })} jslog=${VisualLogging.pane('device-bound-sessions-empty')}></devtools-widget> |
| `, |
| target); |
| return; |
| } |
| |
| let sessionDetailsHtml: TemplateResult|undefined; |
| if (sessionAndEvents.session) { |
| const {key, inclusionRules, cookieCravings} = sessionAndEvents.session; |
| sessionDetailsHtml = html` |
| <devtools-report> |
| <devtools-report-section-header role="heading" aria-level="2">${ |
| i18nString(UIStrings.sessionConfig)}</devtools-report-section-header> |
| <devtools-report-key>${i18nString(UIStrings.keySite)}</devtools-report-key> |
| <devtools-report-value>${key.site}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.keyId)}</devtools-report-key> |
| <devtools-report-value>${key.id}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.refreshUrl)}</devtools-report-key> |
| <devtools-report-value>${sessionAndEvents.session.refreshUrl}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.expiryDate)}</devtools-report-key> |
| <devtools-report-value>${ |
| new Date(sessionAndEvents.session.expiryDate * 1000).toLocaleString()}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.cachedChallenge)}</devtools-report-key> |
| <devtools-report-value>${sessionAndEvents.session.cachedChallenge || ''}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.allowedRefreshInitiators)}</devtools-report-key> |
| <devtools-report-value>${sessionAndEvents.session.allowedRefreshInitiators.join(', ')}</devtools-report-value> |
| <devtools-report-section-header role="heading" aria-level="2">${ |
| i18nString(UIStrings.scope)}</devtools-report-section-header> |
| <devtools-report-key>${i18nString(UIStrings.origin)}</devtools-report-key> |
| <devtools-report-value>${inclusionRules.origin}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.includeSite)}</devtools-report-key> |
| <devtools-report-value>${boolToString(inclusionRules.includeSite)}</devtools-report-value> |
| </devtools-report> |
| ${ |
| inclusionRules.urlRules.length > 0 ? html` |
| <div class="device-bound-session-grid-wrapper"> |
| <devtools-data-grid class="device-bound-session-url-rules-grid" striped inline name=${ |
| i18nString(UIStrings.scope)}> |
| <table> |
| <thead> |
| <tr> |
| <th id="should-include" sortable>${i18nString(UIStrings.ruleType)}</th> |
| <th id="host-pattern" sortable>${i18nString(UIStrings.ruleHostPattern)}</th> |
| <th id="path-prefix" sortable>${i18nString(UIStrings.rulePathPrefix)}</th> |
| </tr> |
| </thead> |
| <tbody> |
| ${inclusionRules.urlRules.map(rule => html` |
| <tr> |
| <td>${ruleTypeToString(rule.ruleType)}</td> |
| <td>${rule.hostPattern}</td> |
| <td>${rule.pathPrefix}</td> |
| </tr> |
| `)} |
| </tbody> |
| </table> |
| </devtools-data-grid> |
| </div> |
| ` : |
| nothing} |
| <devtools-report-section-header role="heading" aria-level="2">${ |
| i18nString(UIStrings.cookieCravings)}</devtools-report-section-header> |
| ${ |
| cookieCravings.length > 0 ? html` |
| <div class="device-bound-session-grid-wrapper"> |
| <devtools-data-grid class="device-bound-session-cookie-cravings-grid" striped inline name=${ |
| i18nString(UIStrings.cookieCravings)}> |
| <table> |
| <thead> |
| <tr> |
| <th id="name" sortable>${i18nString(UIStrings.name)}</th> |
| <th id="domain" sortable>${i18n.i18n.lockedString('Domain')}</th> |
| <th id="path" sortable>${i18n.i18n.lockedString('Path')}</th> |
| <th id="secure" type="boolean" align="center" sortable>${i18n.i18n.lockedString('Secure')}</th> |
| <th id="http-only" type="boolean" align="center" sortable>${i18n.i18n.lockedString('HttpOnly')}</th> |
| <th id="same-site" sortable>${i18n.i18n.lockedString('SameSite')}</th> |
| </tr> |
| </thead> |
| <tbody> |
| ${cookieCravings.map(craving => html` |
| <tr> |
| <td>${craving.name}</td> |
| <td>${craving.domain}</td> |
| <td>${craving.path}</td> |
| <td>${craving.secure}</td> |
| <td>${craving.httpOnly}</td> |
| <td>${craving.sameSite}</td> |
| </tr> |
| `)} |
| </tbody> |
| </table> |
| </devtools-data-grid> |
| </div> |
| ` : |
| nothing}`; |
| } |
| const events = [...sessionAndEvents.eventsById.values()]; |
| const eventsHtml = html` |
| <devtools-report-section-header role="heading" aria-level="2">${ |
| i18nString(UIStrings.events)}</devtools-report-section-header> |
| ${ |
| events.length > 0 && onEventRowSelected ? |
| html` |
| <div class="device-bound-session-grid-wrapper"> |
| <devtools-data-grid class="device-bound-session-events-grid" striped inline name=${ |
| i18nString(UIStrings.events)} ${Directives.ref((el?: Element) => { |
| if (!el || !(el instanceof HTMLElement)) { |
| return; |
| } |
| const grid = el as HTMLElement & {deselectRow(): void}; |
| if (!selectedEvent) { |
| grid.deselectRow(); |
| } |
| })}> |
| <table> |
| <thead> |
| <tr> |
| <th id="type" sortable>${i18nString(UIStrings.type)}</th> |
| <th id="timestamp" sortable>${i18nString(UIStrings.timestamp)}</th> |
| <th id="details" sortable>${i18nString(UIStrings.result)}</th> |
| </tr> |
| </thead> |
| <tbody>${events.map(({event, timestamp}) => html` |
| <tr @select=${(): void => onEventRowSelected(event)}> |
| <td>${getEventTypeString(event)}</td> |
| <td>${timestamp.toLocaleString()}</td> |
| <td>${succeededToString(event.succeeded)}</td> |
| </tr> |
| `)} |
| </tbody> |
| </table> |
| </devtools-data-grid> |
| </div> |
| ` : |
| html`<div class="device-bound-session-no-events-wrapper">${i18nString(UIStrings.noEvents)}</div>`}`; |
| |
| const failedRequestDetailsGetter = |
| (failedRequest?: Protocol.Network.DeviceBoundSessionFailedRequest): TemplateResult|typeof nothing => { |
| if (!failedRequest) { |
| return nothing; |
| } |
| return html`${failedRequest.requestUrl && html` |
| <devtools-report-key>${i18nString(UIStrings.failedRequestUrl)}</devtools-report-key> |
| <devtools-report-value>${failedRequest.requestUrl}</devtools-report-value> |
| `} |
| ${failedRequest.netError && html` |
| <devtools-report-key>${i18nString(UIStrings.failedRequestNetError)}</devtools-report-key> |
| <devtools-report-value>${failedRequest.netError}</devtools-report-value> |
| `} |
| ${ |
| failedRequest.responseError !== undefined ? html` |
| <devtools-report-key>${i18nString(UIStrings.failedRequestResponseCode)}</devtools-report-key> |
| <devtools-report-value>${failedRequest.responseError}</devtools-report-value> |
| ` : |
| nothing} |
| ${failedRequest.responseErrorBody && html` |
| <devtools-report-key>${i18nString(UIStrings.failedRequestResponseBody)}</devtools-report-key> |
| <devtools-report-value> |
| <devtools-widget .widgetConfig=${UI.Widget.widgetConfig(SourceFrame.JSONView.SearchableJsonView, { |
| jsonObject: tryParseJson(failedRequest.responseErrorBody), |
| })}></devtools-widget> |
| </devtools-report-value> |
| `}`; |
| }; |
| |
| const creationEventDetails = |
| selectedEvent?.creationEventDetails && |
| html` |
| <devtools-report-key>${i18nString(UIStrings.fetchResult)}</devtools-report-key> |
| <devtools-report-value>${ |
| fetchResultToString(selectedEvent.creationEventDetails.fetchResult)}</devtools-report-value> |
| ${selectedEvent.creationEventDetails.newSession && html` |
| <devtools-report-key>${i18nString(UIStrings.updatedSessionConfig)}</devtools-report-key> |
| <devtools-report-value>${i18nString(UIStrings.yes)}</devtools-report-value> |
| `} |
| ${failedRequestDetailsGetter(selectedEvent.creationEventDetails.failedRequest)} |
| `; |
| const refreshEventDetails = |
| selectedEvent?.refreshEventDetails && |
| html` |
| <devtools-report-key>${i18nString(UIStrings.refreshResult)}</devtools-report-key> |
| <devtools-report-value>${ |
| refreshResultToString(selectedEvent.refreshEventDetails.refreshResult)}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.causedAnyRequestDeferrals)}</devtools-report-key> |
| <devtools-report-value>${ |
| boolToString(!selectedEvent.refreshEventDetails.wasFullyProactiveRefresh)}</devtools-report-value> |
| ${ |
| selectedEvent.refreshEventDetails.fetchResult && |
| html` |
| <devtools-report-key>${i18nString(UIStrings.fetchResult)}</devtools-report-key> |
| <devtools-report-value>${ |
| fetchResultToString(selectedEvent.refreshEventDetails.fetchResult)}</devtools-report-value> |
| `} |
| ${selectedEvent.refreshEventDetails.newSession && html` |
| <devtools-report-key>${i18nString(UIStrings.updatedSessionConfig)}</devtools-report-key> |
| <devtools-report-value>${i18nString(UIStrings.yes)}</devtools-report-value> |
| `} |
| ${failedRequestDetailsGetter(selectedEvent.refreshEventDetails.failedRequest)} |
| `; |
| const challengeEventDetails = |
| selectedEvent?.challengeEventDetails && |
| html` |
| <devtools-report-key>${i18nString(UIStrings.challengeResult)}</devtools-report-key> |
| <devtools-report-value>${ |
| challengeResultToString(selectedEvent.challengeEventDetails.challengeResult)}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.challenge)}</devtools-report-key> |
| <devtools-report-value>${selectedEvent.challengeEventDetails.challenge}</devtools-report-value> |
| `; |
| const terminationEventDetails = |
| selectedEvent?.terminationEventDetails && |
| html` |
| <devtools-report-key>${i18nString(UIStrings.deletionReason)}</devtools-report-key> |
| <devtools-report-value>${ |
| deletionReasonToString(selectedEvent.terminationEventDetails.deletionReason)}</devtools-report-value> |
| `; |
| const eventDetailsContentHtml = selectedEvent ? |
| html` |
| <devtools-report> |
| <devtools-report-key>${i18nString(UIStrings.keySite)}</devtools-report-key> |
| <devtools-report-value>${selectedEvent.site}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.sessionId)}</devtools-report-key> |
| <devtools-report-value>${selectedEvent.sessionId}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.type)}</devtools-report-key> |
| <devtools-report-value>${getEventTypeString(selectedEvent)}</devtools-report-value> |
| <devtools-report-key>${i18nString(UIStrings.eventResult)}</devtools-report-key> |
| <devtools-report-value>${succeededToString(selectedEvent.succeeded)}</devtools-report-value> |
| ${creationEventDetails} |
| ${refreshEventDetails} |
| ${challengeEventDetails} |
| ${terminationEventDetails} |
| </devtools-report> |
| ` : |
| html`<div class="device-bound-session-no-event-details">${i18nString(UIStrings.selectEventToViewDetails)}</div>`; |
| const eventDetailsHtml = html` |
| <devtools-report-section-header role="heading" aria-level="2">${ |
| i18nString(UIStrings.eventDetails)}</devtools-report-section-header> |
| ${eventDetailsContentHtml} |
| `; |
| |
| render( |
| html` |
| <style>${UI.inspectorCommonStyles}</style> |
| <style>${deviceBoundSessionsViewStyles}</style> |
| ${toolbarHtml} |
| <devtools-split-view sidebar-position="second"> |
| <div slot="main" class="device-bound-session-view-wrapper" role="region" aria-label=${ |
| i18nString(UIStrings.sessionDetails)}> |
| ${sessionDetailsHtml || nothing} |
| ${eventsHtml} |
| </div> |
| <div slot="sidebar" class="device-bound-session-sidebar" role="region" aria-label=${ |
| i18nString(UIStrings.eventDetails)}> |
| ${eventDetailsHtml} |
| </div> |
| </devtools-split-view>`, |
| target); |
| }; |
| |
| export class DeviceBoundSessionsView extends UI.Widget.VBox { |
| #site?: string; |
| #sessionId?: string; |
| #model?: DeviceBoundSessionsModel; |
| #view: typeof DEFAULT_VIEW; |
| #defaultTitle?: string; |
| #defaultDescription?: string; |
| #selectedEvent?: Protocol.Network.DeviceBoundSessionEventOccurredEvent; |
| |
| constructor(view: typeof DEFAULT_VIEW = DEFAULT_VIEW) { |
| super({jslog: `${VisualLogging.pane('device-bound-sessions')}`}); |
| this.#view = view; |
| } |
| |
| showSession(model: DeviceBoundSessionsModel, site: string, sessionId?: string): void { |
| this.#defaultTitle = undefined; |
| this.#defaultDescription = undefined; |
| this.#site = site; |
| this.#sessionId = sessionId; |
| this.#attachModel(model); |
| this.performUpdate(); |
| } |
| |
| showDefault(model: DeviceBoundSessionsModel, defaultTitle: string, defaultDescription: string): void { |
| this.#defaultTitle = defaultTitle; |
| this.#defaultDescription = defaultDescription; |
| this.#site = undefined; |
| this.#sessionId = undefined; |
| this.#attachModel(model); |
| this.performUpdate(); |
| } |
| |
| #attachModel(model: DeviceBoundSessionsModel): void { |
| if (this.#model) { |
| this.#model.removeEventListener(DeviceBoundSessionModelEvents.EVENT_OCCURRED, this.performUpdate, this); |
| this.#model.removeEventListener(DeviceBoundSessionModelEvents.CLEAR_EVENTS, this.performUpdate, this); |
| } |
| this.#model = model; |
| this.#model.addEventListener(DeviceBoundSessionModelEvents.EVENT_OCCURRED, this.performUpdate, this); |
| this.#model.addEventListener(DeviceBoundSessionModelEvents.CLEAR_EVENTS, this.performUpdate, this); |
| if (this.#selectedEvent) { |
| this.#selectedEvent = undefined; |
| } |
| } |
| |
| override performUpdate(): void { |
| let sessionAndEvents: SessionAndEvents|undefined; |
| let preserveLogSetting: Common.Settings.Setting<boolean>|undefined; |
| |
| if (this.#model) { |
| preserveLogSetting = this.#model.getPreserveLogSetting(); |
| if (this.#site) { |
| sessionAndEvents = this.#model.getSession(this.#site, this.#sessionId); |
| } |
| } |
| |
| this.#view( |
| { |
| sessionAndEvents, |
| preserveLogSetting, |
| defaultTitle: this.#defaultTitle, |
| defaultDescription: this.#defaultDescription, |
| selectedEvent: this.#selectedEvent, |
| onEventRowSelected: this.#onEventRowSelected.bind(this), |
| }, |
| {}, this.contentElement); |
| } |
| |
| #onEventRowSelected(selectedEvent?: Protocol.Network.DeviceBoundSessionEventOccurredEvent): void { |
| this.#selectedEvent = selectedEvent; |
| this.performUpdate(); |
| } |
| } |
| |
| function ruleTypeToString(ruleType: Protocol.Network.DeviceBoundSessionUrlRuleRuleType): string { |
| switch (ruleType) { |
| case Protocol.Network.DeviceBoundSessionUrlRuleRuleType.Exclude: |
| return i18nString(UIStrings.ruleTypeExclude); |
| case Protocol.Network.DeviceBoundSessionUrlRuleRuleType.Include: |
| return i18nString(UIStrings.ruleTypeInclude); |
| default: |
| return ruleType; |
| } |
| } |
| function getEventTypeString(event: Protocol.Network.DeviceBoundSessionEventOccurredEvent): string { |
| if (event.creationEventDetails) { |
| return i18nString(UIStrings.creation); |
| } |
| if (event.refreshEventDetails) { |
| return i18nString(UIStrings.refresh); |
| } |
| if (event.challengeEventDetails) { |
| return i18nString(UIStrings.challenge); |
| } |
| if (event.terminationEventDetails) { |
| return i18nString(UIStrings.termination); |
| } |
| return i18nString(UIStrings.unknown); |
| } |
| |
| function fetchResultToString(fetchResult: Protocol.Network.DeviceBoundSessionFetchResult): string { |
| switch (fetchResult) { |
| case Protocol.Network.DeviceBoundSessionFetchResult.Success: |
| return i18nString(UIStrings.success); |
| case Protocol.Network.DeviceBoundSessionFetchResult.KeyError: |
| return i18nString(UIStrings.keyError); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SigningError: |
| return i18nString(UIStrings.signingError); |
| case Protocol.Network.DeviceBoundSessionFetchResult.ServerRequestedTermination: |
| return i18nString(UIStrings.serverRequestedTermination); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidSessionId: |
| return i18nString(UIStrings.invalidSessionId); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidChallenge: |
| return i18nString(UIStrings.invalidChallenge); |
| case Protocol.Network.DeviceBoundSessionFetchResult.TooManyChallenges: |
| return i18nString(UIStrings.tooManyChallenges); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidFetcherUrl: |
| return i18nString(UIStrings.invalidFetcherUrl); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidRefreshUrl: |
| return i18nString(UIStrings.invalidRefreshUrl); |
| case Protocol.Network.DeviceBoundSessionFetchResult.TransientHttpError: |
| return i18nString(UIStrings.transientHttpError); |
| case Protocol.Network.DeviceBoundSessionFetchResult.ScopeOriginSameSiteMismatch: |
| return i18nString(UIStrings.scopeOriginSameSiteMismatch); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RefreshUrlSameSiteMismatch: |
| return i18nString(UIStrings.refreshUrlSameSiteMismatch); |
| case Protocol.Network.DeviceBoundSessionFetchResult.MismatchedSessionId: |
| return i18nString(UIStrings.mismatchedSessionId); |
| case Protocol.Network.DeviceBoundSessionFetchResult.MissingScope: |
| return i18nString(UIStrings.missingScope); |
| case Protocol.Network.DeviceBoundSessionFetchResult.NoCredentials: |
| return i18nString(UIStrings.noCredentials); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SubdomainRegistrationWellKnownUnavailable: |
| return i18nString(UIStrings.subdomainRegistrationWellKnownUnavailable); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SubdomainRegistrationUnauthorized: |
| return i18nString(UIStrings.subdomainRegistrationUnauthorized); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SubdomainRegistrationWellKnownMalformed: |
| return i18nString(UIStrings.subdomainRegistrationWellKnownMalformed); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SessionProviderWellKnownUnavailable: |
| return i18nString(UIStrings.sessionProviderWellKnownUnavailable); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RelyingPartyWellKnownUnavailable: |
| return i18nString(UIStrings.relyingPartyWellKnownUnavailable); |
| case Protocol.Network.DeviceBoundSessionFetchResult.FederatedKeyThumbprintMismatch: |
| return i18nString(UIStrings.federatedKeyThumbprintMismatch); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidFederatedSessionUrl: |
| return i18nString(UIStrings.invalidFederatedSessionUrl); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidFederatedKey: |
| return i18nString(UIStrings.invalidFederatedKey); |
| case Protocol.Network.DeviceBoundSessionFetchResult.TooManyRelyingOriginLabels: |
| return i18nString(UIStrings.tooManyRelyingOriginLabels); |
| case Protocol.Network.DeviceBoundSessionFetchResult.BoundCookieSetForbidden: |
| return i18nString(UIStrings.boundCookieSetForbidden); |
| case Protocol.Network.DeviceBoundSessionFetchResult.NetError: |
| return i18nString(UIStrings.netError); |
| case Protocol.Network.DeviceBoundSessionFetchResult.ProxyError: |
| return i18nString(UIStrings.proxyError); |
| case Protocol.Network.DeviceBoundSessionFetchResult.EmptySessionConfig: |
| return i18nString(UIStrings.emptySessionConfig); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsConfig: |
| return i18nString(UIStrings.invalidCredentialsConfig); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsType: |
| return i18nString(UIStrings.invalidCredentialsType); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsEmptyName: |
| return i18nString(UIStrings.invalidCredentialsEmptyName); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookie: |
| return i18nString(UIStrings.invalidCredentialsCookie); |
| case Protocol.Network.DeviceBoundSessionFetchResult.PersistentHttpError: |
| return i18nString(UIStrings.persistentHttpError); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RegistrationAttemptedChallenge: |
| return i18nString(UIStrings.registrationAttemptedChallenge); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidScopeOrigin: |
| return i18nString(UIStrings.invalidScopeOrigin); |
| case Protocol.Network.DeviceBoundSessionFetchResult.ScopeOriginContainsPath: |
| return i18nString(UIStrings.scopeOriginContainsPath); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RefreshInitiatorNotString: |
| return i18nString(UIStrings.refreshInitiatorNotString); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RefreshInitiatorInvalidHostPattern: |
| return i18nString(UIStrings.refreshInitiatorInvalidHostPattern); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidScopeSpecification: |
| return i18nString(UIStrings.invalidScopeSpecification); |
| case Protocol.Network.DeviceBoundSessionFetchResult.MissingScopeSpecificationType: |
| return i18nString(UIStrings.missingScopeSpecificationType); |
| case Protocol.Network.DeviceBoundSessionFetchResult.EmptyScopeSpecificationDomain: |
| return i18nString(UIStrings.emptyScopeSpecificationDomain); |
| case Protocol.Network.DeviceBoundSessionFetchResult.EmptyScopeSpecificationPath: |
| return i18nString(UIStrings.emptyScopeSpecificationPath); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidScopeSpecificationType: |
| return i18nString(UIStrings.invalidScopeSpecificationType); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidScopeIncludeSite: |
| return i18nString(UIStrings.invalidScopeIncludeSite); |
| case Protocol.Network.DeviceBoundSessionFetchResult.MissingScopeIncludeSite: |
| return i18nString(UIStrings.missingScopeIncludeSite); |
| case Protocol.Network.DeviceBoundSessionFetchResult.FederatedNotAuthorizedByProvider: |
| return i18nString(UIStrings.federatedNotAuthorizedByProvider); |
| case Protocol.Network.DeviceBoundSessionFetchResult.FederatedNotAuthorizedByRelyingParty: |
| return i18nString(UIStrings.federatedNotAuthorizedByRelyingParty); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SessionProviderWellKnownMalformed: |
| return i18nString(UIStrings.sessionProviderWellKnownMalformed); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SessionProviderWellKnownHasProviderOrigin: |
| return i18nString(UIStrings.sessionProviderWellKnownHasProviderOrigin); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RelyingPartyWellKnownMalformed: |
| return i18nString(UIStrings.relyingPartyWellKnownMalformed); |
| case Protocol.Network.DeviceBoundSessionFetchResult.RelyingPartyWellKnownHasRelyingOrigins: |
| return i18nString(UIStrings.relyingPartyWellKnownHasRelyingOrigins); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidFederatedSessionProviderSessionMissing: |
| return i18nString(UIStrings.invalidFederatedSessionProviderSessionMissing); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidFederatedSessionWrongProviderOrigin: |
| return i18nString(UIStrings.invalidFederatedSessionWrongProviderOrigin); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookieCreationTime: |
| return i18nString(UIStrings.invalidCredentialsCookieCreationTime); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookieName: |
| return i18nString(UIStrings.invalidCredentialsCookieName); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookieParsing: |
| return i18nString(UIStrings.invalidCredentialsCookieParsing); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookieUnpermittedAttribute: |
| return i18nString(UIStrings.invalidCredentialsCookieUnpermittedAttribute); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookieInvalidDomain: |
| return i18nString(UIStrings.invalidCredentialsCookieInvalidDomain); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidCredentialsCookiePrefix: |
| return i18nString(UIStrings.invalidCredentialsCookiePrefix); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidScopeRulePath: |
| return i18nString(UIStrings.invalidScopeRulePath); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidScopeRuleHostPattern: |
| return i18nString(UIStrings.invalidScopeRuleHostPattern); |
| case Protocol.Network.DeviceBoundSessionFetchResult.ScopeRuleOriginScopedHostPatternMismatch: |
| return i18nString(UIStrings.scopeRuleOriginScopedHostPatternMismatch); |
| case Protocol.Network.DeviceBoundSessionFetchResult.ScopeRuleSiteScopedHostPatternMismatch: |
| return i18nString(UIStrings.scopeRuleSiteScopedHostPatternMismatch); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SigningQuotaExceeded: |
| return i18nString(UIStrings.signingQuotaExceeded); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidConfigJson: |
| return i18nString(UIStrings.invalidConfigJson); |
| case Protocol.Network.DeviceBoundSessionFetchResult.InvalidFederatedSessionProviderFailedToRestoreKey: |
| return i18nString(UIStrings.invalidFederatedSessionProviderFailedToRestoreKey); |
| case Protocol.Network.DeviceBoundSessionFetchResult.FailedToUnwrapKey: |
| return i18nString(UIStrings.failedToUnwrapKey); |
| case Protocol.Network.DeviceBoundSessionFetchResult.SessionDeletedDuringRefresh: |
| return i18nString(UIStrings.sessionDeletedDuringRefresh); |
| default: |
| return fetchResult; |
| } |
| } |
| |
| function refreshResultToString(refreshResult: Protocol.Network.RefreshEventDetailsRefreshResult): string { |
| switch (refreshResult) { |
| case Protocol.Network.RefreshEventDetailsRefreshResult.Refreshed: |
| return i18nString(UIStrings.refreshed); |
| case Protocol.Network.RefreshEventDetailsRefreshResult.InitializedService: |
| return i18nString(UIStrings.initializedService); |
| case Protocol.Network.RefreshEventDetailsRefreshResult.Unreachable: |
| return i18nString(UIStrings.unreachable); |
| case Protocol.Network.RefreshEventDetailsRefreshResult.ServerError: |
| return i18nString(UIStrings.serverError); |
| case Protocol.Network.RefreshEventDetailsRefreshResult.RefreshQuotaExceeded: |
| return i18nString(UIStrings.refreshQuotaExceeded); |
| case Protocol.Network.RefreshEventDetailsRefreshResult.FatalError: |
| return i18nString(UIStrings.fatalError); |
| case Protocol.Network.RefreshEventDetailsRefreshResult.SigningQuotaExceeded: |
| return i18nString(UIStrings.signingQuotaExceeded); |
| default: |
| return refreshResult; |
| } |
| } |
| |
| function challengeResultToString(challengeResult: Protocol.Network.ChallengeEventDetailsChallengeResult): string { |
| switch (challengeResult) { |
| case Protocol.Network.ChallengeEventDetailsChallengeResult.Success: |
| return i18nString(UIStrings.success); |
| case Protocol.Network.ChallengeEventDetailsChallengeResult.NoSessionId: |
| return i18nString(UIStrings.noSessionId); |
| case Protocol.Network.ChallengeEventDetailsChallengeResult.NoSessionMatch: |
| return i18nString(UIStrings.noSessionMatch); |
| case Protocol.Network.ChallengeEventDetailsChallengeResult.CantSetBoundCookie: |
| return i18nString(UIStrings.cantSetBoundCookie); |
| default: |
| return challengeResult; |
| } |
| } |
| |
| function deletionReasonToString(deletionReason: Protocol.Network.TerminationEventDetailsDeletionReason): string { |
| switch (deletionReason) { |
| case Protocol.Network.TerminationEventDetailsDeletionReason.Expired: |
| return i18nString(UIStrings.expired); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.FailedToRestoreKey: |
| return i18nString(UIStrings.failedToRestoreKey); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.FailedToUnwrapKey: |
| return i18nString(UIStrings.failedToUnwrapKey); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.StoragePartitionCleared: |
| return i18nString(UIStrings.storagePartitionCleared); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.ClearBrowsingData: |
| return i18nString(UIStrings.clearBrowsingData); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.ServerRequested: |
| return i18nString(UIStrings.serverRequestedTermination); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.InvalidSessionParams: |
| return i18nString(UIStrings.invalidSessionParams); |
| case Protocol.Network.TerminationEventDetailsDeletionReason.RefreshFatalError: |
| return i18nString(UIStrings.refreshFatalError); |
| default: |
| return deletionReason; |
| } |
| } |
| |
| function boolToString(bool: boolean): string { |
| return bool ? i18nString(UIStrings.yes) : i18nString(UIStrings.no); |
| } |
| |
| function succeededToString(succeeded: boolean): string { |
| return succeeded ? i18nString(UIStrings.success) : i18nString(UIStrings.error); |
| } |
| |
| function tryParseJson(body: string): object { |
| let parsedBody; |
| try { |
| parsedBody = JSON.parse(body); |
| } catch { |
| return {body}; |
| } |
| |
| if (typeof parsedBody === 'object' && parsedBody !== null) { |
| return parsedBody; |
| } |
| return {body: parsedBody}; |
| } |