Home | History | Annotate | Download | only in js
      1 // Copyright (c) 2012 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 /**
      6  * @fileoverview This file defines a singleton which provides access to all data
      7  * that is available as soon as the page's resources are loaded (before DOM
      8  * content has finished loading). This data includes both localized strings and
      9  * any data that is important to have ready from a very early stage (e.g. things
     10  * that must be displayed right away).
     11  */
     12 
     13 var loadTimeData;
     14 
     15 // Expose this type globally as a temporary work around until
     16 // https://github.com/google/closure-compiler/issues/544 is fixed.
     17 /** @constructor */
     18 function LoadTimeData() {}
     19 
     20 (function() {
     21   'use strict';
     22 
     23   LoadTimeData.prototype = {
     24     /**
     25      * Sets the backing object.
     26      *
     27      * Note that there is no getter for |data_| to discourage abuse of the form:
     28      *
     29      *     var value = loadTimeData.data()['key'];
     30      *
     31      * @param {Object} value The de-serialized page data.
     32      */
     33     set data(value) {
     34       expect(!this.data_, 'Re-setting data.');
     35       this.data_ = value;
     36     },
     37 
     38     /**
     39      * Returns a JsEvalContext for |data_|.
     40      * @returns {JsEvalContext}
     41      */
     42     createJsEvalContext: function() {
     43       return new JsEvalContext(this.data_);
     44     },
     45 
     46     /**
     47      * @param {string} id An ID of a value that might exist.
     48      * @return {boolean} True if |id| is a key in the dictionary.
     49      */
     50     valueExists: function(id) {
     51       return id in this.data_;
     52     },
     53 
     54     /**
     55      * Fetches a value, expecting that it exists.
     56      * @param {string} id The key that identifies the desired value.
     57      * @return {*} The corresponding value.
     58      */
     59     getValue: function(id) {
     60       expect(this.data_, 'No data. Did you remember to include strings.js?');
     61       var value = this.data_[id];
     62       expect(typeof value != 'undefined', 'Could not find value for ' + id);
     63       return value;
     64     },
     65 
     66     /**
     67      * As above, but also makes sure that the value is a string.
     68      * @param {string} id The key that identifies the desired string.
     69      * @return {string} The corresponding string value.
     70      */
     71     getString: function(id) {
     72       var value = this.getValue(id);
     73       expectIsType(id, value, 'string');
     74       return /** @type {string} */ (value);
     75     },
     76 
     77     /**
     78      * Returns a formatted localized string where $1 to $9 are replaced by the
     79      * second to the tenth argument.
     80      * @param {string} id The ID of the string we want.
     81      * @param {...string} var_args The extra values to include in the formatted
     82      *     output.
     83      * @return {string} The formatted string.
     84      */
     85     getStringF: function(id, var_args) {
     86       var value = this.getString(id);
     87       if (!value)
     88         return '';
     89 
     90       var varArgs = arguments;
     91       return value.replace(/\$[$1-9]/g, function(m) {
     92         return m == '$$' ? '$' : varArgs[m[1]];
     93       });
     94     },
     95 
     96     /**
     97      * As above, but also makes sure that the value is a boolean.
     98      * @param {string} id The key that identifies the desired boolean.
     99      * @return {boolean} The corresponding boolean value.
    100      */
    101     getBoolean: function(id) {
    102       var value = this.getValue(id);
    103       expectIsType(id, value, 'boolean');
    104       return /** @type {boolean} */ (value);
    105     },
    106 
    107     /**
    108      * As above, but also makes sure that the value is an integer.
    109      * @param {string} id The key that identifies the desired number.
    110      * @return {number} The corresponding number value.
    111      */
    112     getInteger: function(id) {
    113       var value = this.getValue(id);
    114       expectIsType(id, value, 'number');
    115       expect(value == Math.floor(value), 'Number isn\'t integer: ' + value);
    116       return /** @type {number} */ (value);
    117     },
    118 
    119     /**
    120      * Override values in loadTimeData with the values found in |replacements|.
    121      * @param {Object} replacements The dictionary object of keys to replace.
    122      */
    123     overrideValues: function(replacements) {
    124       expect(typeof replacements == 'object',
    125              'Replacements must be a dictionary object.');
    126       for (var key in replacements) {
    127         this.data_[key] = replacements[key];
    128       }
    129     }
    130   };
    131 
    132   /**
    133    * Checks condition, displays error message if expectation fails.
    134    * @param {*} condition The condition to check for truthiness.
    135    * @param {string} message The message to display if the check fails.
    136    */
    137   function expect(condition, message) {
    138     if (!condition) {
    139       console.error('Unexpected condition on ' + document.location.href + ': ' +
    140                     message);
    141     }
    142   }
    143 
    144   /**
    145    * Checks that the given value has the given type.
    146    * @param {string} id The id of the value (only used for error message).
    147    * @param {*} value The value to check the type on.
    148    * @param {string} type The type we expect |value| to be.
    149    */
    150   function expectIsType(id, value, type) {
    151     expect(typeof value == type, '[' + value + '] (' + id +
    152                                  ') is not a ' + type);
    153   }
    154 
    155   expect(!loadTimeData, 'should only include this file once');
    156   loadTimeData = new LoadTimeData;
    157 })();
    158