Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 3f1208b

Browse files
Justin Emgejelbourn
authored andcommitted
feat($mdThemeProvider): allow the user to define a nonce attribute for generated theme style tags
Closes #6691
1 parent 91291ed commit 3f1208b

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

src/core/services/theming/theming.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ angular.module('material.core.theming', ['material.core.theming.palette'])
1212
* @description Provider to configure the `$mdTheming` service.
1313
*/
1414

15+
/**
16+
* @ngdoc method
17+
* @name $mdThemingProvider#setNonce
18+
* @param {string} nonceValue The nonce to be added as an attribute to the theme style tags.
19+
* Setting a value allows the use CSP policy without using the unsafe-inline directive.
20+
*/
21+
1522
/**
1623
* @ngdoc method
1724
* @name $mdThemingProvider#setDefaultTheme
@@ -125,6 +132,9 @@ var VALID_HUE_VALUES = [
125132
// Whether or not themes are to be generated on-demand (vs. eagerly).
126133
var generateOnDemand = false;
127134

135+
// Nonce to be added as an attribute to the generated themes style tags.
136+
var nonce = null;
137+
128138
function ThemingProvider($mdColorPalette) {
129139
PALETTES = { };
130140
THEMES = { };
@@ -143,6 +153,9 @@ function ThemingProvider($mdColorPalette) {
143153
extendPalette: extendPalette,
144154
theme: registerTheme,
145155

156+
setNonce: function(nonceValue) {
157+
nonce = nonceValue;
158+
},
146159
setDefaultTheme: function(theme) {
147160
defaultTheme = theme;
148161
},
@@ -355,7 +368,7 @@ function ThemingProvider($mdColorPalette) {
355368
applyTheme.THEMES = angular.extend({}, THEMES);
356369
applyTheme.defaultTheme = function() { return defaultTheme; };
357370
applyTheme.registered = registered;
358-
applyTheme.generateTheme = generateTheme;
371+
applyTheme.generateTheme = function(name) { generateTheme(name, nonce); };
359372

360373
return applyTheme;
361374

@@ -516,7 +529,7 @@ function generateAllThemes($injector) {
516529

517530
angular.forEach(THEMES, function(theme) {
518531
if (!GENERATED[theme.name]) {
519-
generateTheme(theme.name);
532+
generateTheme(theme.name, nonce);
520533
}
521534
});
522535

@@ -581,7 +594,7 @@ function generateAllThemes($injector) {
581594
}
582595
}
583596

584-
function generateTheme(name) {
597+
function generateTheme(name, nonce) {
585598
var theme = THEMES[name];
586599
var head = document.head;
587600
var firstChild = head ? head.firstElementChild : null;
@@ -596,6 +609,9 @@ function generateTheme(name) {
596609
if (styleContent) {
597610
var style = document.createElement('style');
598611
style.setAttribute('md-theme-style', '');
612+
if (nonce) {
613+
style.setAttribute('nonce', nonce);
614+
}
599615
style.appendChild(document.createTextNode(styleContent));
600616
head.insertBefore(style, firstChild);
601617
}

src/core/services/theming/theming.spec.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,68 @@ describe('$mdThemeProvider with on-demand generation', function() {
369369
});
370370
});
371371

372+
describe('$mdThemeProvider with nonce', function() {
373+
beforeEach(function() {
374+
375+
module('material.core', function($provide) {
376+
/**
377+
* material-mocks.js clears the $MD_THEME_CSS for Karma testing performance
378+
* performance optimizations. Here inject some length into our theme_css so that
379+
* palettes are parsed/generated
380+
*/
381+
$provide.constant('$MD_THEME_CSS', '/**/');
382+
});
383+
});
384+
385+
describe('and auto-generated themes', function() {
386+
beforeEach(function() {
387+
module('material.core', function($mdThemingProvider) {
388+
$mdThemingProvider.generateThemesOnDemand(false);
389+
390+
$mdThemingProvider.theme('auto-nonce')
391+
.primaryPalette('light-blue')
392+
.accentPalette('yellow');
393+
394+
$mdThemingProvider.setNonce('1');
395+
});
396+
inject();
397+
});
398+
399+
it('should add a nonce', function() {
400+
var styles = document.head.querySelectorAll('style[nonce="1"]');
401+
expect(styles.length).toBe(4);
402+
});
403+
});
404+
405+
describe('and on-demand generated themes', function() {
406+
var $mdTheming;
407+
408+
beforeEach(function() {
409+
module('material.core', function($mdThemingProvider) {
410+
$mdThemingProvider.generateThemesOnDemand(true);
411+
412+
$mdThemingProvider.theme('nonce')
413+
.primaryPalette('light-blue')
414+
.accentPalette('yellow');
415+
416+
$mdThemingProvider.setNonce('2');
417+
});
418+
inject(function(_$mdTheming_) {
419+
$mdTheming = _$mdTheming_;
420+
});
421+
});
422+
423+
it('should add a nonce', function() {
424+
var styles = document.head.querySelectorAll('style[nonce="2"]');
425+
expect(styles.length).toBe(0);
426+
427+
$mdTheming.generateTheme('nonce');
428+
styles = document.head.querySelectorAll('style[nonce="2"]');
429+
expect(styles.length).toBe(4);
430+
});
431+
});
432+
});
433+
372434
describe('$mdTheming service', function() {
373435
var $mdThemingProvider;
374436
beforeEach(module('material.core', function(_$mdThemingProvider_) {

0 commit comments

Comments
 (0)