Use imported SafeTypes

This change removes usages of global Gerrit.SafeTypes replaces
them with direct import.

Change-Id: Ida8233178bf3bd50948986a14518adb5f30ae78f
This commit is contained in:
Dmitrii Filippov
2020-04-03 18:23:05 +02:00
parent 6fd3abd49a
commit ef366ab34f
4 changed files with 64 additions and 60 deletions

View File

@@ -14,62 +14,65 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
(function(window) {
'use strict';
window.Gerrit = window.Gerrit || {}; const SAFE_URL_PATTERN = /^(https?:\/\/|mailto:|[^:/?#]*(?:[/?#]|$))/i;
/** @polymerBehavior Gerrit.SafeTypes */ /** @polymerBehavior Gerrit.SafeTypes */
Gerrit.SafeTypes = {}; export const SafeTypes = {};
const SAFE_URL_PATTERN = /^(https?:\/\/|mailto:|[^:/?#]*(?:[/?#]|$))/i; /**
* Wraps a string to be used as a URL. An error is thrown if the string cannot
* be considered safe.
*
* @constructor
* @param {string} url the unwrapped, potentially unsafe URL.
*/
SafeTypes.SafeUrl = function(url) {
if (!SAFE_URL_PATTERN.test(url)) {
throw new Error(`URL not marked as safe: ${url}`);
}
this._url = url;
};
/** /**
* Wraps a string to be used as a URL. An error is thrown if the string cannot * Get the string representation of the safe URL.
* be considered safe. *
* * @returns {string}
* @constructor */
* @param {string} url the unwrapped, potentially unsafe URL. SafeTypes.SafeUrl.prototype.asString = function() {
*/ return this._url;
Gerrit.SafeTypes.SafeUrl = function(url) { };
if (!SAFE_URL_PATTERN.test(url)) {
throw new Error(`URL not marked as safe: ${url}`); SafeTypes.safeTypesBridge = function(value, type) {
// If the value is being bound to a URL, ensure the value is wrapped in the
// SafeUrl type first. If the URL is not safe, allow the SafeUrl constructor
// to surface the error.
if (type === 'URL') {
let safeValue = null;
if (value instanceof SafeTypes.SafeUrl) {
safeValue = value;
} else if (typeof value === 'string') {
safeValue = new SafeTypes.SafeUrl(value);
} }
this._url = url; if (safeValue) {
}; return safeValue.asString();
/**
* Get the string representation of the safe URL.
*
* @returns {string}
*/
Gerrit.SafeTypes.SafeUrl.prototype.asString = function() {
return this._url;
};
Gerrit.SafeTypes.safeTypesBridge = function(value, type) {
// If the value is being bound to a URL, ensure the value is wrapped in the
// SafeUrl type first. If the URL is not safe, allow the SafeUrl constructor
// to surface the error.
if (type === 'URL') {
let safeValue = null;
if (value instanceof Gerrit.SafeTypes.SafeUrl) {
safeValue = value;
} else if (typeof value === 'string') {
safeValue = new Gerrit.SafeTypes.SafeUrl(value);
}
if (safeValue) {
return safeValue.asString();
}
} }
}
// If the value is being bound to a string or a constant, then the string // If the value is being bound to a string or a constant, then the string
// can be used as is. // can be used as is.
if (type === 'STRING' || type === 'CONSTANT') { if (type === 'STRING' || type === 'CONSTANT') {
return value; return value;
} }
// Otherwise fail.
throw new Error(`Refused to bind value as ${type}: ${value}`);
};
// TODO(dmfilippov) Remove the following lines with assignments
// Plugins can use the behavior because it was accessible with
// the global Gerrit... variable. To avoid breaking changes in plugins
// temporary assign global variables.
window.Gerrit = window.Gerrit || {};
window.Gerrit.SafeTypes = SafeTypes;
// Otherwise fail.
throw new Error(`Refused to bind value as ${type}: ${value}`);
};
})(window);

View File

@@ -31,8 +31,8 @@ limitations under the License.
<script type="module"> <script type="module">
import '../../test/common-test-setup.js'; import '../../test/common-test-setup.js';
import './safe-types-behavior.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js'; import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
import {SafeTypes} from './safe-types-behavior.js';
suite('gr-tooltip-behavior tests', () => { suite('gr-tooltip-behavior tests', () => {
let element; let element;
let sandbox; let sandbox;
@@ -40,7 +40,7 @@ suite('gr-tooltip-behavior tests', () => {
suiteSetup(() => { suiteSetup(() => {
Polymer({ Polymer({
is: 'safe-types-element', is: 'safe-types-element',
behaviors: [Gerrit.SafeTypes], behaviors: [SafeTypes],
}); });
}); });
@@ -79,12 +79,12 @@ suite('gr-tooltip-behavior tests', () => {
suite('safeTypesBridge', () => { suite('safeTypesBridge', () => {
function acceptsString(value, type) { function acceptsString(value, type) {
assert.equal(Gerrit.SafeTypes.safeTypesBridge(value, type), assert.equal(SafeTypes.safeTypesBridge(value, type),
value); value);
} }
function rejects(value, type) { function rejects(value, type) {
assert.throws(() => { Gerrit.SafeTypes.safeTypesBridge(value, type); }); assert.throws(() => { SafeTypes.safeTypesBridge(value, type); });
} }
test('accepts valid URL strings', () => { test('accepts valid URL strings', () => {
@@ -99,7 +99,7 @@ suite('gr-tooltip-behavior tests', () => {
test('accepts SafeUrl values', () => { test('accepts SafeUrl values', () => {
const url = '/abc/123'; const url = '/abc/123';
const safeUrl = new element.SafeUrl(url); const safeUrl = new element.SafeUrl(url);
assert.equal(Gerrit.SafeTypes.safeTypesBridge(safeUrl, 'URL'), url); assert.equal(SafeTypes.safeTypesBridge(safeUrl, 'URL'), url);
}); });
test('rejects non-string or non-SafeUrl types', () => { test('rejects non-string or non-SafeUrl types', () => {

View File

@@ -25,18 +25,18 @@ import './gr-app-init.js';
import './font-roboto-local-loader.js'; import './font-roboto-local-loader.js';
import '../scripts/bundled-polymer.js'; import '../scripts/bundled-polymer.js';
import 'polymer-resin/standalone/polymer-resin.js'; import 'polymer-resin/standalone/polymer-resin.js';
import '../behaviors/safe-types-behavior/safe-types-behavior.js';
import './gr-app-element.js'; import './gr-app-element.js';
import './change-list/gr-embed-dashboard/gr-embed-dashboard.js'; import './change-list/gr-embed-dashboard/gr-embed-dashboard.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js'; import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js'; import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js'; import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {htmlTemplate} from './gr-app_html.js'; import {htmlTemplate} from './gr-app_html.js';
import {SafeTypes} from '../behaviors/safe-types-behavior/safe-types-behavior.js';
security.polymer_resin.install({ security.polymer_resin.install({
allowedIdentifierPrefixes: [''], allowedIdentifierPrefixes: [''],
reportHandler: security.polymer_resin.CONSOLE_LOGGING_REPORT_HANDLER, reportHandler: security.polymer_resin.CONSOLE_LOGGING_REPORT_HANDLER,
safeTypesBridge: Gerrit.SafeTypes.safeTypesBridge, safeTypesBridge: SafeTypes.safeTypesBridge,
}); });
/** @extends Polymer.Element */ /** @extends Polymer.Element */

View File

@@ -17,10 +17,11 @@
import '../scripts/bundled-polymer.js'; import '../scripts/bundled-polymer.js';
import 'polymer-resin/standalone/polymer-resin.js'; import 'polymer-resin/standalone/polymer-resin.js';
import '../behaviors/safe-types-behavior/safe-types-behavior.js';
import '@polymer/iron-test-helpers/iron-test-helpers.js'; import '@polymer/iron-test-helpers/iron-test-helpers.js';
import './test-router.js'; import './test-router.js';
import moment from 'moment/src/moment.js'; import moment from 'moment/src/moment.js';
import {SafeTypes} from '../behaviors/safe-types-behavior/safe-types-behavior.js';
self.moment = moment; self.moment = moment;
security.polymer_resin.install({ security.polymer_resin.install({
allowedIdentifierPrefixes: [''], allowedIdentifierPrefixes: [''],
@@ -35,7 +36,7 @@ security.polymer_resin.install({
JSON.stringify(args)); JSON.stringify(args));
} }
}, },
safeTypesBridge: Gerrit.SafeTypes.safeTypesBridge, safeTypesBridge: SafeTypes.safeTypesBridge,
}); });
// Default implementations of 'fixture' and 'stub' methods in // Default implementations of 'fixture' and 'stub' methods in