tab-manager.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /* global bgReady */// common.js
  2. /* global navMan */
  3. 'use strict';
  4. const tabMan = (() => {
  5. const listeners = new Set();
  6. const cache = new Map();
  7. chrome.tabs.onRemoved.addListener(tabId => cache.delete(tabId));
  8. chrome.tabs.onReplaced.addListener((added, removed) => cache.delete(removed));
  9. bgReady.all.then(() => {
  10. navMan.onUrlChange(({tabId, frameId, url}) => {
  11. const oldUrl = !frameId && tabMan.get(tabId, 'url', frameId);
  12. tabMan.set(tabId, 'url', frameId, url);
  13. if (frameId) return;
  14. for (const fn of listeners) {
  15. try {
  16. fn({tabId, url, oldUrl});
  17. } catch (err) {
  18. console.error(err);
  19. }
  20. }
  21. });
  22. });
  23. return {
  24. onUpdate(fn) {
  25. listeners.add(fn);
  26. },
  27. get(tabId, ...keys) {
  28. return keys.reduce((meta, key) => meta && meta[key], cache.get(tabId));
  29. },
  30. /**
  31. * number of keys is arbitrary, last arg is value, `undefined` will delete the last key from meta
  32. * (tabId, 'foo', 123) will set tabId's meta to {foo: 123},
  33. * (tabId, 'foo', 'bar', 'etc', 123) will set tabId's meta to {foo: {bar: {etc: 123}}}
  34. */
  35. set(tabId, ...args) {
  36. let meta = cache.get(tabId);
  37. if (!meta) {
  38. meta = {};
  39. cache.set(tabId, meta);
  40. }
  41. const value = args.pop();
  42. const lastKey = args.pop();
  43. for (const key of args) meta = meta[key] || (meta[key] = {});
  44. if (value === undefined) {
  45. delete meta[lastKey];
  46. } else {
  47. meta[lastKey] = value;
  48. }
  49. },
  50. /** @returns {IterableIterator<number>} */
  51. list() {
  52. return cache.keys();
  53. },
  54. };
  55. })();