File size: 4,314 Bytes
bf3e07d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | # -*- coding: utf-8 -*-
# @Time : 2025/1/2
# @Author : nipurnagarwal
# @ProjectName: browser-use-100XPrompt
# @FileName: browser.py
import asyncio
import os
import platform
import subprocess
import requests
import logging
from playwright.async_api import Browser as PlaywrightBrowser
from playwright.async_api import (
BrowserContext as PlaywrightBrowserContext,
Playwright,
async_playwright,
)
from browser_use.browser.browser import Browser
from browser_use.browser.context import BrowserContext, BrowserContextConfig
from .config import BrowserPersistenceConfig
from .custom_context import CustomBrowserContext
logger = logging.getLogger(__name__)
class CustomBrowser(Browser):
async def new_context(
self,
config: BrowserContextConfig = BrowserContextConfig()
) -> CustomBrowserContext:
return CustomBrowserContext(config=config, browser=self)
async def _setup_browser(self, playwright: Playwright) -> PlaywrightBrowser:
"""Sets up and returns a Playwright Browser instance."""
try:
# Always check for Arc first on macOS
arc_path = "/Applications/Arc.app/Contents/MacOS/Arc"
using_arc = platform.system() == "Darwin" and os.path.exists(arc_path)
# If we're on macOS and Arc exists, use it instead of chrome_instance_path
if using_arc:
browser_path = arc_path
else:
browser_path = self.config.chrome_instance_path
if self.config.wss_url:
browser = await playwright.chromium.connect(self.config.wss_url)
return browser
# Try to connect to existing browser instance
try:
response = requests.get('http://localhost:9222/json/version', timeout=2)
if response.status_code == 200:
logger.info('Reusing existing browser instance')
browser = await playwright.chromium.connect_over_cdp(
endpoint_url='http://localhost:9222',
timeout=20000,
)
return browser
except requests.ConnectionError:
logger.debug('No existing browser instance found, starting new one')
if browser_path:
# Kill any existing browser processes that might interfere
if platform.system() == "Darwin":
os.system("pkill 'Arc'")
await asyncio.sleep(1) # Give it time to close
# Launch the browser with debugging port
subprocess.Popen(
[
browser_path,
'--remote-debugging-port=9222',
'--no-first-run',
'--no-default-browser-check',
'--disable-features=Translate',
'--enable-automation',
'--disable-blink-features=AutomationControlled',
] + self.config.extra_chromium_args,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
# Wait for browser to be ready
for _ in range(10):
try:
response = requests.get('http://localhost:9222/json/version', timeout=2)
if response.status_code == 200:
break
except requests.ConnectionError:
pass
await asyncio.sleep(1)
try:
browser = await playwright.chromium.connect_over_cdp(
endpoint_url='http://localhost:9222',
timeout=20000,
)
if using_arc:
logger.info('Successfully connected to Arc browser')
return browser
except Exception as e:
logger.error(f'Failed to connect to browser: {str(e)}')
raise RuntimeError(
'Failed to connect to browser. Please ensure all instances are closed and try again.'
)
# Fallback to launching regular chromium if no specific browser path
disable_security_args = []
if self.config.disable_security:
disable_security_args = [
'--disable-web-security',
'--disable-site-isolation-trials',
'--disable-features=IsolateOrigins,site-per-process',
]
browser = await playwright.chromium.launch(
headless=self.config.headless,
executable_path=None, # Let Playwright use its bundled Chromium
args=[
'--no-sandbox',
'--disable-blink-features=AutomationControlled',
'--disable-infobars',
'--disable-background-timer-throttling',
'--disable-popup-blocking',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
'--enable-automation',
] + disable_security_args + self.config.extra_chromium_args,
proxy=self.config.proxy,
)
return browser
except Exception as e:
logger.error(f'Failed to initialize browser: {str(e)}')
raise
|