|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 "use strict"; |
|
5 |
|
6 module.metadata = { |
|
7 "stability": "experimental" |
|
8 }; |
|
9 |
|
10 const { Cc, Ci } = require("chrome"); |
|
11 const { Class } = require("../core/heritage"); |
|
12 const { ns } = require("../core/namespace"); |
|
13 const { URL } = require('../url'); |
|
14 const events = require("../system/events"); |
|
15 const { loadSheet, removeSheet, isTypeValid } = require("./utils"); |
|
16 const { isString } = require("../lang/type"); |
|
17 const { attachTo, detachFrom, getTargetWindow } = require("../content/mod"); |
|
18 |
|
19 const { freeze, create } = Object; |
|
20 const LOCAL_URI_SCHEMES = ['resource', 'data']; |
|
21 |
|
22 function isLocalURL(item) { |
|
23 try { |
|
24 return LOCAL_URI_SCHEMES.indexOf(URL(item).scheme) > -1; |
|
25 } |
|
26 catch(e) {} |
|
27 |
|
28 return false; |
|
29 } |
|
30 |
|
31 function Style({ source, uri, type }) { |
|
32 source = source == null ? null : freeze([].concat(source)); |
|
33 uri = uri == null ? null : freeze([].concat(uri)); |
|
34 type = type == null ? "author" : type; |
|
35 |
|
36 if (source && !source.every(isString)) |
|
37 throw new Error('Style.source must be a string or an array of strings.'); |
|
38 |
|
39 if (uri && !uri.every(isLocalURL)) |
|
40 throw new Error('Style.uri must be a local URL or an array of local URLs'); |
|
41 |
|
42 if (type && !isTypeValid(type)) |
|
43 throw new Error('Style.type must be "agent", "user" or "author"'); |
|
44 |
|
45 return freeze(create(Style.prototype, { |
|
46 "source": { value: source, enumerable: true }, |
|
47 "uri": { value: uri, enumerable: true }, |
|
48 "type": { value: type, enumerable: true } |
|
49 })); |
|
50 }; |
|
51 |
|
52 exports.Style = Style; |
|
53 |
|
54 attachTo.define(Style, function (style, window) { |
|
55 if (style.uri) { |
|
56 for (let uri of style.uri) |
|
57 loadSheet(window, uri, style.type); |
|
58 } |
|
59 |
|
60 if (style.source) { |
|
61 let uri = "data:text/css;charset=utf-8,"; |
|
62 |
|
63 uri += encodeURIComponent(style.source.join("")); |
|
64 |
|
65 loadSheet(window, uri, style.type); |
|
66 } |
|
67 }); |
|
68 |
|
69 detachFrom.define(Style, function (style, window) { |
|
70 if (style.uri) |
|
71 for (let uri of style.uri) |
|
72 removeSheet(window, uri); |
|
73 |
|
74 if (style.source) { |
|
75 let uri = "data:text/css;charset=utf-8,"; |
|
76 |
|
77 uri += encodeURIComponent(style.source.join("")); |
|
78 |
|
79 removeSheet(window, uri, style.type); |
|
80 } |
|
81 }); |