chromium-helper
Version:
CLI tool for searching and exploring Chromium source code via Google's official APIs
142 lines ⢠6 kB
JavaScript
import { chromium } from 'playwright';
import fs from 'fs/promises';
import path from 'path';
import os from 'os';
import chalk from 'chalk';
export class AuthManager {
cookieFile;
constructor() {
// Store cookies in user's home directory
this.cookieFile = path.join(os.homedir(), '.gerrit-cookie');
}
async authenticate(options = {}) {
console.log(chalk.cyan('š Starting Gerrit authentication...'));
console.log(chalk.gray('This will open Chrome for you to sign in to Gerrit.'));
// Try to use the user's actual Chrome browser instead of Playwright's Chromium
const browser = await chromium.launch({
headless: false, // Always use headed mode for auth
channel: 'chrome', // Use real Chrome
args: [
'--disable-blink-features=AutomationControlled',
'--no-sandbox'
]
});
try {
const context = await browser.newContext({
// Use a more complete user agent
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
viewport: { width: 1280, height: 800 },
// Don't indicate automation
bypassCSP: true
});
const page = await context.newPage();
console.log(chalk.yellow('\nš Please sign in to your Google account in the browser window...'));
console.log(chalk.gray('Waiting for you to complete sign-in...'));
console.log(chalk.yellow('\nā ļø If you see a security warning about the browser:'));
console.log(chalk.gray('1. Use "ch auth manual" for manual cookie setup instead'));
console.log(chalk.gray('2. Or try signing in anyway - sometimes it works after a few attempts'));
// Navigate to Gerrit
await page.goto('https://chromium-review.googlesource.com');
// Wait for authentication - poll for cookies
let authCookie = null;
let attempts = 0;
const maxAttempts = 60; // 60 seconds timeout
while (attempts < maxAttempts) {
await page.waitForTimeout(1000); // Wait 1 second between checks
// Get all cookies
const cookies = await context.cookies();
// Look for key authentication cookies (only need one!)
authCookie = cookies.find(cookie => cookie.name === '__Secure-1PSID' ||
cookie.name === '__Secure-3PSID');
// If we have either key cookie, we're authenticated
if (authCookie) {
console.log(chalk.green('\nā Authentication detected!'));
break;
}
attempts++;
}
if (!authCookie) {
// Get all cookies for debugging
const allCookies = await context.cookies();
console.log(chalk.red('\nAvailable cookies:'));
allCookies.forEach(cookie => {
console.log(chalk.gray(` - ${cookie.name}`));
});
throw new Error('Authentication timeout. Could not find required cookie (__Secure-1PSID or __Secure-3PSID).');
}
// Just use the found auth cookie - we only need one!
const cookieString = `${authCookie.name}=${authCookie.value}`;
// Save to file
await this.saveCookies(cookieString);
console.log(chalk.green(`\nā
Authentication successful! Cookies saved to ${this.cookieFile}`));
console.log(chalk.gray('You can now use gerrit list commands without --auth-cookie parameter'));
return cookieString;
}
finally {
await browser.close();
}
}
async getCookies() {
try {
const cookies = await fs.readFile(this.cookieFile, 'utf-8');
return cookies.trim();
}
catch (error) {
return null;
}
}
async saveCookies(cookies) {
await fs.writeFile(this.cookieFile, cookies, { mode: 0o600 }); // Secure permissions
}
async clearCookies() {
try {
await fs.unlink(this.cookieFile);
console.log(chalk.yellow('šļø Cleared saved authentication'));
}
catch (error) {
// File doesn't exist, that's fine
}
}
async checkAuth() {
const cookies = await this.getCookies();
if (!cookies) {
return false;
}
// Test if cookies are still valid
try {
const response = await fetch('https://chromium-review.googlesource.com/changes/?O=1&S=0&n=1', {
headers: {
'Cookie': cookies,
'Accept': 'application/json',
}
});
return response.ok;
}
catch {
return false;
}
}
}
// Helper function to get cookies with fallback
export async function getAuthCookies(providedCookie) {
// If cookie is provided via parameter, use it
if (providedCookie) {
return providedCookie;
}
// Otherwise, try to load from saved file
const authManager = new AuthManager();
const savedCookies = await authManager.getCookies();
if (savedCookies) {
// Verify they're still valid
const isValid = await authManager.checkAuth();
if (isValid) {
return savedCookies;
}
console.log(chalk.yellow('ā ļø Saved authentication has expired'));
}
throw new Error('No authentication found. Please run:\n' +
chalk.cyan(' ch auth manual') + ' (recommended)\n' +
chalk.cyan(' ch auth login') + ' (may be blocked by Google)\n' +
'Or provide cookie with --auth-cookie parameter');
}
//# sourceMappingURL=auth.js.map