panel-bridge.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. (function attachBackgroundPanelBridge(root, factory) {
  2. root.MultiPageBackgroundPanelBridge = factory();
  3. })(typeof self !== 'undefined' ? self : globalThis, function createBackgroundPanelBridgeModule() {
  4. function createPanelBridge(deps = {}) {
  5. const {
  6. chrome,
  7. addLog,
  8. closeConflictingTabsForSource,
  9. ensureContentScriptReadyOnTab,
  10. getPanelMode,
  11. normalizeSub2ApiUrl,
  12. rememberSourceLastUrl,
  13. sendToContentScript,
  14. sendToContentScriptResilient,
  15. waitForTabUrlFamily,
  16. DEFAULT_SUB2API_GROUP_NAME,
  17. SUB2API_STEP1_RESPONSE_TIMEOUT_MS,
  18. } = deps;
  19. async function requestOAuthUrlFromPanel(state, options = {}) {
  20. if (getPanelMode(state) === 'sub2api') {
  21. return requestSub2ApiOAuthUrl(state, options);
  22. }
  23. return requestCpaOAuthUrl(state, options);
  24. }
  25. async function requestCpaOAuthUrl(state, options = {}) {
  26. const { logLabel = 'OAuth 刷新' } = options;
  27. if (!state.vpsUrl) {
  28. throw new Error('尚未配置 CPA 地址,请先在侧边栏填写。');
  29. }
  30. await addLog(`${logLabel}:正在打开 CPA 面板...`);
  31. const injectFiles = ['content/activation-utils.js', 'content/utils.js', 'content/vps-panel.js'];
  32. await closeConflictingTabsForSource('vps-panel', state.vpsUrl);
  33. const tab = await chrome.tabs.create({ url: state.vpsUrl, active: true });
  34. const tabId = tab.id;
  35. await rememberSourceLastUrl('vps-panel', state.vpsUrl);
  36. await addLog(`${logLabel}:CPA 面板已打开,正在等待页面进入目标地址...`);
  37. const matchedTab = await waitForTabUrlFamily('vps-panel', tabId, state.vpsUrl, {
  38. timeoutMs: 15000,
  39. retryDelayMs: 400,
  40. });
  41. if (!matchedTab) {
  42. await addLog(`${logLabel}:CPA 页面尚未完全进入目标地址,继续尝试连接内容脚本...`, 'warn');
  43. }
  44. await ensureContentScriptReadyOnTab('vps-panel', tabId, {
  45. inject: injectFiles,
  46. timeoutMs: 45000,
  47. retryDelayMs: 900,
  48. logMessage: `${logLabel}:CPA 面板仍在加载,正在重试连接内容脚本...`,
  49. });
  50. const result = await sendToContentScriptResilient('vps-panel', {
  51. type: 'REQUEST_OAUTH_URL',
  52. source: 'background',
  53. payload: {
  54. vpsPassword: state.vpsPassword,
  55. logStep: 6,
  56. },
  57. }, {
  58. timeoutMs: 30000,
  59. retryDelayMs: 700,
  60. logMessage: `${logLabel}:CPA 面板通信未就绪,正在等待页面恢复...`,
  61. });
  62. if (result?.error) {
  63. throw new Error(result.error);
  64. }
  65. return result || {};
  66. }
  67. async function requestSub2ApiOAuthUrl(state, options = {}) {
  68. const { logLabel = 'OAuth 刷新' } = options;
  69. const sub2apiUrl = normalizeSub2ApiUrl(state.sub2apiUrl);
  70. const groupName = (state.sub2apiGroupName || DEFAULT_SUB2API_GROUP_NAME).trim() || DEFAULT_SUB2API_GROUP_NAME;
  71. if (!state.sub2apiEmail) {
  72. throw new Error('尚未配置 SUB2API 登录邮箱,请先在侧边栏填写。');
  73. }
  74. if (!state.sub2apiPassword) {
  75. throw new Error('尚未配置 SUB2API 登录密码,请先在侧边栏填写。');
  76. }
  77. await addLog(`${logLabel}:正在打开 SUB2API 后台...`);
  78. const injectFiles = ['content/utils.js', 'content/sub2api-panel.js'];
  79. await closeConflictingTabsForSource('sub2api-panel', sub2apiUrl);
  80. const tab = await chrome.tabs.create({ url: sub2apiUrl, active: true });
  81. const tabId = tab.id;
  82. await rememberSourceLastUrl('sub2api-panel', sub2apiUrl);
  83. await addLog(`${logLabel}:SUB2API 页面已打开,正在等待页面进入目标地址...`);
  84. const matchedTab = await waitForTabUrlFamily('sub2api-panel', tabId, sub2apiUrl, {
  85. timeoutMs: 15000,
  86. retryDelayMs: 400,
  87. });
  88. if (!matchedTab) {
  89. await addLog(`${logLabel}:SUB2API 页面尚未稳定,继续尝试连接内容脚本...`, 'warn');
  90. }
  91. await ensureContentScriptReadyOnTab('sub2api-panel', tabId, {
  92. inject: injectFiles,
  93. injectSource: 'sub2api-panel',
  94. timeoutMs: 45000,
  95. retryDelayMs: 900,
  96. logMessage: `${logLabel}:SUB2API 页面仍在加载,正在重试连接内容脚本...`,
  97. });
  98. const result = await sendToContentScript('sub2api-panel', {
  99. type: 'REQUEST_OAUTH_URL',
  100. source: 'background',
  101. payload: {
  102. sub2apiUrl,
  103. sub2apiEmail: state.sub2apiEmail,
  104. sub2apiPassword: state.sub2apiPassword,
  105. sub2apiGroupName: groupName,
  106. logStep: 6,
  107. },
  108. }, {
  109. responseTimeoutMs: SUB2API_STEP1_RESPONSE_TIMEOUT_MS,
  110. });
  111. if (result?.error) {
  112. throw new Error(result.error);
  113. }
  114. return result || {};
  115. }
  116. return {
  117. requestOAuthUrlFromPanel,
  118. requestCpaOAuthUrl,
  119. requestSub2ApiOAuthUrl,
  120. };
  121. }
  122. return {
  123. createPanelBridge,
  124. };
  125. });