Home | History | Annotate | Download | only in login
      1 // Copyright 2013 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('login', function() {
      6 
      7   /**
      8    * Minimum wallpaper load delay in milliseconds.
      9    * @type {number}
     10    * @const
     11    */
     12   var WALLPAPER_LOAD_MIN_DELAY_MS = 100;
     13 
     14   /**
     15    * If last walpaper load time cannot be calculated, assume this value.
     16    * @type {number}
     17    * @const
     18    */
     19   var WALLPAPER_DEFAULT_LOAD_TIME_MS = 200;
     20 
     21   /**
     22    * Min and Max average wallpaper load time.
     23    * Delay to next wallpaper load is 2 * <average load time>.
     24    * @type {number}
     25    * @const
     26    */
     27   var WALLPAPER_MIN_LOAD_TIME_MS = 50;
     28   var WALLPAPER_MAX_LOAD_TIME_MS = 2000;
     29 
     30   /**
     31    * Number last wallpaper load times to remember.
     32    * @type {number}
     33    * @const
     34    */
     35   var WALLPAPER_LOAD_STATS_MAX_LENGTH = 4;
     36 
     37 
     38   /**
     39    * Creates a new pod row element.
     40    * @constructor
     41    * @extends {HTMLDivElement}
     42    */
     43   var WallpaperLoader = function() {
     44     this.wallpaperLoadInProgress_ = {
     45         name: '',
     46         date: undefined
     47     };
     48     this.loadStats_ = [];
     49   };
     50 
     51   WallpaperLoader.prototype = {
     52     // When moving through users quickly at login screen, set a timeout to
     53     // prevent loading intermediate wallpapers.
     54     beforeLoadTimeout_: null,
     55 
     56     // If we do not receive notification on WallpaperLoaded within timeout,
     57     // probably an error happened and the wallpaper is just bad. Skip it
     58     // and unblock loader.
     59     loadTimeout_: null,
     60 
     61     // When waiting for wallpaper load, remember load start time.
     62     // wallpaperLoadInProgress_: { name: '', date: undefined }
     63     wallpaperLoadInProgress_: undefined,
     64 
     65     // Wait a delay and then load this wallpaper. Value = username.
     66     wallpaperLoadPending_: undefined,
     67 
     68     // Wait untill this Date before loading next wallpaper.
     69     wallpaperLoadTryNextAfter_: undefined,
     70 
     71     // Username, owner of current wallpaper.
     72     currentWallpaper_: '',
     73 
     74     // Array of times (in milliseconds) of last wallpaper load attempts.
     75     // Length is limited by WALLPAPER_LOAD_STATS_MAX_LENGTH.
     76     loadStats_: undefined,
     77 
     78     // Force next load request even if requested wallpaper is already loaded.
     79     forceLoad_: false,
     80 
     81     /**
     82      * Stop load timer. Clear pending record.
     83      */
     84     reset: function() {
     85       delete this.wallpaperLoadPending_;
     86 
     87       if (this.beforeLoadTimeout_ != null)
     88         window.clearTimeout(this.beforeLoadTimeout_);
     89       this.beforeLoadTimeout_ = null;
     90 
     91       if (this.loadTimeout_ != null)
     92         window.clearTimeout(this.loadTimeout_);
     93       this.loadTimeout_ = null;
     94 
     95       this.wallpaperLoadInProgress_.name = '';
     96     },
     97 
     98     /**
     99      * Schedules wallpaper load.
    100      */
    101     scheduleLoad: function(email, force) {
    102       if (force || this.forceLoad_) {
    103         this.forceLoad_ = true;
    104       } else {
    105         if (this.wallpaperLoadPending_ && this.wallpaperLoadPending_ == email)
    106           return;
    107         if ((this.wallpaperLoadInProgress_.name == '') &&
    108             (this.currentWallpaper_ == email))
    109           return;
    110       }
    111       this.reset();
    112 
    113       this.wallpaperLoadPending_ = email;
    114       var now = new Date();
    115       var timeout = WALLPAPER_LOAD_MIN_DELAY_MS;
    116       if (this.wallpaperLoadTryNextAfter_)
    117         timeout = Math.max(timeout, this.wallpaperLoadTryNextAfter_ - now);
    118 
    119       this.beforeLoadTimeout_ = window.setTimeout(
    120           this.loadWallpaper_.bind(this), timeout);
    121     },
    122 
    123 
    124     /**
    125      * Loads pending wallpaper, if any.
    126      * @private
    127      */
    128     loadWallpaper_: function() {
    129       this.beforeLoadTimeout_ = null;
    130       if (!this.wallpaperLoadPending_)
    131         return;
    132       if (!this.forceLoad_ && this.wallpaperLoadInProgress_.name != '')
    133         return;
    134       var email = this.wallpaperLoadPending_;
    135       delete this.wallpaperLoadPending_;
    136       if (!this.forceLoad_ && email == this.currentWallpaper_)
    137         return;
    138       this.wallpaperLoadInProgress_.name = email;
    139       this.wallpaperLoadInProgress_.date = new Date();
    140       this.forceLoad_ = false;
    141       chrome.send('loadWallpaper', [email]);
    142 
    143       var timeout = 3 * this.getWallpaperLoadTime_();
    144       this.loadTimeout_ = window.setTimeout(
    145           this.loadTimeoutFired_.bind(this), timeout);
    146     },
    147 
    148     /**
    149      * Calculates average wallpaper load time.
    150      */
    151     calcLoadStatsAvg: function() {
    152         return this.loadStats_.reduce(
    153             function(previousValue, currentValue) {
    154               return previousValue + currentValue;
    155             }) / this.loadStats_.length;
    156     },
    157 
    158     /**
    159      * Calculates average next wallpaper load delay time.
    160      */
    161     getWallpaperLoadTime_: function() {
    162       var avg = WALLPAPER_DEFAULT_LOAD_TIME_MS;
    163 
    164       if (this.loadStats_.length == 0)
    165         return avg;
    166 
    167       avg = this.calcLoadStatsAvg();
    168       if (avg < WALLPAPER_MIN_LOAD_TIME_MS)
    169         avg = WALLPAPER_MIN_LOAD_TIME_MS;
    170 
    171       if (avg > WALLPAPER_MAX_LOAD_TIME_MS)
    172         avg = WALLPAPER_MAX_LOAD_TIME_MS;
    173 
    174       return avg;
    175     },
    176 
    177     /**
    178      * Handles 'onWallpaperLoaded' event. Recalculates statistics and
    179      * [re]schedules next wallpaper load.
    180      */
    181     onWallpaperLoaded: function(email) {
    182       this.currentWallpaper_ = email;
    183       if (email != this.wallpaperLoadInProgress_.name)
    184           return;
    185 
    186       window.clearTimeout(this.loadTimeout_);
    187       this.loadTimeout_ = null;
    188 
    189       this.wallpaperLoadInProgress_.name = '';
    190       var started = this.wallpaperLoadInProgress_.date;
    191       var finished = new Date();
    192       var elapsed = started ? finished - started :
    193           WALLPAPER_DEFAULT_LOAD_TIME_MS;
    194       this.loadStats_.push(elapsed);
    195       if (this.loadStats_.length > WALLPAPER_LOAD_STATS_MAX_LENGTH)
    196         this.loadStats_.shift();
    197 
    198       this.wallpaperLoadTryNextAfter_ = new Date(Date.now() + 2 *
    199           this.getWallpaperLoadTime_());
    200       if (this.wallpaperLoadPending_) {
    201         var newWallpaperEmail = this.wallpaperLoadPending_;
    202         this.reset();
    203         this.scheduleLoad(newWallpaperEmail, this.forceLoad_);
    204       }
    205     },
    206 
    207     /**
    208      * Handles timeout of wallpaper load. Pretends load is completed to unblock
    209      * loader.
    210      */
    211     loadTimeoutFired_: function() {
    212       var email = this.wallpaperLoadInProgress_.name;
    213       this.loadTimeout_ = null;
    214       if (email == '')
    215         return;
    216       this.onWallpaperLoaded(email);
    217     }
    218   };
    219 
    220   return {
    221     WallpaperLoader: WallpaperLoader
    222   };
    223 });
    224