style.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  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. module.metadata = {
  6. "stability": "experimental"
  7. };
  8. const { Cc, Ci } = require("chrome");
  9. const { Class } = require("../core/heritage");
  10. const { ns } = require("../core/namespace");
  11. const { URL } = require('../url');
  12. const events = require("../system/events");
  13. const { loadSheet, removeSheet, isTypeValid } = require("./utils");
  14. const { isString } = require("../lang/type");
  15. const { attachTo, detachFrom, getTargetWindow } = require("../content/mod");
  16. const { freeze, create } = Object;
  17. const LOCAL_URI_SCHEMES = ['resource', 'data'];
  18. function isLocalURL(item) {
  19. try {
  20. return LOCAL_URI_SCHEMES.indexOf(URL(item).scheme) > -1;
  21. }
  22. catch(e) {}
  23. return false;
  24. }
  25. function Style({ source, uri, type }) {
  26. source = source == null ? null : freeze([].concat(source));
  27. uri = uri == null ? null : freeze([].concat(uri));
  28. type = type == null ? "author" : type;
  29. if (source && !source.every(isString))
  30. throw new Error('Style.source must be a string or an array of strings.');
  31. if (uri && !uri.every(isLocalURL))
  32. throw new Error('Style.uri must be a local URL or an array of local URLs');
  33. if (type && !isTypeValid(type))
  34. throw new Error('Style.type must be "agent", "user" or "author"');
  35. return freeze(create(Style.prototype, {
  36. "source": { value: source, enumerable: true },
  37. "uri": { value: uri, enumerable: true },
  38. "type": { value: type, enumerable: true }
  39. }));
  40. };
  41. exports.Style = Style;
  42. attachTo.define(Style, function (style, window) {
  43. if (style.uri) {
  44. for (let uri of style.uri)
  45. loadSheet(window, uri, style.type);
  46. }
  47. if (style.source) {
  48. let uri = "data:text/css;charset=utf-8,";
  49. uri += encodeURIComponent(style.source.join(""));
  50. loadSheet(window, uri, style.type);
  51. }
  52. });
  53. detachFrom.define(Style, function (style, window) {
  54. if (style.uri)
  55. for (let uri of style.uri)
  56. removeSheet(window, uri);
  57. if (style.source) {
  58. let uri = "data:text/css;charset=utf-8,";
  59. uri += encodeURIComponent(style.source.join(""));
  60. removeSheet(window, uri, style.type);
  61. }
  62. });