install-hook-usercss.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. 'use strict';
  2. function createSourceLoader() {
  3. let source;
  4. function fetchText(url) {
  5. return new Promise((resolve, reject) => {
  6. // you can't use fetch in Chrome under 'file:' protocol
  7. const xhr = new XMLHttpRequest();
  8. xhr.open('GET', url);
  9. xhr.addEventListener('load', () => resolve(xhr.responseText));
  10. xhr.addEventListener('error', () => reject(xhr));
  11. xhr.send();
  12. });
  13. }
  14. function load() {
  15. return fetchText(location.href).then(newSource => {
  16. source = newSource;
  17. return source;
  18. });
  19. }
  20. function watch(cb) {
  21. let timer;
  22. const DELAY = 1000;
  23. function start() {
  24. if (timer) {
  25. return;
  26. }
  27. timer = setTimeout(check, DELAY);
  28. }
  29. function stop() {
  30. clearTimeout(timer);
  31. timer = null;
  32. }
  33. function check() {
  34. fetchText(location.href)
  35. .then(newSource => {
  36. if (source !== newSource) {
  37. source = newSource;
  38. return cb(source);
  39. }
  40. })
  41. .catch(error => {
  42. console.log(t('liveReloadError', error));
  43. })
  44. .then(() => {
  45. timer = setTimeout(check, DELAY);
  46. });
  47. }
  48. return {start, stop};
  49. }
  50. return {load, watch, source: () => source};
  51. }
  52. function initUsercssInstall() {
  53. const sourceLoader = createSourceLoader();
  54. const pendingSource = sourceLoader.load();
  55. let watcher;
  56. chrome.runtime.onConnect.addListener(port => {
  57. port.onMessage.addListener(msg => {
  58. switch (msg.method) {
  59. case 'getSourceCode':
  60. pendingSource
  61. .then(sourceCode => port.postMessage({method: msg.method + 'Response', sourceCode}))
  62. .catch(err => port.postMessage({method: msg.method + 'Response', error: err.message || String(err)}));
  63. break;
  64. case 'liveReloadStart':
  65. if (!watcher) {
  66. watcher = sourceLoader.watch(sourceCode => {
  67. port.postMessage({method: 'sourceCodeChanged', sourceCode});
  68. });
  69. }
  70. watcher.start();
  71. break;
  72. case 'liveReloadStop':
  73. watcher.stop();
  74. break;
  75. case 'closeTab':
  76. if (history.length > 1) {
  77. history.back();
  78. } else {
  79. chrome.runtime.sendMessage({method: 'closeTab'});
  80. }
  81. break;
  82. }
  83. });
  84. });
  85. chrome.runtime.sendMessage({
  86. method: 'openUsercssInstallPage',
  87. url: location.href,
  88. }, r => r && r.__ERROR__ && alert(r.__ERROR__));
  89. }
  90. function isUsercss() {
  91. if (!/text\/(css|plain)/.test(document.contentType)) {
  92. return false;
  93. }
  94. if (!/==userstyle==/i.test(document.body.textContent)) {
  95. return false;
  96. }
  97. return true;
  98. }
  99. if (isUsercss()) {
  100. initUsercssInstall();
  101. }