1
- import { Injectable } from '@angular/core' ;
1
+ import { Injectable , SecurityContext } from '@angular/core' ;
2
+ import { SafeResourceUrl , DomSanitizer } from '@angular/platform-browser' ;
2
3
import { Http } from '@angular/http' ;
3
4
import { MdError } from '../core' ;
4
5
import { Observable } from 'rxjs/Observable' ;
5
6
import 'rxjs/add/observable/forkJoin' ;
6
7
import 'rxjs/add/observable/of' ;
8
+ import 'rxjs/add/observable/throw' ;
7
9
import 'rxjs/add/operator/map' ;
8
10
import 'rxjs/add/operator/filter' ;
9
11
import 'rxjs/add/operator/do' ;
@@ -18,7 +20,7 @@ import 'rxjs/add/operator/catch';
18
20
*/
19
21
export class MdIconNameNotFoundError extends MdError {
20
22
constructor ( iconName : string ) {
21
- super ( `Unable to find icon with the name "${ iconName } "` ) ;
23
+ super ( `Unable to find icon with the name "${ iconName } "` ) ;
22
24
}
23
25
}
24
26
@@ -29,7 +31,7 @@ export class MdIconNameNotFoundError extends MdError {
29
31
*/
30
32
export class MdIconSvgTagNotFoundError extends MdError {
31
33
constructor ( ) {
32
- super ( '<svg> tag not found' ) ;
34
+ super ( '<svg> tag not found' ) ;
33
35
}
34
36
}
35
37
@@ -39,7 +41,7 @@ export class MdIconSvgTagNotFoundError extends MdError {
39
41
*/
40
42
class SvgIconConfig {
41
43
svgElement : SVGElement = null ;
42
- constructor ( public url : string ) { }
44
+ constructor ( public url : SafeResourceUrl ) { }
43
45
}
44
46
45
47
/** Returns the cache key to use for an icon namespace and name. */
@@ -81,27 +83,27 @@ export class MdIconRegistry {
81
83
*/
82
84
private _defaultFontSetClass = 'material-icons' ;
83
85
84
- constructor ( private _http : Http ) { }
86
+ constructor ( private _http : Http , private _sanitizer : DomSanitizer ) { }
85
87
86
88
/** Registers an icon by URL in the default namespace. */
87
- addSvgIcon ( iconName : string , url : string ) : this {
89
+ addSvgIcon ( iconName : string , url : SafeResourceUrl ) : this {
88
90
return this . addSvgIconInNamespace ( '' , iconName , url ) ;
89
91
}
90
92
91
93
/** Registers an icon by URL in the specified namespace. */
92
- addSvgIconInNamespace ( namespace : string , iconName : string , url : string ) : this {
94
+ addSvgIconInNamespace ( namespace : string , iconName : string , url : SafeResourceUrl ) : this {
93
95
const key = iconKey ( namespace , iconName ) ;
94
96
this . _svgIconConfigs . set ( key , new SvgIconConfig ( url ) ) ;
95
97
return this ;
96
98
}
97
99
98
100
/** Registers an icon set by URL in the default namespace. */
99
- addSvgIconSet ( url : string ) : this {
101
+ addSvgIconSet ( url : SafeResourceUrl ) : this {
100
102
return this . addSvgIconSetInNamespace ( '' , url ) ;
101
103
}
102
104
103
105
/** Registers an icon set by URL in the specified namespace. */
104
- addSvgIconSetInNamespace ( namespace : string , url : string ) : this {
106
+ addSvgIconSetInNamespace ( namespace : string , url : SafeResourceUrl ) : this {
105
107
const config = new SvgIconConfig ( url ) ;
106
108
if ( this . _iconSetConfigs . has ( namespace ) ) {
107
109
this . _iconSetConfigs . get ( namespace ) . push ( config ) ;
@@ -152,7 +154,9 @@ export class MdIconRegistry {
152
154
* the produced element will always be a new copy of the originally fetched icon. (That is,
153
155
* it will not contain any modifications made to elements previously returned).
154
156
*/
155
- getSvgIconFromUrl ( url : string ) : Observable < SVGElement > {
157
+ getSvgIconFromUrl ( safeUrl : SafeResourceUrl ) : Observable < SVGElement > {
158
+ let url = this . _sanitizer . sanitize ( SecurityContext . RESOURCE_URL , safeUrl ) ;
159
+
156
160
if ( this . _cachedIconsByUrl . has ( url ) ) {
157
161
return Observable . of ( cloneSvg ( this . _cachedIconsByUrl . get ( url ) ) ) ;
158
162
}
@@ -221,9 +225,12 @@ export class MdIconRegistry {
221
225
. map ( iconSetConfig =>
222
226
this . _loadSvgIconSetFromConfig ( iconSetConfig )
223
227
. catch ( ( err : any , caught : Observable < SVGElement > ) : Observable < SVGElement > => {
228
+ let url =
229
+ this . _sanitizer . sanitize ( SecurityContext . RESOURCE_URL , iconSetConfig . url ) ;
230
+
224
231
// Swallow errors fetching individual URLs so the combined Observable won't
225
232
// necessarily fail.
226
- console . log ( `Loading icon set URL: ${ iconSetConfig . url } failed: ${ err } ` ) ;
233
+ console . log ( `Loading icon set URL: ${ url } failed: ${ err } ` ) ;
227
234
return Observable . of ( null ) ;
228
235
} )
229
236
. do ( svg => {
@@ -280,7 +287,7 @@ export class MdIconRegistry {
280
287
private _loadSvgIconSetFromConfig ( config : SvgIconConfig ) : Observable < SVGElement > {
281
288
// TODO: Document that icons should only be loaded from trusted sources.
282
289
return this . _fetchUrl ( config . url )
283
- . map ( ( svgText ) => this . _svgElementFromString ( svgText ) ) ;
290
+ . map ( svgText => this . _svgElementFromString ( svgText ) ) ;
284
291
}
285
292
286
293
/**
@@ -353,7 +360,9 @@ export class MdIconRegistry {
353
360
* Returns an Observable which produces the string contents of the given URL. Results may be
354
361
* cached, so future calls with the same URL may not cause another HTTP request.
355
362
*/
356
- private _fetchUrl ( url : string ) : Observable < string > {
363
+ private _fetchUrl ( safeUrl : SafeResourceUrl ) : Observable < string > {
364
+ let url = this . _sanitizer . sanitize ( SecurityContext . RESOURCE_URL , safeUrl ) ;
365
+
357
366
// Store in-progress fetches to avoid sending a duplicate request for a URL when there is
358
367
// already a request in progress for that URL. It's necessary to call share() on the
359
368
// Observable returned by http.get() so that multiple subscribers don't cause multiple XHRs.
0 commit comments