popup-tracker.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { getActiveTab, sendTabCmd } from '@/common';
  2. import cache from './cache';
  3. import { getData } from './db';
  4. import { badges, BROWSER_ACTION, getFailureReason } from './icon';
  5. import { postInitialize } from './init';
  6. import { addPublicCommands, commands } from './message';
  7. import { INJECT } from './preinject';
  8. /** @type {{[tabId: string]: chrome.runtime.Port}} */
  9. export const popupTabs = {};
  10. const getCacheKey = tabId => 'SetPopup' + tabId;
  11. addPublicCommands({
  12. async InitPopup() {
  13. const tab = await getActiveTab() || {};
  14. const { url = '', id: tabId } = tab;
  15. const data = await commands.GetTabDomain(url);
  16. const cachedSetPopup = cache.pop(getCacheKey(tabId));
  17. const badgeData = badges[tabId] || {};
  18. let failure = getFailureReason(url, badgeData);
  19. if (!failure[0] && !cachedSetPopup && !await isInjectable(tabId, badgeData)) {
  20. failure = getFailureReason('');
  21. }
  22. data.tab = tab;
  23. return [cachedSetPopup, data, failure];
  24. },
  25. async SetPopup(data, src) {
  26. const tabId = src.tab.id;
  27. const key = getCacheKey(tabId);
  28. if (popupTabs[tabId]) return;
  29. Object.assign(data, await getData({ [IDS]: Object.keys(data[IDS]) }));
  30. (cache.get(key) || cache.put(key, {}))[src[kFrameId]] = [data, src];
  31. }
  32. });
  33. postInitialize.push(() => {
  34. browser.runtime.onConnect.addListener(onPopupOpened);
  35. browser.webRequest.onBeforeRequest.addListener(prefetchSetPopup, {
  36. urls: [chrome.runtime.getURL(extensionManifest[BROWSER_ACTION].default_popup)],
  37. types: ['main_frame'],
  38. });
  39. });
  40. async function isInjectable(tabId, badgeData) {
  41. return badgeData[INJECT]
  42. && await sendTabCmd(tabId, VIOLENTMONKEY, null, { [kFrameId]: 0 })
  43. || (
  44. await browser.tabs.executeScript(tabId, { code: '1', [RUN_AT]: 'document_start' })
  45. .catch(() => [])
  46. )[0];
  47. }
  48. function onPopupOpened(port) {
  49. const tabId = +port.name;
  50. if (!tabId) return;
  51. popupTabs[tabId] = port;
  52. notifyTab(tabId, true);
  53. port.onDisconnect.addListener(onPopupClosed);
  54. }
  55. function onPopupClosed({ name }) {
  56. delete popupTabs[name];
  57. notifyTab(+name, false);
  58. }
  59. async function prefetchSetPopup() {
  60. notifyTab((await getActiveTab()).id, true);
  61. }
  62. function notifyTab(tabId, data) {
  63. if (badges[tabId]?.total) {
  64. sendTabCmd(tabId, 'PopupShown', data);
  65. }
  66. }