Home | History | Annotate | Download | only in chromeos
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 cr.define('settime', function() {
      6   /**
      7    * TimeSetter handles a dialog to check and set system time. It can also
      8    * include a timezone dropdown if timezoneId is provided.
      9    *
     10    * TimeSetter uses the system time to populate the controls initially and
     11    * update them as the system time or timezone changes, and notifies Chrome
     12    * when the user changes the time or timezone.
     13    * @constructor
     14    */
     15   function TimeSetter() {}
     16 
     17   cr.addSingletonGetter(TimeSetter);
     18 
     19   /** @const */ var BODY_PADDING_PX = 20;
     20   /** @const */ var LABEL_PADDING_PX = 5;
     21 
     22   TimeSetter.prototype = {
     23     /**
     24      * Performs initial setup.
     25      */
     26     initialize: function() {
     27       // Store values for reverting inputs when the user's date/time is invalid.
     28       this.prevValues_ = {};
     29 
     30       // The build time doesn't include a timezone, so subtract 1 day to get a
     31       // safe minimum date.
     32       this.minDate_ = new Date(loadTimeData.getValue('buildTime'));
     33       this.minDate_.setDate(this.minDate_.getDate() - 1);
     34 
     35       // Set the max date to the min date plus 20 years.
     36       this.maxDate_ = new Date(this.minDate_);
     37       this.maxDate_.setYear(this.minDate_.getFullYear() + 20);
     38 
     39       // Make sure the ostensible date is within this range.
     40       var now = new Date();
     41       if (now > this.maxDate_)
     42         this.maxDate_ = now;
     43       else if (now < this.minDate_)
     44         this.minDate_ = now;
     45 
     46       $('date').setAttribute('min', this.toHtmlValues_(this.minDate_).date);
     47       $('date').setAttribute('max', this.toHtmlValues_(this.maxDate_).date);
     48 
     49       this.updateTime_();
     50 
     51       // Show the timezone select if we have a timezone ID.
     52       var currentTimezoneId = loadTimeData.getValue('currentTimezoneId');
     53       if (currentTimezoneId) {
     54         this.setTimezone_(currentTimezoneId);
     55         $('timezone-select').addEventListener(
     56             'change', this.onTimezoneChange_.bind(this), false);
     57         $('timezone').hidden = false;
     58       }
     59 
     60       this.sizeToFit_();
     61 
     62       $('time').addEventListener('blur', this.onTimeBlur_.bind(this), false);
     63       $('date').addEventListener('blur', this.onTimeBlur_.bind(this), false);
     64 
     65       $('set-time').addEventListener(
     66           'submit', this.onSubmit_.bind(this), false);
     67     },
     68 
     69     /**
     70      * Sets the current timezone.
     71      * @param {string} timezoneId The timezone ID to select.
     72      * @private
     73      */
     74     setTimezone_: function(timezoneId) {
     75       $('timezone-select').value = timezoneId;
     76       this.updateTime_();
     77     },
     78 
     79     /**
     80      * Updates the date/time controls to the current local time.
     81      * Called initially, then called again once a minute.
     82      * @private
     83      */
     84     updateTime_: function() {
     85       var now = new Date();
     86 
     87       // Only update time controls if neither is focused.
     88       if (document.activeElement.id != 'date' &&
     89           document.activeElement.id != 'time') {
     90         var htmlValues = this.toHtmlValues_(now);
     91         this.prevValues_.date = $('date').value = htmlValues.date;
     92         this.prevValues_.time = $('time').value = htmlValues.time;
     93       }
     94 
     95       window.clearTimeout(this.timeTimeout_);
     96 
     97       // Start timer to update these inputs every minute.
     98       var secondsRemaining = 60 - now.getSeconds();
     99       this.timeTimeout_ = window.setTimeout(this.updateTime_.bind(this),
    100                                             secondsRemaining * 1000);
    101     },
    102 
    103     /**
    104      * Sets the system time from the UI.
    105      * @private
    106      */
    107     applyTime_: function() {
    108       var date = $('date').valueAsDate;
    109       date.setMilliseconds(date.getMilliseconds() + $('time').valueAsNumber);
    110 
    111       // Add timezone offset to get real time.
    112       date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
    113 
    114       var seconds = Math.floor(date / 1000);
    115       chrome.send('setTimeInSeconds', [seconds]);
    116     },
    117 
    118     /**
    119      * Called when focus is lost on date/time controls.
    120      * @param {Event} e The blur event.
    121      * @private
    122      */
    123     onTimeBlur_: function(e) {
    124       if (e.target.validity.valid && e.target.value) {
    125         // Make this the new fallback time in case of future invalid input.
    126         this.prevValues_[e.target.id] = e.target.value;
    127         this.applyTime_();
    128       } else {
    129         // Restore previous value.
    130         e.target.value = this.prevValues_[e.target.id];
    131       }
    132     },
    133 
    134     /**
    135      * @param {Event} e The change event.
    136      * @private
    137      */
    138     onTimezoneChange_: function(e) {
    139       chrome.send('setTimezone', [e.currentTarget.value]);
    140     },
    141 
    142     /**
    143      * Closes the dialog window.
    144      * @param {Event} e The submit event.
    145      * @private
    146      */
    147     onSubmit_: function(e) {
    148       e.preventDefault();
    149       chrome.send('dialogClose');
    150     },
    151 
    152     /**
    153      * Resizes the window if necessary to show the entire contents.
    154      * @private
    155      */
    156     sizeToFit_: function() {
    157       // Because of l10n, we should check that the vertical content can fit
    158       // within the window.
    159       if (window.innerHeight < document.body.scrollHeight) {
    160         // Resize window to fit scrollHeight and the title bar.
    161         var newHeight = document.body.scrollHeight +
    162                         window.outerHeight - window.innerHeight;
    163         window.resizeTo(window.outerWidth, newHeight);
    164       }
    165     },
    166 
    167     /**
    168      * Builds date and time strings suitable for the values of HTML date and
    169      * time elements.
    170      * @param {Date} date The date object to represent.
    171      * @return {{date: string, time: string}} Date is an RFC 3339 formatted date
    172      *     and time is an HH:MM formatted time.
    173      * @private
    174      */
    175     toHtmlValues_: function(date) {
    176       // Get the current time and subtract the timezone offset, so the
    177       // JSON string is in local time.
    178       var localDate = new Date(date);
    179       localDate.setMinutes(date.getMinutes() - date.getTimezoneOffset());
    180       return {date: localDate.toISOString().slice(0, 10),
    181               time: localDate.toISOString().slice(11, 16)};
    182     },
    183   };
    184 
    185   TimeSetter.setTimezone = function(timezoneId) {
    186     TimeSetter.getInstance().setTimezone_(timezoneId);
    187   };
    188 
    189   TimeSetter.updateTime = function() {
    190     TimeSetter.getInstance().updateTime_();
    191   };
    192 
    193   return {
    194     TimeSetter: TimeSetter
    195   };
    196 });
    197 
    198 document.addEventListener('DOMContentLoaded', function() {
    199   settime.TimeSetter.getInstance().initialize();
    200 });
    201