mirror of
https://github.com/browser-use/web-ui.git
synced 2026-03-22 03:07:54 +08:00
114 lines
4.7 KiB
Python
114 lines
4.7 KiB
Python
import json
|
|
import logging
|
|
import os
|
|
|
|
from browser_use.browser.browser import Browser, IN_DOCKER
|
|
from browser_use.browser.context import BrowserContext, BrowserContextConfig
|
|
from playwright.async_api import Browser as PlaywrightBrowser
|
|
from playwright.async_api import BrowserContext as PlaywrightBrowserContext
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class CustomBrowserContextConfig(BrowserContextConfig):
|
|
force_new_context: bool = False # force to create new context
|
|
|
|
|
|
class CustomBrowserContext(BrowserContext):
|
|
def __init__(
|
|
self,
|
|
browser: "Browser",
|
|
config: CustomBrowserContextConfig = CustomBrowserContextConfig(),
|
|
):
|
|
super(CustomBrowserContext, self).__init__(browser=browser, config=config)
|
|
|
|
async def _create_context(self, browser: PlaywrightBrowser):
|
|
"""Creates a new browser context with anti-detection measures and loads cookies if available."""
|
|
if not self.config.force_new_context and self.browser.config.cdp_url and len(browser.contexts) > 0:
|
|
context = browser.contexts[0]
|
|
elif not self.config.force_new_context and self.browser.config.browser_binary_path and len(
|
|
browser.contexts) > 0:
|
|
# Connect to existing Chrome instance instead of creating new one
|
|
context = browser.contexts[0]
|
|
else:
|
|
# Original code for creating new context
|
|
context = await browser.new_context(
|
|
no_viewport=True,
|
|
user_agent=self.config.user_agent,
|
|
java_script_enabled=True,
|
|
bypass_csp=self.config.disable_security,
|
|
ignore_https_errors=self.config.disable_security,
|
|
record_video_dir=self.config.save_recording_path,
|
|
record_video_size=self.config.browser_window_size.model_dump(),
|
|
record_har_path=self.config.save_har_path,
|
|
locale=self.config.locale,
|
|
http_credentials=self.config.http_credentials,
|
|
is_mobile=self.config.is_mobile,
|
|
has_touch=self.config.has_touch,
|
|
geolocation=self.config.geolocation,
|
|
permissions=self.config.permissions,
|
|
timezone_id=self.config.timezone_id,
|
|
)
|
|
|
|
if self.config.trace_path:
|
|
await context.tracing.start(screenshots=True, snapshots=True, sources=True)
|
|
|
|
# Load cookies if they exist
|
|
if self.config.cookies_file and os.path.exists(self.config.cookies_file):
|
|
with open(self.config.cookies_file, 'r') as f:
|
|
try:
|
|
cookies = json.load(f)
|
|
|
|
valid_same_site_values = ['Strict', 'Lax', 'None']
|
|
for cookie in cookies:
|
|
if 'sameSite' in cookie:
|
|
if cookie['sameSite'] not in valid_same_site_values:
|
|
logger.warning(
|
|
f"Fixed invalid sameSite value '{cookie['sameSite']}' to 'None' for cookie {cookie.get('name')}"
|
|
)
|
|
cookie['sameSite'] = 'None'
|
|
logger.info(f'🍪 Loaded {len(cookies)} cookies from {self.config.cookies_file}')
|
|
await context.add_cookies(cookies)
|
|
|
|
except json.JSONDecodeError as e:
|
|
logger.error(f'Failed to parse cookies file: {str(e)}')
|
|
|
|
# Expose anti-detection scripts
|
|
await context.add_init_script(
|
|
"""
|
|
// Webdriver property
|
|
Object.defineProperty(navigator, 'webdriver', {
|
|
get: () => undefined
|
|
});
|
|
|
|
// Languages
|
|
Object.defineProperty(navigator, 'languages', {
|
|
get: () => ['en-US']
|
|
});
|
|
|
|
// Plugins
|
|
Object.defineProperty(navigator, 'plugins', {
|
|
get: () => [1, 2, 3, 4, 5]
|
|
});
|
|
|
|
// Chrome runtime
|
|
window.chrome = { runtime: {} };
|
|
|
|
// Permissions
|
|
const originalQuery = window.navigator.permissions.query;
|
|
window.navigator.permissions.query = (parameters) => (
|
|
parameters.name === 'notifications' ?
|
|
Promise.resolve({ state: Notification.permission }) :
|
|
originalQuery(parameters)
|
|
);
|
|
(function () {
|
|
const originalAttachShadow = Element.prototype.attachShadow;
|
|
Element.prototype.attachShadow = function attachShadow(options) {
|
|
return originalAttachShadow.call(this, { ...options, mode: "open" });
|
|
};
|
|
})();
|
|
"""
|
|
)
|
|
|
|
return context
|