| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import {assert, assertNotReached} from '//resources/js/assert.js'; |
| |
| import type {App, Permission} from './app_management.mojom-webui.js'; |
| import {PermissionType, TriState} from './app_management.mojom-webui.js'; |
| import {BrowserProxy} from './browser_proxy.js'; |
| import {AppManagementUserAction, AppType} from './constants.js'; |
| import type {PermissionTypeIndex} from './permission_constants.js'; |
| import {isBoolValue, isPermissionEnabled, isTriStateValue} from './permission_util.js'; |
| |
| /** |
| * @fileoverview Utility functions for the App Management page. |
| */ |
| |
| interface AppManagementPageState { |
| apps: Record<string, App>; |
| selectedAppId: string|null; |
| // Maps all apps to their parent's app ID. Apps without a parent are |
| // not listed in this map. |
| subAppToParentAppId: Record<string, string>; |
| } |
| |
| export function createEmptyState(): AppManagementPageState { |
| return { |
| apps: {}, |
| selectedAppId: null, |
| subAppToParentAppId: {}, |
| }; |
| } |
| |
| export function createInitialState( |
| apps: App[], |
| subAppToParentAppId: {[key: string]: string}): AppManagementPageState { |
| const initialState = createEmptyState(); |
| |
| for (const app of apps) { |
| initialState.apps[app.id] = app; |
| } |
| |
| initialState.subAppToParentAppId = subAppToParentAppId; |
| |
| return initialState; |
| } |
| |
| export function getAppIcon(app: App): string { |
| return `chrome://app-icon/${app.id}/64`; |
| } |
| |
| export function getPermissionValueBool( |
| app: App, permissionType: PermissionTypeIndex): boolean { |
| const permission = getPermission(app, permissionType); |
| assert(permission); |
| |
| return isPermissionEnabled(permission.value); |
| } |
| |
| /** |
| * Returns the TriState value of a permission. If the permission value is not |
| * already a TriState, it will be converted based on the boolean value. |
| */ |
| export function getPermissionValueAsTriState( |
| app: App, permissionType: PermissionTypeIndex): TriState { |
| const permission = getPermission(app, permissionType); |
| assert(permission); |
| |
| if (isTriStateValue(permission.value)) { |
| return permission.value.tristateValue!; |
| } |
| |
| if (isBoolValue(permission.value)) { |
| return permission.value.boolValue!? TriState.kAllow : TriState.kBlock; |
| } |
| |
| assertNotReached(); |
| } |
| |
| /** |
| * Undefined is returned when the app does not request a permission. |
| */ |
| export function getPermission( |
| app: App, permissionType: PermissionTypeIndex): Permission|undefined { |
| return app.permissions[PermissionType[permissionType]]; |
| } |
| |
| export function getSelectedApp(state: AppManagementPageState): App|null { |
| const selectedAppId = state.selectedAppId; |
| return selectedAppId ? state.apps[selectedAppId]! : null; |
| } |
| |
| /** |
| * Returns a list of all apps whose parent's app ID matches the selected app. |
| */ |
| export function getSubAppsOfSelectedApp(state: AppManagementPageState): App[] { |
| const selectedAppId = state.selectedAppId; |
| const result = selectedAppId ? |
| Object.values(state.apps) |
| .filter( |
| (app) => state.subAppToParentAppId[app.id] === selectedAppId) : |
| []; |
| return result; |
| } |
| |
| /** |
| * Returns the selected app's parent app or null. |
| */ |
| export function getParentApp(state: AppManagementPageState): App|null { |
| const selectedAppId = state.selectedAppId; |
| if (selectedAppId) { |
| const parentAppId = state.subAppToParentAppId[selectedAppId]; |
| return parentAppId ? state.apps[parentAppId]! : null; |
| } |
| return null; |
| } |
| |
| /** |
| * A comparator function to sort strings alphabetically. |
| */ |
| export function alphabeticalSort(a: string, b: string) { |
| return a.localeCompare(b); |
| } |
| |
| function getUserActionHistogramNameForAppType(appType: AppType): string { |
| switch (appType) { |
| case AppType.kArc: |
| return 'AppManagement.AppDetailViews.ArcApp'; |
| case AppType.kChromeApp: |
| return 'AppManagement.AppDetailViews.ChromeApp'; |
| case AppType.kWeb: |
| return 'AppManagement.AppDetailViews.WebApp'; |
| case AppType.kPluginVm: |
| return 'AppManagement.AppDetailViews.PluginVmApp'; |
| case AppType.kBorealis: |
| return 'AppManagement.AppDetailViews.BorealisApp'; |
| default: |
| assertNotReached(); |
| } |
| } |
| |
| export function recordAppManagementUserAction( |
| appType: AppType, userAction: AppManagementUserAction) { |
| const histogram = getUserActionHistogramNameForAppType(appType); |
| const enumLength = Object.keys(AppManagementUserAction).length; |
| BrowserProxy.getInstance().recordEnumerationValue( |
| histogram, userAction, enumLength); |
| } |
| |
| /** |
| * @param arg An argument to check for existence. |
| * @throws If |arg| is undefined or null. |
| */ |
| export function assertExists<T>( |
| arg: T, message: string = `Expected ${arg} to be defined.`): |
| asserts arg is NonNullable<T> { |
| assert(arg !== undefined && arg !== null, message); |
| } |
| |
| /** |
| * @param arg A argument to check for existence. |
| * @return |arg| with the type narrowed as non-nullable. |
| * @throws If |arg| is undefined or null. |
| */ |
| export function castExists<T>(arg: T, message?: string): NonNullable<T> { |
| assertExists(arg, message); |
| return arg; |
| } |