@browserless.io/browserless 2.0.0-beta-5 → 2.0.0-beta-7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/LICENSE +2 -0
  2. package/README.md +11 -11
  3. package/bin/browserless.js +169 -11
  4. package/bin/scaffold/README.md +415 -0
  5. package/bin/scaffold/package.json +21 -0
  6. package/bin/scaffold/src/hello-world.http.ts +27 -0
  7. package/bin/scaffold/tsconfig.json +4 -0
  8. package/build/browserless.js +18 -15
  9. package/build/browsers/index.d.ts +2 -18
  10. package/build/browsers/index.js +43 -14
  11. package/build/file-system.d.ts +5 -0
  12. package/build/file-system.js +20 -5
  13. package/build/file-system.spec.d.ts +1 -0
  14. package/build/file-system.spec.js +44 -0
  15. package/build/http.d.ts +3 -3
  16. package/build/http.js +3 -3
  17. package/build/router.js +2 -4
  18. package/build/routes/chromium/http/content-post.body.json +8 -8
  19. package/build/routes/chromium/http/content-post.d.ts +15 -3
  20. package/build/routes/chromium/http/content-post.js +14 -15
  21. package/build/routes/chromium/http/download-post.d.ts +16 -3
  22. package/build/routes/chromium/http/download-post.js +17 -22
  23. package/build/routes/chromium/http/function-post.d.ts +16 -3
  24. package/build/routes/chromium/http/function-post.js +17 -22
  25. package/build/routes/chromium/http/pdf-post.body.json +8 -8
  26. package/build/routes/chromium/http/pdf-post.d.ts +15 -3
  27. package/build/routes/chromium/http/pdf-post.js +19 -15
  28. package/build/routes/chromium/http/performance.d.ts +15 -3
  29. package/build/routes/chromium/http/performance.js +15 -23
  30. package/build/routes/chromium/http/scrape-post.body.json +8 -8
  31. package/build/routes/chromium/http/scrape-post.d.ts +15 -3
  32. package/build/routes/chromium/http/scrape-post.js +15 -16
  33. package/build/routes/chromium/http/screenshot-post.body.json +8 -8
  34. package/build/routes/chromium/http/screenshot-post.d.ts +15 -3
  35. package/build/routes/chromium/http/screenshot-post.js +18 -15
  36. package/build/routes/chromium/tests/websocket.spec.js +20 -1
  37. package/build/routes/chromium/utils/function/handler.js +2 -2
  38. package/build/routes/chromium/ws/browser.d.ts +13 -3
  39. package/build/routes/chromium/ws/browser.js +10 -11
  40. package/build/routes/chromium/ws/cdp-chromium.d.ts +13 -3
  41. package/build/routes/chromium/ws/cdp-chromium.js +10 -11
  42. package/build/routes/chromium/ws/page.d.ts +13 -3
  43. package/build/routes/chromium/ws/page.js +10 -11
  44. package/build/routes/chromium/ws/playwright-chromium.d.ts +13 -3
  45. package/build/routes/chromium/ws/playwright-chromium.js +11 -12
  46. package/build/routes/firefox/ws/playwright-firefox.d.ts +13 -3
  47. package/build/routes/firefox/ws/playwright-firefox.js +11 -12
  48. package/build/routes/management/http/config-get.d.ts +15 -3
  49. package/build/routes/management/http/config-get.js +15 -20
  50. package/build/routes/management/http/metrics-get.d.ts +15 -3
  51. package/build/routes/management/http/metrics-get.js +16 -21
  52. package/build/routes/management/http/metrics-total-get.d.ts +15 -3
  53. package/build/routes/management/http/metrics-total-get.js +16 -21
  54. package/build/routes/management/http/sessions-get.d.ts +15 -3
  55. package/build/routes/management/http/sessions-get.js +16 -20
  56. package/build/routes/management/http/static-get.d.ts +15 -3
  57. package/build/routes/management/http/static-get.js +15 -20
  58. package/build/routes/webkit/ws/playwright-webkit.d.ts +13 -3
  59. package/build/routes/webkit/ws/playwright-webkit.js +11 -12
  60. package/build/server.js +0 -1
  61. package/build/types.d.ts +48 -38
  62. package/build/types.js +135 -0
  63. package/extensions/ublock/1p-filters.html +0 -1
  64. package/extensions/ublock/3p-filters.html +0 -2
  65. package/extensions/ublock/_locales/bg/messages.json +6 -6
  66. package/extensions/ublock/_locales/br_FR/messages.json +14 -14
  67. package/extensions/ublock/_locales/bs/messages.json +8 -8
  68. package/extensions/ublock/_locales/ca/messages.json +1 -1
  69. package/extensions/ublock/_locales/da/messages.json +5 -5
  70. package/extensions/ublock/_locales/fa/messages.json +1 -1
  71. package/extensions/ublock/_locales/fi/messages.json +6 -6
  72. package/extensions/ublock/_locales/hr/messages.json +4 -4
  73. package/extensions/ublock/_locales/nb/messages.json +1 -1
  74. package/extensions/ublock/_locales/no/messages.json +1 -1
  75. package/extensions/ublock/_locales/ro/messages.json +2 -2
  76. package/extensions/ublock/_locales/ru/messages.json +1 -1
  77. package/extensions/ublock/_locales/sk/messages.json +1 -1
  78. package/extensions/ublock/_locales/sv/messages.json +2 -2
  79. package/extensions/ublock/_locales/te/messages.json +17 -17
  80. package/extensions/ublock/_locales/vi/messages.json +12 -12
  81. package/extensions/ublock/_locales/zh_TW/messages.json +13 -13
  82. package/extensions/ublock/assets/assets.json +3 -3
  83. package/extensions/ublock/assets/resources/scriptlets.js +218 -97
  84. package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +3010 -2056
  85. package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +624 -433
  86. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +93 -24
  87. package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +7 -15
  88. package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +795 -777
  89. package/extensions/ublock/assets/ublock/badware.min.txt +138 -72
  90. package/extensions/ublock/assets/ublock/filters.min.txt +1929 -2735
  91. package/extensions/ublock/assets/ublock/privacy.min.txt +57 -26
  92. package/extensions/ublock/assets/ublock/quick-fixes.min.txt +125 -74
  93. package/extensions/ublock/assets/ublock/unbreak.min.txt +46 -53
  94. package/extensions/ublock/css/codemirror.css +8 -7
  95. package/extensions/ublock/css/dom-inspector.css +40 -0
  96. package/extensions/ublock/css/logger-ui-inspector.css +7 -1
  97. package/extensions/ublock/css/logger-ui.css +12 -5
  98. package/extensions/ublock/css/popup-fenix.css +1 -1
  99. package/extensions/ublock/devtools.html +1 -0
  100. package/extensions/ublock/js/1p-filters.js +4 -3
  101. package/extensions/ublock/js/3p-filters.js +25 -31
  102. package/extensions/ublock/js/about.js +1 -1
  103. package/extensions/ublock/js/advanced-settings.js +1 -1
  104. package/extensions/ublock/js/asset-viewer.js +1 -1
  105. package/extensions/ublock/js/assets.js +74 -44
  106. package/extensions/ublock/js/background.js +9 -3
  107. package/extensions/ublock/js/base64-custom.js +1 -1
  108. package/extensions/ublock/js/benchmarks.js +1 -1
  109. package/extensions/ublock/js/biditrie.js +1 -1
  110. package/extensions/ublock/js/broadcast.js +75 -0
  111. package/extensions/ublock/js/cachestorage.js +68 -45
  112. package/extensions/ublock/js/click2load.js +1 -1
  113. package/extensions/ublock/js/cloud-ui.js +1 -1
  114. package/extensions/ublock/js/code-viewer.js +1 -1
  115. package/extensions/ublock/js/codemirror/search-thread.js +1 -1
  116. package/extensions/ublock/js/codemirror/search.js +1 -1
  117. package/extensions/ublock/js/codemirror/ubo-dynamic-filtering.js +1 -1
  118. package/extensions/ublock/js/codemirror/ubo-static-filtering.js +98 -24
  119. package/extensions/ublock/js/commands.js +1 -1
  120. package/extensions/ublock/js/console.js +1 -1
  121. package/extensions/ublock/js/contentscript-extra.js +1 -1
  122. package/extensions/ublock/js/contentscript.js +1 -3
  123. package/extensions/ublock/js/contextmenu.js +1 -1
  124. package/extensions/ublock/js/cosmetic-filtering.js +4 -4
  125. package/extensions/ublock/js/dashboard-common.js +1 -1
  126. package/extensions/ublock/js/dashboard.js +1 -1
  127. package/extensions/ublock/js/devtools.js +23 -15
  128. package/extensions/ublock/js/diff-updater.js +3 -3
  129. package/extensions/ublock/js/document-blocked.js +1 -1
  130. package/extensions/ublock/js/dom-inspector.js +68 -0
  131. package/extensions/ublock/js/dom.js +1 -1
  132. package/extensions/ublock/js/dyna-rules.js +1 -1
  133. package/extensions/ublock/js/dynamic-net-filtering.js +1 -1
  134. package/extensions/ublock/js/epicker-ui.js +35 -59
  135. package/extensions/ublock/js/fa-icons.js +1 -1
  136. package/extensions/ublock/js/filtering-context.js +1 -1
  137. package/extensions/ublock/js/filtering-engines.js +1 -1
  138. package/extensions/ublock/js/hnswitches.js +1 -1
  139. package/extensions/ublock/js/hntrie.js +1 -1
  140. package/extensions/ublock/js/html-filtering.js +1 -1
  141. package/extensions/ublock/js/httpheader-filtering.js +1 -1
  142. package/extensions/ublock/js/i18n.js +1 -1
  143. package/extensions/ublock/js/is-webrtc-supported.js +1 -1
  144. package/extensions/ublock/js/logger-ui-inspector.js +203 -145
  145. package/extensions/ublock/js/logger-ui.js +21 -5
  146. package/extensions/ublock/js/logger.js +6 -2
  147. package/extensions/ublock/js/lz4.js +2 -2
  148. package/extensions/ublock/js/messaging.js +266 -166
  149. package/extensions/ublock/js/mrucache.js +58 -0
  150. package/extensions/ublock/js/pagestore.js +1 -1
  151. package/extensions/ublock/js/popup-fenix.js +2 -1
  152. package/extensions/ublock/js/redirect-engine.js +1 -1
  153. package/extensions/ublock/js/redirect-resources.js +1 -12
  154. package/extensions/ublock/js/reverselookup-worker.js +1 -1
  155. package/extensions/ublock/js/reverselookup.js +1 -1
  156. package/extensions/ublock/js/scriptlet-filtering-core.js +300 -0
  157. package/extensions/ublock/js/scriptlet-filtering.js +122 -350
  158. package/extensions/ublock/js/scriptlets/cosmetic-logger.js +36 -47
  159. package/extensions/ublock/js/scriptlets/cosmetic-off.js +1 -1
  160. package/extensions/ublock/js/scriptlets/cosmetic-on.js +1 -1
  161. package/extensions/ublock/js/scriptlets/cosmetic-report.js +1 -1
  162. package/extensions/ublock/js/scriptlets/dom-inspector.js +341 -323
  163. package/extensions/ublock/js/scriptlets/dom-survey-elements.js +1 -1
  164. package/extensions/ublock/js/scriptlets/dom-survey-scripts.js +1 -1
  165. package/extensions/ublock/js/scriptlets/epicker.js +80 -89
  166. package/extensions/ublock/js/scriptlets/load-3p-css.js +1 -1
  167. package/extensions/ublock/js/scriptlets/load-large-media-all.js +1 -1
  168. package/extensions/ublock/js/scriptlets/load-large-media-interactive.js +1 -1
  169. package/extensions/ublock/js/scriptlets/noscript-spoof.js +1 -1
  170. package/extensions/ublock/js/scriptlets/should-inject-contentscript.js +1 -1
  171. package/extensions/ublock/js/scriptlets/subscriber.js +1 -1
  172. package/extensions/ublock/js/scriptlets/updater.js +20 -3
  173. package/extensions/ublock/js/settings.js +1 -1
  174. package/extensions/ublock/js/start.js +19 -20
  175. package/extensions/ublock/js/static-dnr-filtering.js +1 -1
  176. package/extensions/ublock/js/static-ext-filtering-db.js +1 -1
  177. package/extensions/ublock/js/static-ext-filtering.js +1 -1
  178. package/extensions/ublock/js/static-filtering-io.js +1 -1
  179. package/extensions/ublock/js/static-filtering-parser.js +5 -3
  180. package/extensions/ublock/js/static-net-filtering.js +57 -37
  181. package/extensions/ublock/js/storage.js +49 -29
  182. package/extensions/ublock/js/support.js +4 -4
  183. package/extensions/ublock/js/tab.js +1 -1
  184. package/extensions/ublock/js/tasks.js +1 -1
  185. package/extensions/ublock/js/text-encode.js +1 -1
  186. package/extensions/ublock/js/text-utils.js +1 -1
  187. package/extensions/ublock/js/theme.js +1 -1
  188. package/extensions/ublock/js/traffic.js +2 -1
  189. package/extensions/ublock/js/ublock.js +15 -11
  190. package/extensions/ublock/js/uri-utils.js +1 -1
  191. package/extensions/ublock/js/url-net-filtering.js +1 -1
  192. package/extensions/ublock/js/utils.js +1 -73
  193. package/extensions/ublock/js/vapi-background-ext.js +1 -1
  194. package/extensions/ublock/js/vapi-background.js +92 -83
  195. package/extensions/ublock/js/vapi-client.js +4 -33
  196. package/extensions/ublock/js/vapi-common.js +16 -30
  197. package/extensions/ublock/js/vapi.js +1 -1
  198. package/extensions/ublock/js/wasm/biditrie.wat +1 -1
  199. package/extensions/ublock/js/wasm/hntrie.wat +1 -1
  200. package/extensions/ublock/js/webext.js +1 -1
  201. package/extensions/ublock/js/whitelist.js +1 -1
  202. package/extensions/ublock/logger-ui.html +2 -2
  203. package/extensions/ublock/manifest.json +1 -1
  204. package/extensions/ublock/support.html +0 -1
  205. package/extensions/ublock/web_accessible_resources/dom-inspector.html +25 -0
  206. package/extensions/ublock/web_accessible_resources/epicker-ui.html +0 -1
  207. package/extensions/ublock/web_accessible_resources/googletagservices_gpt.js +1 -0
  208. package/package.json +7 -19
  209. package/scripts/build-open-api.js +7 -4
  210. package/src/browserless.ts +42 -18
  211. package/src/browsers/index.ts +48 -20
  212. package/src/file-system.spec.ts +58 -0
  213. package/src/file-system.ts +36 -8
  214. package/src/http.ts +3 -3
  215. package/src/router.ts +2 -6
  216. package/src/routes/chromium/http/content-post.ts +13 -16
  217. package/src/routes/chromium/http/download-post.ts +16 -27
  218. package/src/routes/chromium/http/function-post.ts +16 -25
  219. package/src/routes/chromium/http/pdf-post.ts +19 -15
  220. package/src/routes/chromium/http/performance.ts +14 -26
  221. package/src/routes/chromium/http/scrape-post.ts +14 -16
  222. package/src/routes/chromium/http/screenshot-post.ts +18 -15
  223. package/src/routes/chromium/tests/websocket.spec.ts +28 -1
  224. package/src/routes/chromium/utils/function/handler.ts +2 -1
  225. package/src/routes/chromium/ws/browser.ts +10 -12
  226. package/src/routes/chromium/ws/cdp-chromium.ts +10 -12
  227. package/src/routes/chromium/ws/page.ts +10 -12
  228. package/src/routes/chromium/ws/playwright-chromium.ts +10 -12
  229. package/src/routes/firefox/ws/playwright-firefox.ts +10 -12
  230. package/src/routes/management/http/config-get.ts +14 -23
  231. package/src/routes/management/http/metrics-get.ts +15 -24
  232. package/src/routes/management/http/metrics-total-get.ts +15 -26
  233. package/src/routes/management/http/sessions-get.ts +15 -23
  234. package/src/routes/management/http/static-get.ts +14 -22
  235. package/src/routes/webkit/ws/playwright-webkit.ts +10 -12
  236. package/src/server.ts +0 -1
  237. package/src/types.ts +59 -45
  238. package/static/docs/browserless-logo-inline.svg +1 -0
  239. package/static/docs/index.html +27 -0
  240. package/static/docs/swagger.json +33 -33
  241. package/static/function/client.js +626 -78
  242. package/extensions/ublock/js/vapi-client-extra.js +0 -312
  243. package/extensions/ublock/web_accessible_resources/addthis_widget.js +0 -39
  244. package/extensions/ublock/web_accessible_resources/ligatus_angular-tag.js +0 -29
  245. package/extensions/ublock/web_accessible_resources/monkeybroker.js +0 -43
  246. package/extensions/ublock/web_accessible_resources/mxpnl_mixpanel.js +0 -51
@@ -1,7 +1,7 @@
1
1
  /*******************************************************************************
2
2
 
3
- uBlock Origin - a browser extension to block requests.
4
- Copyright (C) 2015-2018 Raymond Hill
3
+ uBlock Origin - a comprehensive, efficient content blocker
4
+ Copyright (C) 2015-present Raymond Hill
5
5
 
6
6
  This program is free software: you can redistribute it and/or modify
7
7
  it under the terms of the GNU General Public License as published by
@@ -19,47 +19,39 @@
19
19
  Home: https://github.com/gorhill/uBlock
20
20
  */
21
21
 
22
+ /* globals browser */
23
+
22
24
  'use strict';
23
25
 
24
26
  /******************************************************************************/
25
27
  /******************************************************************************/
26
28
 
27
- (( ) => {
28
-
29
- /******************************************************************************/
30
-
31
- if ( typeof vAPI !== 'object' || !vAPI.domFilterer ) { return; }
29
+ (async ( ) => {
32
30
 
33
31
  /******************************************************************************/
34
32
 
35
- var sessionId = vAPI.sessionId;
36
-
37
- if ( document.querySelector('iframe.dom-inspector.' + sessionId) !== null ) {
38
- return;
39
- }
40
-
41
- /******************************************************************************/
42
- /******************************************************************************/
33
+ if ( typeof vAPI !== 'object' ) { return; }
34
+ if ( typeof vAPI === null ) { return; }
35
+ if ( vAPI.domFilterer instanceof Object === false ) { return; }
43
36
 
44
- let loggerConnectionId;
37
+ if ( vAPI.inspectorFrame ) { return; }
38
+ vAPI.inspectorFrame = true;
45
39
 
46
- // Highlighter-related
47
- let svgRoot = null;
48
- let pickerRoot = null;
40
+ const inspectorUniqueId = vAPI.randomToken();
49
41
 
50
- let nodeToIdMap = new WeakMap(); // No need to iterate
42
+ const nodeToIdMap = new WeakMap(); // No need to iterate
51
43
 
52
44
  let blueNodes = [];
53
45
  const roRedNodes = new Map(); // node => current cosmetic filter
54
46
  const rwRedNodes = new Set(); // node => new cosmetic filter (toggle node)
55
- //var roGreenNodes = new Map(); // node => current exception cosmetic filter (can't toggle)
56
47
  const rwGreenNodes = new Set(); // node => new exception cosmetic filter (toggle filter)
48
+ //const roGreenNodes = new Map(); // node => current exception cosmetic filter (can't toggle)
57
49
 
58
50
  const reHasCSSCombinators = /[ >+~]/;
59
51
 
60
52
  /******************************************************************************/
61
53
 
62
- const domLayout = (function() {
54
+ const domLayout = (( ) => {
63
55
  const skipTagNames = new Set([
64
56
  'br', 'head', 'link', 'meta', 'script', 'style', 'title'
65
57
  ]);
@@ -70,87 +62,81 @@ const domLayout = (function() {
70
62
  [ 'object', 'data' ]
71
63
  ]);
72
64
 
73
- var idGenerator = 0;
65
+ let idGenerator = 1;
74
66
 
75
67
  // This will be used to uniquely identify nodes across process.
76
68
 
77
- const newNodeId = function(node) {
78
- var nid = 'n' + (idGenerator++).toString(36);
69
+ const newNodeId = node => {
70
+ const nid = `n${(idGenerator++).toString(36)}`;
79
71
  nodeToIdMap.set(node, nid);
80
72
  return nid;
81
73
  };
82
74
 
83
- const selectorFromNode = function(node) {
84
- var str, attr, pos, sw, i;
85
- var tag = node.localName;
86
- var selector = CSS.escape(tag);
75
+ const selectorFromNode = node => {
76
+ const tag = node.localName;
77
+ let selector = CSS.escape(tag);
87
78
  // Id
88
79
  if ( typeof node.id === 'string' ) {
89
- str = node.id.trim();
80
+ let str = node.id.trim();
90
81
  if ( str !== '' ) {
91
- selector += '#' + CSS.escape(str);
82
+ selector += `#${CSS.escape(str)}`;
92
83
  }
93
84
  }
94
85
  // Class
95
- var cl = node.classList;
86
+ const cl = node.classList;
96
87
  if ( cl ) {
97
- for ( i = 0; i < cl.length; i++ ) {
98
- selector += '.' + CSS.escape(cl[i]);
88
+ for ( let i = 0; i < cl.length; i++ ) {
89
+ selector += `.${CSS.escape(cl[i])}`;
99
90
  }
100
91
  }
101
92
  // Tag-specific attributes
102
- attr = resourceAttrNames.get(tag);
93
+ const attr = resourceAttrNames.get(tag);
103
94
  if ( attr !== undefined ) {
104
- str = node.getAttribute(attr) || '';
95
+ let str = node.getAttribute(attr) || '';
105
96
  str = str.trim();
106
- if ( str.startsWith('data:') ) {
107
- pos = 5;
108
- } else {
109
- pos = str.search(/[#?]/);
110
- }
97
+ const pos = str.startsWith('data:') ? 5 : str.search(/[#?]/);
98
+ let sw = '';
111
99
  if ( pos !== -1 ) {
112
100
  str = str.slice(0, pos);
113
101
  sw = '^';
114
- } else {
115
- sw = '';
116
102
  }
117
103
  if ( str !== '' ) {
118
- selector += '[' + attr + sw + '="' + CSS.escape(str, true) + '"]';
104
+ selector += `[${attr}${sw}="${CSS.escape(str, true)}"]`;
119
105
  }
120
106
  }
121
107
  return selector;
122
108
  };
123
109
 
124
- const DomRoot = function() {
110
+ function DomRoot() {
125
111
  this.nid = newNodeId(document.body);
126
112
  this.lvl = 0;
127
113
  this.sel = 'body';
128
114
  this.cnt = 0;
129
115
  this.filter = roRedNodes.get(document.body);
130
- };
116
+ }
131
117
 
132
- const DomNode = function(node, level) {
118
+ function DomNode(node, level) {
133
119
  this.nid = newNodeId(node);
134
120
  this.lvl = level;
135
121
  this.sel = selectorFromNode(node);
136
122
  this.cnt = 0;
137
123
  this.filter = roRedNodes.get(node);
138
- };
124
+ }
139
125
 
140
- const domNodeFactory = function(level, node) {
126
+ const domNodeFactory = (level, node) => {
141
127
  const localName = node.localName;
142
128
  if ( skipTagNames.has(localName) ) { return null; }
143
129
  // skip uBlock's own nodes
144
- if ( node.classList.contains(sessionId) ) { return null; }
130
+ if ( node === inspectorFrame ) { return null; }
145
131
  if ( level === 0 && localName === 'body' ) {
146
132
  return new DomRoot();
147
133
  }
148
134
  return new DomNode(node, level);
149
135
  };
150
136
 
151
- // Collect layout data.
137
+ // Collect layout data
152
138
 
153
- const getLayoutData = function() {
139
+ const getLayoutData = ( ) => {
154
140
  const layout = [];
155
141
  const stack = [];
156
142
  let lvl = 0;
@@ -163,7 +149,7 @@ const domLayout = (function() {
163
149
  layout.push(domNode);
164
150
  }
165
151
  // children
166
- if ( node.firstElementChild !== null ) {
152
+ if ( domNode !== null && node.firstElementChild !== null ) {
167
153
  stack.push(node);
168
154
  lvl += 1;
169
155
  node = node.firstElementChild;
@@ -188,14 +174,14 @@ const domLayout = (function() {
188
174
 
189
175
  // Descendant count for each node.
190
176
 
191
- const patchLayoutData = function(layout) {
192
- var stack = [], ptr;
193
- var lvl = 0;
194
- var domNode, cnt;
195
- var i = layout.length;
177
+ const patchLayoutData = layout => {
178
+ const stack = [];
179
+ let ptr;
180
+ let lvl = 0;
181
+ let i = layout.length;
196
182
 
197
183
  while ( i-- ) {
198
- domNode = layout[i];
184
+ const domNode = layout[i];
199
185
  if ( domNode.lvl === lvl ) {
200
186
  stack[ptr] += 1;
201
187
  continue;
@@ -210,7 +196,7 @@ const domLayout = (function() {
210
196
  continue;
211
197
  }
212
198
  // domNode.lvl < lvl
213
- cnt = stack.pop();
199
+ const cnt = stack.pop();
214
200
  domNode.cnt = cnt;
215
201
  lvl -= 1;
216
202
  ptr = lvl - 1;
@@ -221,13 +207,13 @@ const domLayout = (function() {
221
207
 
222
208
  // Track and report mutations of the DOM
223
209
 
224
- var mutationObserver = null;
225
- var mutationTimer;
226
- var addedNodelists = [];
227
- var removedNodelist = [];
210
+ let mutationObserver = null;
211
+ let mutationTimer;
212
+ let addedNodelists = [];
213
+ let removedNodelist = [];
228
214
 
229
- const previousElementSiblingId = function(node) {
230
- var sibling = node;
215
+ const previousElementSiblingId = node => {
216
+ let sibling = node;
231
217
  for (;;) {
232
218
  sibling = sibling.previousElementSibling;
233
219
  if ( sibling === null ) { return null; }
@@ -236,11 +222,10 @@ const domLayout = (function() {
236
222
  }
237
223
  };
238
224
 
239
- const journalFromBranch = function(root, newNodes, newNodeToIdMap) {
240
- var domNode;
241
- var node = root.firstElementChild;
225
+ const journalFromBranch = (root, newNodes, newNodeToIdMap) => {
226
+ let node = root.firstElementChild;
242
227
  while ( node !== null ) {
243
- domNode = domNodeFactory(undefined, node);
228
+ const domNode = domNodeFactory(undefined, node);
244
229
  if ( domNode !== null ) {
245
230
  newNodeToIdMap.set(domNode.nid, domNode);
246
231
  newNodes.push(node);
@@ -267,22 +252,21 @@ const domLayout = (function() {
267
252
  }
268
253
  };
269
254
 
270
- const journalFromMutations = function() {
271
- var nodelist, node, domNode, nid;
255
+ const journalFromMutations = ( ) => {
272
256
  mutationTimer = undefined;
273
257
 
274
258
  // This is used to temporarily hold all added nodes, before resolving
275
259
  // their node id and relative position.
276
- var newNodes = [];
277
- var journalEntries = [];
278
- var newNodeToIdMap = new Map();
260
+ const newNodes = [];
261
+ const journalEntries = [];
262
+ const newNodeToIdMap = new Map();
279
263
 
280
- for ( nodelist of addedNodelists ) {
281
- for ( node of nodelist ) {
264
+ for ( const nodelist of addedNodelists ) {
265
+ for ( const node of nodelist ) {
282
266
  if ( node.nodeType !== 1 ) { continue; }
283
267
  if ( node.parentElement === null ) { continue; }
284
268
  cosmeticFilterMapper.incremental(node);
285
- domNode = domNodeFactory(undefined, node);
269
+ const domNode = domNodeFactory(undefined, node);
286
270
  if ( domNode !== null ) {
287
271
  newNodeToIdMap.set(domNode.nid, domNode);
288
272
  newNodes.push(node);
@@ -291,19 +275,16 @@ const domLayout = (function() {
291
275
  }
292
276
  }
293
277
  addedNodelists = [];
294
- for ( nodelist of removedNodelist ) {
295
- for ( node of nodelist ) {
278
+ for ( const nodelist of removedNodelist ) {
279
+ for ( const node of nodelist ) {
296
280
  if ( node.nodeType !== 1 ) { continue; }
297
- nid = nodeToIdMap.get(node);
281
+ const nid = nodeToIdMap.get(node);
298
282
  if ( nid === undefined ) { continue; }
299
- journalEntries.push({
300
- what: -1,
301
- nid: nid
302
- });
283
+ journalEntries.push({ what: -1, nid });
303
284
  }
304
285
  }
305
286
  removedNodelist = [];
306
- for ( node of newNodes ) {
287
+ for ( const node of newNodes ) {
307
288
  journalEntries.push({
308
289
  what: 1,
309
290
  nid: nodeToIdMap.get(node),
@@ -314,7 +295,7 @@ const domLayout = (function() {
314
295
 
315
296
  if ( journalEntries.length === 0 ) { return; }
316
297
 
317
- vAPI.MessagingConnection.sendTo(loggerConnectionId, {
298
+ contentInspectorChannel.toLogger({
318
299
  what: 'domLayoutIncremental',
319
300
  url: window.location.href,
320
301
  hostname: window.location.hostname,
@@ -323,8 +304,8 @@ const domLayout = (function() {
323
304
  });
324
305
  };
325
306
 
326
- const onMutationObserved = function(mutationRecords) {
327
- for ( var record of mutationRecords ) {
307
+ const onMutationObserved = mutationRecords => {
308
+ for ( const record of mutationRecords ) {
328
309
  if ( record.addedNodes.length !== 0 ) {
329
310
  addedNodelists.push(record.addedNodes);
330
311
  }
@@ -339,7 +320,7 @@ const domLayout = (function() {
339
320
 
340
321
  // API
341
322
 
342
- const getLayout = function() {
323
+ const getLayout = ( ) => {
343
324
  cosmeticFilterMapper.reset();
344
325
  mutationObserver = new MutationObserver(onMutationObserved);
345
326
  mutationObserver.observe(document.body, {
@@ -355,11 +336,11 @@ const domLayout = (function() {
355
336
  };
356
337
  };
357
338
 
358
- const reset = function() {
339
+ const reset = ( ) => {
359
340
  shutdown();
360
341
  };
361
342
 
362
- const shutdown = function() {
343
+ const shutdown = ( ) => {
363
344
  if ( mutationTimer !== undefined ) {
364
345
  clearTimeout(mutationTimer);
365
346
  mutationTimer = undefined;
@@ -370,35 +351,20 @@ const domLayout = (function() {
370
351
  }
371
352
  addedNodelists = [];
372
353
  removedNodelist = [];
373
- nodeToIdMap = new WeakMap();
374
354
  };
375
355
 
376
356
  return {
377
357
  get: getLayout,
378
- reset: reset,
379
- shutdown: shutdown
358
+ reset,
359
+ shutdown,
380
360
  };
381
361
  })();
382
362
 
383
- // https://www.youtube.com/watch?v=qo8zKhd4Cf0
384
-
385
363
  /******************************************************************************/
386
364
  /******************************************************************************/
387
365
 
388
- // For browsers not supporting `:scope`, it's not the end of the world: the
389
- // suggested CSS selectors may just end up being more verbose.
390
-
391
- let cssScope = ':scope > ';
392
- try {
393
- document.querySelector(':scope *');
394
- } catch (e) {
395
- cssScope = '';
396
- }
397
-
398
- /******************************************************************************/
399
-
400
- const cosmeticFilterMapper = (function() {
401
- const nodesFromStyleTag = function(rootNode) {
366
+ const cosmeticFilterMapper = (( ) => {
367
+ const nodesFromStyleTag = rootNode => {
402
368
  const filterMap = roRedNodes;
403
369
  const details = vAPI.domFilterer.getAllSelectors();
404
370
 
@@ -434,25 +400,25 @@ const cosmeticFilterMapper = (function() {
434
400
  }
435
401
  };
436
402
 
437
- const incremental = function(rootNode) {
403
+ const incremental = rootNode => {
438
404
  nodesFromStyleTag(rootNode);
439
405
  };
440
406
 
441
- const reset = function() {
407
+ const reset = ( ) => {
442
408
  roRedNodes.clear();
443
409
  if ( document.documentElement !== null ) {
444
410
  incremental(document.documentElement);
445
411
  }
446
412
  };
447
413
 
448
- const shutdown = function() {
414
+ const shutdown = ( ) => {
449
415
  vAPI.domFilterer.toggle(true);
450
416
  };
451
417
 
452
418
  return {
453
- incremental: incremental,
454
- reset: reset,
455
- shutdown: shutdown
419
+ incremental,
420
+ reset,
421
+ shutdown,
456
422
  };
457
423
  })();
458
424
 
@@ -475,21 +441,18 @@ const elementsFromSelector = function(selector, context) {
475
441
  };
476
442
 
477
443
  const elementsFromSpecialSelector = function(selector) {
478
- var out = [], i;
479
- var matches = /^(.+?):has\((.+?)\)$/.exec(selector);
444
+ const out = [];
445
+ let matches = /^(.+?):has\((.+?)\)$/.exec(selector);
480
446
  if ( matches !== null ) {
481
- var nodes;
447
+ let nodes;
482
448
  try {
483
449
  nodes = document.querySelectorAll(matches[1]);
484
450
  } catch(ex) {
485
451
  nodes = [];
486
452
  }
487
- i = nodes.length;
488
- while ( i-- ) {
489
- var node = nodes[i];
490
- if ( node.querySelector(matches[2]) !== null ) {
491
- out.push(node);
492
- }
453
+ for ( const node of nodes ) {
454
+ if ( node.querySelector(matches[2]) === null ) { continue; }
455
+ out.push(node);
493
456
  }
494
457
  return out;
495
458
  }
@@ -503,7 +466,7 @@ const elementsFromSpecialSelector = function(selector) {
503
466
  XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
504
467
  null
505
468
  );
506
- i = xpr.snapshotLength;
469
+ let i = xpr.snapshotLength;
507
470
  while ( i-- ) {
508
471
  out.push(xpr.snapshotItem(i));
509
472
  }
@@ -512,128 +475,114 @@ const elementsFromSpecialSelector = function(selector) {
512
475
 
513
476
  /******************************************************************************/
514
477
 
515
- const getSvgRootChildren = function() {
516
- if ( svgRoot.children ) {
517
- return svgRoot.children;
518
- } else {
519
- const childNodes = Array.prototype.slice.apply(svgRoot.childNodes);
520
- return childNodes.filter(function(node) {
521
- return node.nodeType === Node.ELEMENT_NODE;
522
- });
523
- }
524
- };
525
-
526
- const highlightElements = function() {
527
- var islands;
528
- var elem, rect, poly;
529
- var xl, xr, yt, yb, w, h, ws;
530
- var svgRootChildren = getSvgRootChildren();
478
+ const highlightElements = ( ) => {
479
+ const paths = [];
531
480
 
532
- islands = [];
533
- for ( elem of rwRedNodes.keys() ) {
534
- if ( elem === pickerRoot ) { continue; }
481
+ const path = [];
482
+ for ( const elem of rwRedNodes.keys() ) {
483
+ if ( elem === inspectorFrame ) { continue; }
535
484
  if ( rwGreenNodes.has(elem) ) { continue; }
536
485
  if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; }
537
- rect = elem.getBoundingClientRect();
538
- xl = rect.left;
539
- xr = rect.right;
540
- w = rect.width;
541
- yt = rect.top;
542
- yb = rect.bottom;
543
- h = rect.height;
544
- ws = w.toFixed(1);
545
- poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
486
+ const rect = elem.getBoundingClientRect();
487
+ const xl = rect.left;
488
+ const w = rect.width;
489
+ const yt = rect.top;
490
+ const h = rect.height;
491
+ const ws = w.toFixed(1);
492
+ const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
546
493
  'h' + ws +
547
494
  'v' + h.toFixed(1) +
548
495
  'h-' + ws +
549
496
  'z';
550
- islands.push(poly);
497
+ path.push(poly);
551
498
  }
552
- svgRootChildren[0].setAttribute('d', islands.join('') || 'M0 0');
499
+ paths.push(path.join('') || 'M0 0');
553
500
 
554
- islands = [];
555
- for ( elem of rwGreenNodes ) {
501
+ path.length = 0;
502
+ for ( const elem of rwGreenNodes ) {
556
503
  if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; }
557
- rect = elem.getBoundingClientRect();
558
- xl = rect.left;
559
- xr = rect.right;
560
- w = rect.width;
561
- yt = rect.top;
562
- yb = rect.bottom;
563
- h = rect.height;
564
- ws = w.toFixed(1);
565
- poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
504
+ const rect = elem.getBoundingClientRect();
505
+ const xl = rect.left;
506
+ const w = rect.width;
507
+ const yt = rect.top;
508
+ const h = rect.height;
509
+ const ws = w.toFixed(1);
510
+ const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
566
511
  'h' + ws +
567
512
  'v' + h.toFixed(1) +
568
513
  'h-' + ws +
569
514
  'z';
570
- islands.push(poly);
515
+ path.push(poly);
571
516
  }
572
- svgRootChildren[1].setAttribute('d', islands.join('') || 'M0 0');
517
+ paths.push(path.join('') || 'M0 0');
573
518
 
574
- islands = [];
575
- for ( elem of roRedNodes.keys() ) {
576
- if ( elem === pickerRoot ) { continue; }
519
+ path.length = 0;
520
+ for ( const elem of roRedNodes.keys() ) {
521
+ if ( elem === inspectorFrame ) { continue; }
577
522
  if ( rwGreenNodes.has(elem) ) { continue; }
578
523
  if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; }
579
- rect = elem.getBoundingClientRect();
580
- xl = rect.left;
581
- xr = rect.right;
582
- w = rect.width;
583
- yt = rect.top;
584
- yb = rect.bottom;
585
- h = rect.height;
586
- ws = w.toFixed(1);
587
- poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
524
+ const rect = elem.getBoundingClientRect();
525
+ const xl = rect.left;
526
+ const w = rect.width;
527
+ const yt = rect.top;
528
+ const h = rect.height;
529
+ const ws = w.toFixed(1);
530
+ const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
588
531
  'h' + ws +
589
532
  'v' + h.toFixed(1) +
590
533
  'h-' + ws +
591
534
  'z';
592
- islands.push(poly);
535
+ path.push(poly);
593
536
  }
594
- svgRootChildren[2].setAttribute('d', islands.join('') || 'M0 0');
537
+ paths.push(path.join('') || 'M0 0');
595
538
 
596
- islands = [];
597
- for ( elem of blueNodes ) {
598
- if ( elem === pickerRoot ) { continue; }
539
+ path.length = 0;
540
+ for ( const elem of blueNodes ) {
541
+ if ( elem === inspectorFrame ) { continue; }
599
542
  if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; }
600
- rect = elem.getBoundingClientRect();
601
- xl = rect.left;
602
- xr = rect.right;
603
- w = rect.width;
604
- yt = rect.top;
605
- yb = rect.bottom;
606
- h = rect.height;
607
- ws = w.toFixed(1);
608
- poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
543
+ const rect = elem.getBoundingClientRect();
544
+ const xl = rect.left;
545
+ const w = rect.width;
546
+ const yt = rect.top;
547
+ const h = rect.height;
548
+ const ws = w.toFixed(1);
549
+ const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) +
609
550
  'h' + ws +
610
551
  'v' + h.toFixed(1) +
611
552
  'h-' + ws +
612
553
  'z';
613
- islands.push(poly);
554
+ path.push(poly);
614
555
  }
615
- svgRootChildren[3].setAttribute('d', islands.join('') || 'M0 0');
556
+ paths.push(path.join('') || 'M0 0');
557
+
558
+ contentInspectorChannel.toFrame({
559
+ what: 'svgPaths',
560
+ paths,
561
+ });
616
562
  };
617
563
 
618
564
  /******************************************************************************/
619
565
 
620
- const onScrolled = (function() {
621
- let buffered = false;
622
- const timerHandler = function() {
623
- buffered = false;
624
- highlightElements();
625
- };
626
- return function() {
627
- if ( buffered === false ) {
628
- window.requestAnimationFrame(timerHandler);
629
- buffered = true;
630
- }
566
+ const onScrolled = (( ) => {
567
+ let timer;
568
+ return ( ) => {
569
+ if ( timer ) { return; }
570
+ timer = window.requestAnimationFrame(( ) => {
571
+ timer = undefined;
572
+ highlightElements();
573
+ });
631
574
  };
632
575
  })();
633
576
 
577
+ const onMouseOver = ( ) => {
578
+ if ( blueNodes.length === 0 ) { return; }
579
+ blueNodes = [];
580
+ highlightElements();
581
+ };
582
+
634
583
  /******************************************************************************/
635
584
 
636
- const selectNodes = function(selector, nid) {
585
+ const selectNodes = (selector, nid) => {
637
586
  const nodes = elementsFromSelector(selector);
638
587
  if ( nid === '' ) { return nodes; }
639
588
  for ( const node of nodes ) {
@@ -646,7 +595,7 @@ const selectNodes = function(selector, nid) {
646
595
 
647
596
  /******************************************************************************/
648
597
 
649
- const nodesFromFilter = function(selector) {
598
+ const nodesFromFilter = selector => {
650
599
  const out = [];
651
600
  for ( const entry of roRedNodes ) {
652
601
  if ( entry[1] === selector ) {
@@ -658,7 +607,7 @@ const nodesFromFilter = function(selector) {
658
607
 
659
608
  /******************************************************************************/
660
609
 
661
- const toggleExceptions = function(nodes, targetState) {
610
+ const toggleExceptions = (nodes, targetState) => {
662
611
  for ( const node of nodes ) {
663
612
  if ( targetState ) {
664
613
  rwGreenNodes.add(node);
@@ -668,7 +617,7 @@ const toggleExceptions = function(nodes, targetState) {
668
617
  }
669
618
  };
670
619
 
671
- const toggleFilter = function(nodes, targetState) {
620
+ const toggleFilter = (nodes, targetState) => {
672
621
  for ( const node of nodes ) {
673
622
  if ( targetState ) {
674
623
  rwRedNodes.delete(node);
@@ -678,23 +627,28 @@ const toggleFilter = function(nodes, targetState) {
678
627
  }
679
628
  };
680
629
 
681
- const resetToggledNodes = function() {
630
+ const resetToggledNodes = ( ) => {
682
631
  rwGreenNodes.clear();
683
632
  rwRedNodes.clear();
684
633
  };
685
634
 
686
635
  /******************************************************************************/
687
636
 
688
- const start = function() {
689
- const onReady = function(ev) {
690
- if ( ev ) {
691
- document.removeEventListener(ev.type, onReady);
692
- }
693
- vAPI.MessagingConnection.sendTo(loggerConnectionId, domLayout.get());
637
+ const startInspector = ( ) => {
638
+ const onReady = ( ) => {
639
+ window.addEventListener('scroll', onScrolled, {
640
+ capture: true,
641
+ passive: true,
642
+ });
643
+ window.addEventListener('mouseover', onMouseOver, {
644
+ capture: true,
645
+ passive: true,
646
+ });
647
+ contentInspectorChannel.toLogger(domLayout.get());
694
648
  vAPI.domFilterer.toggle(false, highlightElements);
695
649
  };
696
650
  if ( document.readyState === 'loading' ) {
697
- document.addEventListener('DOMContentLoaded', onReady);
651
+ document.addEventListener('DOMContentLoaded', onReady, { once: true });
698
652
  } else {
699
653
  onReady();
700
654
  }
@@ -702,38 +656,61 @@ const start = function() {
702
656
 
703
657
  /******************************************************************************/
704
658
 
705
- const shutdown = function() {
659
+ const shutdownInspector = ( ) => {
706
660
  cosmeticFilterMapper.shutdown();
707
661
  domLayout.shutdown();
708
- vAPI.MessagingConnection.disconnectFrom(loggerConnectionId);
709
- window.removeEventListener('scroll', onScrolled, true);
710
- pickerRoot.remove();
711
- pickerRoot = svgRoot = null;
662
+ window.removeEventListener('scroll', onScrolled, {
663
+ capture: true,
664
+ passive: true,
665
+ });
666
+ window.removeEventListener('mouseover', onMouseOver, {
667
+ capture: true,
668
+ passive: true,
669
+ });
670
+ contentInspectorChannel.shutdown();
671
+ if ( inspectorFrame ) {
672
+ inspectorFrame.remove();
673
+ inspectorFrame = null;
674
+ }
675
+ vAPI.userStylesheet.remove(inspectorCSS);
676
+ vAPI.userStylesheet.apply();
677
+ vAPI.inspectorFrame = false;
712
678
  };
713
679
 
714
680
  /******************************************************************************/
715
681
  /******************************************************************************/
716
682
 
717
- const onMessage = function(request) {
718
- var response,
719
- nodes;
720
-
683
+ const onMessage = request => {
721
684
  switch ( request.what ) {
685
+ case 'startInspector':
686
+ startInspector();
687
+ break;
688
+
689
+ case 'quitInspector':
690
+ shutdownInspector();
691
+ break;
692
+
722
693
  case 'commitFilters':
723
694
  highlightElements();
724
695
  break;
725
696
 
726
697
  case 'domLayout':
727
- response = domLayout.get();
698
+ domLayout.get();
728
699
  highlightElements();
729
700
  break;
730
701
 
731
702
  case 'highlightMode':
732
- //svgRoot.classList.toggle('invert', request.invert);
733
703
  break;
734
704
 
735
705
  case 'highlightOne':
736
706
  blueNodes = selectNodes(request.selector, request.nid);
707
+ if ( blueNodes.length !== 0 ) {
708
+ blueNodes[0].scrollIntoView({
709
+ behavior: 'smooth',
710
+ block: 'nearest',
711
+ inline: 'nearest',
712
+ });
713
+ }
737
714
  highlightElements();
738
715
  break;
739
716
 
@@ -753,133 +730,174 @@ const onMessage = function(request) {
753
730
  highlightElements();
754
731
  break;
755
732
 
756
- case 'toggleFilter':
757
- nodes = selectNodes(request.selector, request.nid);
758
- if ( nodes.length !== 0 ) { nodes[0].scrollIntoView(); }
733
+ case 'toggleFilter': {
734
+ const nodes = selectNodes(request.selector, request.nid);
735
+ if ( nodes.length !== 0 ) {
736
+ nodes[0].scrollIntoView({
737
+ behavior: 'smooth',
738
+ block: 'nearest',
739
+ inline: 'nearest',
740
+ });
741
+ }
759
742
  toggleExceptions(nodesFromFilter(request.filter), request.target);
760
743
  highlightElements();
761
744
  break;
762
-
763
- case 'toggleNodes':
764
- nodes = selectNodes(request.selector, request.nid);
765
- if ( nodes.length !== 0 ) { nodes[0].scrollIntoView(); }
745
+ }
746
+ case 'toggleNodes': {
747
+ const nodes = selectNodes(request.selector, request.nid);
748
+ if ( nodes.length !== 0 ) {
749
+ nodes[0].scrollIntoView({
750
+ behavior: 'smooth',
751
+ block: 'nearest',
752
+ inline: 'nearest',
753
+ });
754
+ }
766
755
  toggleFilter(nodes, request.target);
767
756
  highlightElements();
768
757
  break;
769
-
758
+ }
770
759
  default:
771
760
  break;
772
761
  }
773
-
774
- return response;
775
762
  };
776
763
 
777
- /******************************************************************************/
764
+ /*******************************************************************************
765
+ *
766
+ * Establish two-way communication with logger/inspector window and
767
+ * inspector frame
768
+ *
769
+ * */
770
+
771
+ const contentInspectorChannel = (( ) => {
772
+ let toLoggerPort;
773
+ let toFramePort;
774
+
775
+ const toLogger = msg => {
776
+ if ( toLoggerPort === undefined ) { return; }
777
+ try {
778
+ toLoggerPort.postMessage(msg);
779
+ } catch(_) {
780
+ shutdownInspector();
781
+ }
782
+ };
778
783
 
779
- // Install DOM inspector widget
784
+ const onLoggerMessage = msg => {
785
+ onMessage(msg);
786
+ };
780
787
 
781
- const bootstrap = function(ev) {
782
- if ( ev ) {
783
- pickerRoot.removeEventListener(ev.type, bootstrap);
784
- }
785
- const pickerDoc = ev.target.contentDocument;
788
+ const onLoggerDisconnect = ( ) => {
789
+ shutdownInspector();
790
+ };
786
791
 
787
- pickerDoc.documentElement.style.setProperty(
788
- 'color-scheme',
789
- 'dark light',
790
- 'important'
791
- );
792
+ const onLoggerConnect = port => {
793
+ browser.runtime.onConnect.removeListener(onLoggerConnect);
794
+ toLoggerPort = port;
795
+ port.onMessage.addListener(onLoggerMessage);
796
+ port.onDisconnect.addListener(onLoggerDisconnect);
797
+ };
792
798
 
793
- const style = pickerDoc.createElement('style');
794
- style.textContent = [
795
- 'body {',
796
- 'background-color: transparent;',
797
- '}',
798
- 'svg {',
799
- 'height: 100%;',
800
- 'left: 0;',
801
- 'position: fixed;',
802
- 'top: 0;',
803
- 'width: 100%;',
804
- '}',
805
- 'svg > path:nth-of-type(1) {',
806
- 'fill: rgba(255,0,0,0.2);',
807
- 'stroke: #F00;',
808
- '}',
809
- 'svg > path:nth-of-type(2) {',
810
- 'fill: rgba(0,255,0,0.2);',
811
- 'stroke: #0F0;',
812
- '}',
813
- 'svg > path:nth-of-type(3) {',
814
- 'fill: rgba(255,0,0,0.2);',
815
- 'stroke: #F00;',
816
- '}',
817
- 'svg > path:nth-of-type(4) {',
818
- 'fill: rgba(0,0,255,0.1);',
819
- 'stroke: #FFF;',
820
- 'stroke-width: 0.5px;',
821
- '}',
822
- ''
823
- ].join('\n');
824
- pickerDoc.body.appendChild(style);
825
-
826
- svgRoot = pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'svg');
827
- svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
828
- svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
829
- svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
830
- svgRoot.appendChild(pickerDoc.createElementNS('http://www.w3.org/2000/svg', 'path'));
831
- pickerDoc.body.appendChild(svgRoot);
832
-
833
- window.addEventListener('scroll', onScrolled, true);
834
-
835
- // Dynamically add direct connection abilities so that we can establish
836
- // a direct, fast messaging connection to the logger.
837
- vAPI.messaging.extend().then(extended => {
838
- if ( extended !== true ) { return; }
839
- vAPI.MessagingConnection.connectTo('domInspector', 'loggerUI', msg => {
840
- switch ( msg.what ) {
841
- case 'connectionAccepted':
842
- loggerConnectionId = msg.id;
843
- start();
844
- break;
845
- case 'connectionBroken':
846
- shutdown();
847
- break;
848
- case 'connectionMessage':
849
- onMessage(msg.payload);
850
- break;
851
- }
799
+ const toFrame = msg => {
800
+ if ( toFramePort === undefined ) { return; }
801
+ toFramePort.postMessage(msg);
802
+ };
803
+
804
+ const shutdown = ( ) => {
805
+ if ( toFramePort !== undefined ) {
806
+ toFrame({ what: 'quitInspector' });
807
+ toFramePort.onmessage = null;
808
+ toFramePort.close();
809
+ toFramePort = undefined;
810
+ }
811
+ if ( toLoggerPort !== undefined ) {
812
+ toLoggerPort.onMessage.removeListener(onLoggerMessage);
813
+ toLoggerPort.onDisconnect.removeListener(onLoggerDisconnect);
814
+ toLoggerPort.disconnect();
815
+ toLoggerPort = undefined;
816
+ }
817
+ browser.runtime.onConnect.removeListener(onLoggerConnect);
818
+ };
819
+
820
+ const start = async ( ) => {
821
+ browser.runtime.onConnect.addListener(onLoggerConnect);
822
+ const inspectorArgs = await vAPI.messaging.send('domInspectorContent', {
823
+ what: 'getInspectorArgs',
852
824
  });
853
- });
854
- };
825
+ if ( typeof inspectorArgs !== 'object' ) { return; }
826
+ if ( inspectorArgs === null ) { return; }
827
+ return new Promise(resolve => {
828
+ const iframe = document.createElement('iframe');
829
+ iframe.setAttribute(inspectorUniqueId, '');
830
+ document.documentElement.append(iframe);
831
+ iframe.addEventListener('load', ( ) => {
832
+ iframe.setAttribute(`${inspectorUniqueId}-loaded`, '');
833
+ const channel = new MessageChannel();
834
+ toFramePort = channel.port1;
835
+ toFramePort.onmessage = ev => {
836
+ const msg = ev.data || {};
837
+ if ( msg.what !== 'startInspector' ) { return; }
838
+ };
839
+ iframe.contentWindow.postMessage(
840
+ { what: 'startInspector' },
841
+ inspectorArgs.inspectorURL,
842
+ [ channel.port2 ]
843
+ );
844
+ resolve(iframe);
845
+ }, { once: true });
846
+ iframe.contentWindow.location = inspectorArgs.inspectorURL;
847
+ });
848
+ };
849
+
850
+ return { start, toLogger, toFrame, shutdown };
851
+ })();
855
852
 
856
- pickerRoot = document.createElement('iframe');
857
- pickerRoot.classList.add(sessionId);
858
- pickerRoot.classList.add('dom-inspector');
859
- pickerRoot.style.cssText = [
853
+
854
+ // Install DOM inspector widget
855
+ const inspectorCSSStyle = [
860
856
  'background: transparent',
861
857
  'border: 0',
862
858
  'border-radius: 0',
863
859
  'box-shadow: none',
864
860
  'color-scheme: light dark',
865
861
  'display: block',
862
+ 'filter: none',
866
863
  'height: 100%',
867
864
  'left: 0',
868
865
  'margin: 0',
866
+ 'max-height: none',
867
+ 'max-width: none',
868
+ 'min-height: unset',
869
+ 'min-width: unset',
869
870
  'opacity: 1',
870
871
  'outline: 0',
871
872
  'padding: 0',
872
- 'pointer-events:none;',
873
+ 'pointer-events: none',
873
874
  'position: fixed',
874
875
  'top: 0',
875
- 'visibility: visible',
876
+ 'transform: none',
877
+ 'visibility: hidden',
876
878
  'width: 100%',
877
879
  'z-index: 2147483647',
878
880
  ''
879
881
  ].join(' !important;\n');
880
882
 
881
- pickerRoot.addEventListener('load', ev => { bootstrap(ev); });
882
- (document.documentElement || document).appendChild(pickerRoot);
883
+ const inspectorCSS = `
884
+ :root > [${inspectorUniqueId}] {
885
+ ${inspectorCSSStyle}
886
+ }
887
+ :root > [${inspectorUniqueId}-loaded] {
888
+ visibility: visible !important;
889
+ }
890
+ `;
891
+
892
+ vAPI.userStylesheet.add(inspectorCSS);
893
+ vAPI.userStylesheet.apply();
894
+
895
+ let inspectorFrame = await contentInspectorChannel.start();
896
+ if ( inspectorFrame instanceof HTMLIFrameElement === false ) {
897
+ return shutdownInspector();
898
+ }
899
+
900
+ startInspector();
883
901
 
884
902
  /******************************************************************************/
885
903