| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * @fileoverview |
| * 'os-settings-apps-page' is the settings page containing app related settings. |
| * |
| */ |
| import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; |
| import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; |
| import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; |
| import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.m.js'; |
| import '../../settings_page/settings_animated_pages.js'; |
| import '../../settings_page/settings_subpage.js'; |
| import '../../settings_shared.css.js'; |
| import '../../settings_shared.css.js'; |
| import '../guest_os/guest_os_shared_usb_devices.js'; |
| import '../guest_os/guest_os_shared_paths.js'; |
| import 'chrome://resources/cr_components/localized_link/localized_link.js'; |
| import './android_apps_subpage.js'; |
| import './app_notifications_page/app_notifications_subpage.js'; |
| import './app_management_page/app_management_page.js'; |
| import './app_management_page/app_detail_view.js'; |
| import 'chrome://resources/cr_components/app_management/uninstall_button.js'; |
| import '../../controls/settings_dropdown_menu.js'; |
| |
| import {AppManagementEntryPoint, AppManagementEntryPointsHistogramName} from 'chrome://resources/cr_components/app_management/constants.js'; |
| import {getAppIcon, getSelectedApp} from 'chrome://resources/cr_components/app_management/util.js'; |
| import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; |
| import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; |
| import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import {loadTimeData} from '../../i18n_setup.js'; |
| import {Setting} from '../../mojom-webui/setting.mojom-webui.js'; |
| import {Route, Router} from '../../router.js'; |
| import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; |
| import {routes} from '../os_route.js'; |
| import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; |
| import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; |
| |
| import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from './android_apps_browser_proxy.js'; |
| import {AppManagementStoreClient, AppManagementStoreClientInterface} from './app_management_page/store_client.js'; |
| import {getAppNotificationProvider} from './app_notifications_page/mojo_interface_provider.js'; |
| |
| /** |
| * @param {!chromeos.settings.appNotification.mojom.App} app |
| * @return {boolean} |
| */ |
| export function isAppInstalled(app) { |
| switch (app.readiness) { |
| case chromeos.settings.appNotification.mojom.Readiness.kReady: |
| case chromeos.settings.appNotification.mojom.Readiness.kDisabledByBlocklist: |
| case chromeos.settings.appNotification.mojom.Readiness.kDisabledByPolicy: |
| case chromeos.settings.appNotification.mojom.Readiness.kDisabledByUser: |
| case chromeos.settings.appNotification.mojom.Readiness.kTerminated: |
| return true; |
| case chromeos.settings.appNotification.mojom.Readiness.kUninstalledByUser: |
| case chromeos.settings.appNotification.mojom.Readiness |
| .kUninstalledByMigration: |
| case chromeos.settings.appNotification.mojom.Readiness.kRemoved: |
| case chromeos.settings.appNotification.mojom.Readiness.kUnknown: |
| return false; |
| } |
| assertNotReached(); |
| return false; |
| } |
| |
| /** |
| * @constructor |
| * @extends {PolymerElement} |
| * @implements {AppManagementStoreClientInterface} |
| * @implements {DeepLinkingBehaviorInterface} |
| * @implements {I18nBehaviorInterface} |
| * @implements {PrefsBehaviorInterface} |
| * @implements {RouteObserverBehaviorInterface} |
| */ |
| const OsSettingsAppsPageElementBase = mixinBehaviors( |
| [ |
| AppManagementStoreClient, |
| DeepLinkingBehavior, |
| I18nBehavior, |
| PrefsBehavior, |
| RouteObserverBehavior, |
| ], |
| PolymerElement); |
| |
| /** @polymer */ |
| class OsSettingsAppsPageElement extends OsSettingsAppsPageElementBase { |
| static get is() { |
| return 'os-settings-apps-page'; |
| } |
| |
| static get template() { |
| return html`{__html_template__}`; |
| } |
| |
| static get properties() { |
| return { |
| /** Preferences state. */ |
| prefs: { |
| type: Object, |
| notify: true, |
| }, |
| |
| /** |
| * This object holds the playStoreEnabled and settingsAppAvailable |
| * boolean. |
| * @type {Object} |
| */ |
| androidAppsInfo: Object, |
| |
| /** |
| * If the Play Store app is available. |
| * @type {boolean} |
| */ |
| havePlayStoreApp: Boolean, |
| |
| /** |
| * @type {string} |
| */ |
| searchTerm: String, |
| |
| /** |
| * Show ARC++ related settings and sub-page. |
| * @type {boolean} |
| */ |
| showAndroidApps: Boolean, |
| |
| /** |
| * Show ARCVM Manage USB related settings and sub-page. |
| * @type {boolean} |
| */ |
| showArcvmManageUsb: Boolean, |
| |
| /** |
| * Whether the App Notifications page should be shown. |
| * @type {boolean} |
| */ |
| showAppNotificationsRow_: { |
| type: Boolean, |
| value() { |
| return loadTimeData.getBoolean('showOsSettingsAppNotificationsRow'); |
| }, |
| }, |
| |
| /** |
| * Show Plugin VM shared folders sub-page. |
| * @type {boolean} |
| */ |
| showPluginVm: Boolean, |
| |
| /** |
| * Show On startup settings and sub-page. |
| * @type {boolean} |
| */ |
| showStartup: Boolean, |
| |
| /** @private {!Map<string, string>} */ |
| focusConfig_: { |
| type: Object, |
| value() { |
| const map = new Map(); |
| if (routes.APP_MANAGEMENT) { |
| map.set(routes.APP_MANAGEMENT.path, '#appManagement'); |
| } |
| if (routes.ANDROID_APPS_DETAILS) { |
| map.set( |
| routes.ANDROID_APPS_DETAILS.path, |
| '#android-apps .subpage-arrow'); |
| } |
| return map; |
| }, |
| }, |
| |
| /** |
| * @type {App} |
| * @private |
| */ |
| app_: Object, |
| |
| /** |
| * @type {!Array<!Object>} |
| * @private |
| */ |
| appsWithNotifications_: { |
| type: Array, |
| value: [], |
| }, |
| |
| /** |
| * List of options for the on startup drop-down menu. |
| * @type {!DropdownMenuOptionList} |
| */ |
| onStartupOptions_: { |
| readOnly: true, |
| type: Array, |
| value() { |
| return [ |
| {value: 1, name: loadTimeData.getString('onStartupAlways')}, |
| {value: 2, name: loadTimeData.getString('onStartupAskEveryTime')}, |
| {value: 3, name: loadTimeData.getString('onStartupDoNotRestore')}, |
| ]; |
| }, |
| }, |
| |
| /** @private {boolean} */ |
| isDndEnabled_: { |
| type: Boolean, |
| value: false, |
| }, |
| |
| /** |
| * Used by DeepLinkingBehavior to focus this page's deep links. |
| * @type {!Set<!Setting>} |
| */ |
| supportedSettingIds: { |
| type: Object, |
| value: () => new Set([ |
| Setting.kManageAndroidPreferences, |
| Setting.kTurnOnPlayStore, |
| Setting.kRestoreAppsAndPages, |
| ]), |
| }, |
| }; |
| } |
| |
| connectedCallback() { |
| super.connectedCallback(); |
| |
| this.watch('app_', state => { |
| // Don't set `app_` to `null`, since it triggers Polymer |
| // data bindings of <app-management-uninstall-button> which does not |
| // accept `null`, use `undefined` instead. |
| return getSelectedApp(state) || undefined; |
| }); |
| |
| /** |
| * @private {!chromeos.settings.appNotification.mojom.AppNotificationsHandlerInterface} |
| */ |
| this.mojoInterfaceProvider_ = getAppNotificationProvider(); |
| |
| /** |
| * @private {!chromeos.settings.appNotification.mojom.AppNotificationsObserverReceiver} |
| */ |
| this.appNotificationsObserverReceiver_ = |
| new chromeos.settings.appNotification.mojom |
| .AppNotificationsObserverReceiver( |
| /** |
| * @type {!chromeos.settings.appNotification.mojom. |
| * AppNotificationsObserverInterface} |
| */ |
| (this)); |
| |
| this.mojoInterfaceProvider_.addObserver( |
| this.appNotificationsObserverReceiver_.$.bindNewPipeAndPassRemote()); |
| |
| this.mojoInterfaceProvider_.getQuietMode().then((result) => { |
| this.isDndEnabled_ = result.enabled; |
| }); |
| this.mojoInterfaceProvider_.getApps().then((result) => { |
| this.appsWithNotifications_ = result.apps; |
| }); |
| } |
| |
| /** |
| * @param {!Route} route |
| * @param {!Route=} oldRoute |
| */ |
| currentRouteChanged(route, oldRoute) { |
| // Does not apply to this page. |
| if (route !== routes.APPS) { |
| return; |
| } |
| |
| this.attemptDeepLink(); |
| } |
| |
| /** |
| * @param {App} app |
| * @return {string} |
| * @private |
| */ |
| iconUrlFromId_(app) { |
| if (!app) { |
| return ''; |
| } |
| return getAppIcon(app); |
| } |
| |
| /** @private */ |
| onClickAppManagement_() { |
| chrome.metricsPrivate.recordEnumerationValue( |
| AppManagementEntryPointsHistogramName, |
| AppManagementEntryPoint.OS_SETTINGS_MAIN_PAGE, |
| Object.keys(AppManagementEntryPoint).length); |
| Router.getInstance().navigateTo(routes.APP_MANAGEMENT); |
| } |
| |
| /** @private */ |
| onClickAppNotifications_() { |
| Router.getInstance().navigateTo(routes.APP_NOTIFICATIONS); |
| } |
| |
| /** |
| * @param {!Event} event |
| * @private |
| */ |
| onEnableAndroidAppsTap_(event) { |
| this.setPrefValue('arc.enabled', true); |
| event.stopPropagation(); |
| } |
| |
| /** |
| * @return {boolean} |
| * @private |
| */ |
| isEnforced_(pref) { |
| return pref.enforcement === chrome.settingsPrivate.Enforcement.ENFORCED; |
| } |
| |
| /** @private */ |
| onAndroidAppsSubpageTap_(event) { |
| if (this.androidAppsInfo.playStoreEnabled) { |
| Router.getInstance().navigateTo(routes.ANDROID_APPS_DETAILS); |
| } |
| } |
| |
| /** |
| * @param {!MouseEvent} event |
| * @private |
| */ |
| onManageAndroidAppsTap_(event) { |
| // |event.detail| is the click count. Keyboard events will have 0 clicks. |
| const isKeyboardAction = event.detail === 0; |
| AndroidAppsBrowserProxyImpl.getInstance().showAndroidAppsSettings( |
| isKeyboardAction); |
| } |
| |
| /** Override chromeos.settings.appNotification.onNotificationAppChanged */ |
| onNotificationAppChanged(updatedApp) { |
| const foundIdx = this.appsWithNotifications_.findIndex(app => { |
| return app.id === updatedApp.id; |
| }); |
| if (isAppInstalled(updatedApp)) { |
| if (foundIdx !== -1) { |
| this.splice('appsWithNotifications_', foundIdx, updatedApp); |
| return; |
| } |
| this.push('appsWithNotifications_', updatedApp); |
| return; |
| } |
| |
| // Cannot have an app that is uninstalled prior to being installed. |
| assert(foundIdx !== -1); |
| // Uninstalled app found, remove it from the list. |
| this.splice('appsWithNotifications_', foundIdx, 1); |
| } |
| |
| /** Override chromeos.settings.appNotification.onQuietModeChanged */ |
| onQuietModeChanged(enabled) { |
| this.isDndEnabled_ = enabled; |
| } |
| |
| /** |
| * @return {string} |
| * @protected |
| */ |
| getAppListCountDescription_() { |
| return this.isDndEnabled_ ? |
| this.i18n('appNotificationsDoNotDisturbDescription') : |
| this.i18n( |
| 'appNotificationsCountDescription', |
| this.appsWithNotifications_.length); |
| } |
| } |
| |
| customElements.define(OsSettingsAppsPageElement.is, OsSettingsAppsPageElement); |