213 lines
7.2 KiB
JavaScript
213 lines
7.2 KiB
JavaScript
// Copyright (c) 2012 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 This file defines a singleton which provides access to all data
|
|
* that is available as soon as the page's resources are loaded (before DOM
|
|
* content has finished loading). This data includes both localized strings and
|
|
* any data that is important to have ready from a very early stage (e.g. things
|
|
* that must be displayed right away).
|
|
*
|
|
* Note that loadTimeData is not guaranteed to be consistent between page
|
|
* refreshes (https://crbug.com/740629) and should not contain values that might
|
|
* change if the page is re-opened later.
|
|
*/
|
|
|
|
/** @type {!LoadTimeData} */ var loadTimeData;
|
|
|
|
// Expose this type globally as a temporary work around until
|
|
// https://github.com/google/closure-compiler/issues/544 is fixed.
|
|
/** @constructor */
|
|
function LoadTimeData(){}
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
LoadTimeData.prototype = {
|
|
/**
|
|
* Sets the backing object.
|
|
*
|
|
* Note that there is no getter for |data_| to discourage abuse of the form:
|
|
*
|
|
* var value = loadTimeData.data()['key'];
|
|
*
|
|
* @param {Object} value The de-serialized page data.
|
|
*/
|
|
set data(value) {
|
|
expect(!this.data_, 'Re-setting data.');
|
|
this.data_ = value;
|
|
},
|
|
|
|
/**
|
|
* Returns a JsEvalContext for |data_|.
|
|
* @returns {JsEvalContext}
|
|
*/
|
|
createJsEvalContext: function() {
|
|
return new JsEvalContext(this.data_);
|
|
},
|
|
|
|
/**
|
|
* @param {string} id An ID of a value that might exist.
|
|
* @return {boolean} True if |id| is a key in the dictionary.
|
|
*/
|
|
valueExists: function(id) {
|
|
return id in this.data_;
|
|
},
|
|
|
|
/**
|
|
* Fetches a value, expecting that it exists.
|
|
* @param {string} id The key that identifies the desired value.
|
|
* @return {*} The corresponding value.
|
|
*/
|
|
getValue: function(id) {
|
|
expect(this.data_, 'No data. Did you remember to include strings.js?');
|
|
var value = this.data_[id];
|
|
expect(typeof value != 'undefined', 'Could not find value for ' + id);
|
|
return value;
|
|
},
|
|
|
|
/**
|
|
* As above, but also makes sure that the value is a string.
|
|
* @param {string} id The key that identifies the desired string.
|
|
* @return {string} The corresponding string value.
|
|
*/
|
|
getString: function(id) {
|
|
var value = this.getValue(id);
|
|
expectIsType(id, value, 'string');
|
|
return /** @type {string} */ (value);
|
|
},
|
|
|
|
/**
|
|
* Returns a formatted localized string where $1 to $9 are replaced by the
|
|
* second to the tenth argument.
|
|
* @param {string} id The ID of the string we want.
|
|
* @param {...(string|number)} var_args The extra values to include in the
|
|
* formatted output.
|
|
* @return {string} The formatted string.
|
|
*/
|
|
getStringF: function(id, var_args) {
|
|
var value = this.getString(id);
|
|
if (!value)
|
|
return '';
|
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
args[0] = value;
|
|
return this.substituteString.apply(this, args);
|
|
},
|
|
|
|
/**
|
|
* Returns a formatted localized string where $1 to $9 are replaced by the
|
|
* second to the tenth argument. Any standalone $ signs must be escaped as
|
|
* $$.
|
|
* @param {string} label The label to substitute through.
|
|
* This is not an resource ID.
|
|
* @param {...(string|number)} var_args The extra values to include in the
|
|
* formatted output.
|
|
* @return {string} The formatted string.
|
|
*/
|
|
substituteString: function(label, var_args) {
|
|
var varArgs = arguments;
|
|
return label.replace(/\$(.|$|\n)/g, function(m) {
|
|
assert(m.match(/\$[$1-9]/), 'Unescaped $ found in localized string.');
|
|
return m == '$$' ? '$' : varArgs[m[1]];
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Returns a formatted string where $1 to $9 are replaced by the second to
|
|
* tenth argument, split apart into a list of pieces describing how the
|
|
* substitution was performed. Any standalone $ signs must be escaped as $$.
|
|
* @param {string} label A localized string to substitute through.
|
|
* This is not an resource ID.
|
|
* @param {...(string|number)} var_args The extra values to include in the
|
|
* formatted output.
|
|
* @return {!Array<!{value: string, arg: (null|string)}>} The formatted
|
|
* string pieces.
|
|
*/
|
|
getSubstitutedStringPieces: function(label, var_args) {
|
|
var varArgs = arguments;
|
|
// Split the string by separately matching all occurrences of $1-9 and of
|
|
// non $1-9 pieces.
|
|
var pieces = (label.match(/(\$[1-9])|(([^$]|\$([^1-9]|$))+)/g) ||
|
|
[]).map(function(p) {
|
|
// Pieces that are not $1-9 should be returned after replacing $$
|
|
// with $.
|
|
if (!p.match(/^\$[1-9]$/)) {
|
|
assert(
|
|
(p.match(/\$/g) || []).length % 2 == 0,
|
|
'Unescaped $ found in localized string.');
|
|
return {value: p.replace(/\$\$/g, '$'), arg: null};
|
|
}
|
|
|
|
// Otherwise, return the substitution value.
|
|
return {value: varArgs[p[1]], arg: p};
|
|
});
|
|
|
|
return pieces;
|
|
},
|
|
|
|
/**
|
|
* As above, but also makes sure that the value is a boolean.
|
|
* @param {string} id The key that identifies the desired boolean.
|
|
* @return {boolean} The corresponding boolean value.
|
|
*/
|
|
getBoolean: function(id) {
|
|
var value = this.getValue(id);
|
|
expectIsType(id, value, 'boolean');
|
|
return /** @type {boolean} */ (value);
|
|
},
|
|
|
|
/**
|
|
* As above, but also makes sure that the value is an integer.
|
|
* @param {string} id The key that identifies the desired number.
|
|
* @return {number} The corresponding number value.
|
|
*/
|
|
getInteger: function(id) {
|
|
var value = this.getValue(id);
|
|
expectIsType(id, value, 'number');
|
|
expect(value == Math.floor(value), 'Number isn\'t integer: ' + value);
|
|
return /** @type {number} */ (value);
|
|
},
|
|
|
|
/**
|
|
* Override values in loadTimeData with the values found in |replacements|.
|
|
* @param {Object} replacements The dictionary object of keys to replace.
|
|
*/
|
|
overrideValues: function(replacements) {
|
|
expect(
|
|
typeof replacements == 'object',
|
|
'Replacements must be a dictionary object.');
|
|
for (var key in replacements) {
|
|
this.data_[key] = replacements[key];
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Checks condition, displays error message if expectation fails.
|
|
* @param {*} condition The condition to check for truthiness.
|
|
* @param {string} message The message to display if the check fails.
|
|
*/
|
|
function expect(condition, message) {
|
|
if (!condition) {
|
|
console.error(
|
|
'Unexpected condition on ' + document.location.href + ': ' + message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks that the given value has the given type.
|
|
* @param {string} id The id of the value (only used for error message).
|
|
* @param {*} value The value to check the type on.
|
|
* @param {string} type The type we expect |value| to be.
|
|
*/
|
|
function expectIsType(id, value, type) {
|
|
expect(
|
|
typeof value == type, '[' + value + '] (' + id + ') is not a ' + type);
|
|
}
|
|
|
|
expect(!loadTimeData, 'should only include this file once');
|
|
loadTimeData = new LoadTimeData;
|
|
})();
|