chromium/chrome/browser/resources/chromeos/password_change/urgent_password_expiry_notification_app.js

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @fileoverview 'urgent-password-expiry-notification' is a notification that
 * warns the user their password is about to expire - but it is a large
 * notification that is shown in the center of the screen.
 * It is implemented not using the notification system, but as a system dialog.
 */

import 'chrome://resources/ash/common/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/ash/common/cr_elements/cr_dialog/cr_dialog.js';
import 'chrome://resources/ash/common/cr_elements/icons.html.js';
import 'chrome://resources/ash/common/cr_elements/cr_shared_vars.css.js';
import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import './strings.m.js';

import {I18nBehavior} from 'chrome://resources/ash/common/i18n_behavior.js';
import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
import {WebUIListenerBehavior} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {getTemplate} from './urgent_password_expiry_notification_app.html.js';

const ONE_SECOND_IN_MS = 1000;
const ONE_MINUTE_IN_MS = ONE_SECOND_IN_MS * 60;
const ONE_HOUR_IN_MS = ONE_MINUTE_IN_MS * 60;

/**
 * @constructor
 * @extends {PolymerElement}
 * @implements {I18nBehaviorInterface}
 */
const UrgentPasswordExpiryNotificationElementBase =
    mixinBehaviors([I18nBehavior, WebUIListenerBehavior], PolymerElement);

/** @polymer */
class UrgentPasswordExpiryNotificationElement extends
    UrgentPasswordExpiryNotificationElementBase {
  static get is() {
    return 'urgent-password-expiry-notification';
  }

  static get template() {
    return getTemplate();
  }

  static get properties() {
    return {
      /** @private {string} */
      title_: {
        type: String,
        value: '',
      },

    };
  }

  constructor() {
    super();

    /** @type {?Date} */
    this.expirationTime_ = null;

    /** @type {?number} */
    this.countDownIntervalId_ = null;

    /** @type {?number} */
    this.countDownIntervalMs_ = null;
  }


  /** @override */
  connectedCallback() {
    super.connectedCallback();

    this.$.dialog.showModal();
    if (loadTimeData.valueExists('initialTitle')) {
      this.title_ = loadTimeData.getString('initialTitle');
    }

    if (loadTimeData.valueExists('expirationTime')) {
      const expirationTimeStr = loadTimeData.getString('expirationTime');
      const expirationTimeMs = parseInt(expirationTimeStr);
      if (isNaN(expirationTimeMs)) {
        console.error('Bad expiration time: ' + expirationTimeStr);
      } else {
        this.expirationTime_ = new Date(expirationTimeMs);
        this.ensureCountDownCalledOftenEnough_();
      }
    }
  }

  /** @private */
  ensureCountDownCalledOftenEnough_() {
    const nowMs = Date.now();
    if (nowMs > this.expirationTime_) {
      // Already expired - no need to keep updating UI.
      this.stopCountDownCalls_();
    } else if (nowMs >= (this.expirationTime_ - 2 * ONE_HOUR_IN_MS)) {
      // Expires in the next two hours - update UI every minute.
      this.ensureCountDownCalledWithInterval_(ONE_MINUTE_IN_MS);
    } else {
      // Expires some time in the future - update UI every hour.
      this.ensureCountDownCalledWithInterval_(ONE_HOUR_IN_MS);
    }
  }

  /** @private */
  ensureCountDownCalledWithInterval_(intervalMs) {
    if (this.countDownIntervalMs_ === intervalMs) {
      return;
    }
    this.stopCountDownCalls_();
    this.countDownIntervalId_ =
        setInterval(this.countDown_.bind(this), intervalMs);
    this.countDownIntervalMs_ = intervalMs;
  }

  /** @private */
  stopCountDownCalls_() {
    if (!this.countDownIntervalId_) {
      return;
    }
    clearInterval(this.countDownIntervalId_);
    this.countDownIntervalId_ = null;
    this.countDownIntervalMs_ = null;
  }

  /** @private */
  countDown_() {
    this.ensureCountDownCalledOftenEnough_();
    const msUntilExpiry = this.expirationTime_ - Date.now();
    cr.sendWithPromise('getTitleText', msUntilExpiry).then((title) => {
      this.title_ = title;
    });
  }

  /** @private */
  onButtonTap_() {
    chrome.send('continue');
  }
}

customElements.define(
    UrgentPasswordExpiryNotificationElement.is,
    UrgentPasswordExpiryNotificationElement);