console.log('[MultiPage:kiro-desktop-authorize-page] Content script loaded on', location.href); const KIRO_DESKTOP_AUTHORIZE_LISTENER_SENTINEL = 'data-multipage-kiro-desktop-authorize-page-listener'; const KIRO_DESKTOP_ALLOW_TEXT_PATTERN = /allow access|authorize|continue|allow|允许访问|授权|继续/i; const KIRO_DESKTOP_LOADING_TEXT_PATTERN = /loading|redirecting|please wait|加载中|跳转中|请稍候/i; const KIRO_DESKTOP_CLOUDFRONT_403_TEXT_PATTERN = /403 error|the request could not be satisfied|generated by cloudfront/i; const KIRO_DESKTOP_AWS_REQUEST_ERROR_TEXT_PATTERN = /sorry,\s*there was an error processing your request\.?\s*please try again\.?|抱歉,处理您的请求时出错。请重试。?/i; const KIRO_DESKTOP_EMAIL_INPUT_SELECTOR = [ 'input[placeholder="username@example.com"]', 'input[type="email"]', 'input[name="email"]', 'input[autocomplete="username"]', ].join(', '); const KIRO_DESKTOP_PASSWORD_INPUT_SELECTOR = [ 'input[type="password"]', 'input[name="password"]', 'input[id*="password" i]', 'input[autocomplete="current-password"]', ].join(', '); const KIRO_DESKTOP_OTP_INPUT_SELECTOR = [ 'input[autocomplete="one-time-code"]', 'input[inputmode="numeric"]', 'input[placeholder*="6-digit" i]', 'input[placeholder*="6 位" i]', 'input[name*="otp" i]', 'input[name*="code" i]', ].join(', '); function isVisibleDesktopElement(element) { if (!element) return false; const style = window.getComputedStyle(element); const rect = element.getBoundingClientRect(); return style.display !== 'none' && style.visibility !== 'hidden' && rect.width > 0 && rect.height > 0; } function collectVisibleDesktopElements(selector) { return Array.from(document.querySelectorAll(selector)) .filter((element) => isVisibleDesktopElement(element)); } function findFirstVisibleDesktopElement(selector) { return collectVisibleDesktopElements(selector)[0] || null; } function getDesktopPageText() { return String(document.body?.textContent || '') .replace(/\s+/g, ' ') .trim(); } function getDesktopActionText(element) { return [ element?.textContent, element?.value, element?.getAttribute?.('aria-label'), element?.getAttribute?.('title'), element?.getAttribute?.('data-testid'), ] .filter(Boolean) .join(' ') .replace(/\s+/g, ' ') .trim(); } function findDesktopActionButton(options = {}) { const { preferredSelectors = [], textPattern = null, formOwner = null, } = options; for (const selector of preferredSelectors) { const preferred = findFirstVisibleDesktopElement(selector); if (preferred && !preferred.disabled && preferred.getAttribute('aria-disabled') !== 'true') { return preferred; } } const candidates = collectVisibleDesktopElements('button, [role="button"], input[type="submit"], input[type="button"]') .filter((element) => !element.disabled && element.getAttribute('aria-disabled') !== 'true'); const prioritized = formOwner ? candidates.filter((element) => (element.form || element.closest?.('form') || null) === formOwner) : []; const pool = prioritized.length ? prioritized : candidates; if (textPattern instanceof RegExp) { return pool.find((element) => textPattern.test(getDesktopActionText(element))) || null; } return pool[0] || null; } function isKiroDesktopAuthHost(hostname = '') { const normalized = String(hostname || '').trim().toLowerCase(); return normalized === 'view.awsapps.com' || normalized === 'login.awsapps.com' || normalized === 'profile.aws.amazon.com' || normalized === 'profile.aws' || normalized.endsWith('.profile.aws.amazon.com') || normalized.endsWith('.profile.aws') || normalized === 'signin.aws.amazon.com' || normalized === 'signin.aws' || normalized.endsWith('.signin.aws.amazon.com') || normalized.endsWith('.signin.aws'); } function detectDesktopFatalState(pageText = '', currentUrl = '', pageTitle = '') { const combinedText = `${pageTitle} ${pageText}`.replace(/\s+/g, ' ').trim(); const isKiroAuthHost = isKiroDesktopAuthHost(location.hostname || ''); if (isKiroAuthHost && KIRO_DESKTOP_AWS_REQUEST_ERROR_TEXT_PATTERN.test(combinedText)) { return { state: 'proxy_error_page', url: currentUrl, fatalMessage: 'Kiro 桌面授权页出现 AWS 请求异常,通常是当前代理 IP 或出口区域异常,请先切换代理后再重试。', }; } if (KIRO_DESKTOP_CLOUDFRONT_403_TEXT_PATTERN.test(combinedText)) { return { state: 'cloudfront_403_page', url: currentUrl, fatalMessage: 'Kiro 桌面授权页返回 403(CloudFront 拒绝请求),通常是当前代理 IP 或区域触发了 AWS 风控,请更换代理后重试。', }; } return null; } function detectKiroDesktopAuthorizeState() { const currentUrl = location.href; const pageText = getDesktopPageText(); const fatalState = detectDesktopFatalState(pageText, currentUrl, document.title || ''); if (fatalState) { return fatalState; } if (/^https?:\/\/(127\.0\.0\.1|localhost):/i.test(currentUrl)) { const parsed = new URL(currentUrl); if (parsed.searchParams.get('error')) { return { state: 'callback_error', url: currentUrl, error: parsed.searchParams.get('error_description') || parsed.searchParams.get('error') || 'unknown_error', }; } return { state: 'callback_page', url: currentUrl, code: parsed.searchParams.get('code') || '', stateValue: parsed.searchParams.get('state') || '', }; } const otpInput = findFirstVisibleDesktopElement(KIRO_DESKTOP_OTP_INPUT_SELECTOR); if (otpInput) { return { state: 'otp_page', url: currentUrl, otpInput, continueButton: findDesktopActionButton({ preferredSelectors: ['button[data-testid="email-verification-verify-button"]'], textPattern: KIRO_DESKTOP_ALLOW_TEXT_PATTERN, formOwner: otpInput.form || otpInput.closest?.('form') || null, }), }; } const emailInput = findFirstVisibleDesktopElement(KIRO_DESKTOP_EMAIL_INPUT_SELECTOR); if (emailInput) { return { state: 'relogin_email', url: currentUrl, emailInput, continueButton: findDesktopActionButton({ preferredSelectors: ['button[data-testid="test-primary-button"]'], textPattern: KIRO_DESKTOP_ALLOW_TEXT_PATTERN, formOwner: emailInput.form || emailInput.closest?.('form') || null, }), }; } const passwordInput = findFirstVisibleDesktopElement(KIRO_DESKTOP_PASSWORD_INPUT_SELECTOR); if (passwordInput) { return { state: 'relogin_password', url: currentUrl, passwordInput, continueButton: findDesktopActionButton({ preferredSelectors: ['button[data-testid="test-primary-button"]'], textPattern: KIRO_DESKTOP_ALLOW_TEXT_PATTERN, formOwner: passwordInput.form || passwordInput.closest?.('form') || null, }), }; } const consentButton = findDesktopActionButton({ preferredSelectors: [ 'button[data-testid="confirm-button"]', 'button[data-testid="allow-access-button"]', ], textPattern: KIRO_DESKTOP_ALLOW_TEXT_PATTERN, }); if (consentButton) { return { state: 'consent_page', url: currentUrl, actionButton: consentButton, actionText: getDesktopActionText(consentButton), }; } if (KIRO_DESKTOP_LOADING_TEXT_PATTERN.test(pageText)) { return { state: 'redirecting', url: currentUrl, }; } return { state: 'loading', url: currentUrl, }; } async function getCurrentDesktopAuthorizeState() { const detected = detectKiroDesktopAuthorizeState(); if (detected.state === 'cloudfront_403_page' || detected.state === 'proxy_error_page') { throw new Error(detected.fatalMessage || 'Kiro 桌面授权页出现代理异常。'); } if (detected.state === 'callback_error') { throw new Error(`Kiro 桌面授权回调失败:${detected.error || 'unknown_error'}`); } return detected; } async function submitDesktopEmail(payload = {}) { const email = String(payload?.email || '').trim(); if (!email) { throw new Error('缺少桌面授权邮箱,无法继续。'); } const currentState = await getCurrentDesktopAuthorizeState(); if (currentState.state !== 'relogin_email' || !currentState.emailInput || !currentState.continueButton) { throw new Error(`当前桌面授权页不是邮箱重登状态:${currentState.state}`); } fillInput(currentState.emailInput, email); await sleep(150); simulateClick(currentState.continueButton); return { submitted: true, state: 'email_submitted', url: location.href, }; } async function submitDesktopPassword(payload = {}) { const password = String(payload?.password || ''); if (!password) { throw new Error('缺少桌面授权密码,无法继续。'); } const currentState = await getCurrentDesktopAuthorizeState(); if (currentState.state !== 'relogin_password' || !currentState.passwordInput || !currentState.continueButton) { throw new Error(`当前桌面授权页不是密码重登状态:${currentState.state}`); } fillInput(currentState.passwordInput, password); await sleep(150); simulateClick(currentState.continueButton); return { submitted: true, state: 'password_submitted', url: location.href, }; } async function submitDesktopOtp(payload = {}) { const code = String(payload?.code || '').trim(); if (!code) { throw new Error('缺少桌面授权验证码,无法继续。'); } const currentState = await getCurrentDesktopAuthorizeState(); if (currentState.state !== 'otp_page' || !currentState.otpInput || !currentState.continueButton) { throw new Error(`当前桌面授权页不是验证码状态:${currentState.state}`); } fillInput(currentState.otpInput, code); await sleep(150); simulateClick(currentState.continueButton); return { submitted: true, state: 'otp_submitted', url: location.href, }; } async function confirmDesktopConsent() { const currentState = await getCurrentDesktopAuthorizeState(); if (currentState.state !== 'consent_page' || !currentState.actionButton) { throw new Error(`当前桌面授权页不是授权确认状态:${currentState.state}`); } simulateClick(currentState.actionButton); return { submitted: true, state: 'consent_submitted', url: location.href, actionText: currentState.actionText || '', }; } async function handleKiroDesktopAuthorizeCommand(message) { switch (message.type) { case 'GET_KIRO_DESKTOP_AUTHORIZE_STATE': return getCurrentDesktopAuthorizeState(); case 'EXECUTE_KIRO_DESKTOP_AUTHORIZE_ACTION': { const action = String(message.payload?.action || '').trim(); if (action === 'submit-email') { return submitDesktopEmail(message.payload || {}); } if (action === 'submit-password') { return submitDesktopPassword(message.payload || {}); } if (action === 'submit-otp') { return submitDesktopOtp(message.payload || {}); } if (action === 'confirm-consent') { return confirmDesktopConsent(); } throw new Error(`desktop-authorize-page.js 不处理动作:${action}`); } default: return null; } } if (document.documentElement.getAttribute(KIRO_DESKTOP_AUTHORIZE_LISTENER_SENTINEL) !== '1') { document.documentElement.setAttribute(KIRO_DESKTOP_AUTHORIZE_LISTENER_SENTINEL, '1'); chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { if ( message.type === 'GET_KIRO_DESKTOP_AUTHORIZE_STATE' || message.type === 'EXECUTE_KIRO_DESKTOP_AUTHORIZE_ACTION' ) { resetStopState(); handleKiroDesktopAuthorizeCommand(message) .then((result) => { sendResponse({ ok: true, ...(result || {}) }); }) .catch((error) => { if (isStopError(error)) { sendResponse({ stopped: true, error: error.message }); return; } sendResponse({ error: error?.message || String(error || '未知错误') }); }); return true; } return false; }); }