Я пытаюсь изменить пользовательский агент TChromium и не нашел для этого процедуры, если он использует CefVCL. Уже по ceflib похоже, что да, я видел переменную «настройки», которая получает значение «user_agent», но VCL уже есть, будет или это невозможно?
Изменение пользовательского агента в Chromium Embedded 3 (DCEF3) (CefVCL)
Ответы (7)
Для этого нет встроенного способа. По моему опыту, настройка пользовательского агента ничего не делает ... поэтому вам нужно напрямую редактировать ceflib.pas (строка ~ 8532), чтобы добиться этого эффекта.
settings.user_agent := cefstring(UserAgent);
становится:
settings.user_agent := cefstring('My USERAGENT v1.0');
С учетом вышеизложенного вы можете захотеть включить свою собственную ОС и информацию о браузере, поскольку это блокирует реализацию этих переменных в CEF. Или добавьте его, например:
settings.user_agent := cefstring(UserAgent+'; My UserAgent v1.0');
Вот как я это делаю... Я работаю с DCEF1 и DCEF3 около года... и все еще учусь!
Просмотр исходного кода проекта демонстрационного guiclient
begin
//CefCache := 'cache';
CefCache:='./ca1';
CefUserAgent:='"Mozilla/5.0(Linux; U; Android 4.0.4; zh-cn; MI-ONE C1 Build/IMM76D) UC AppleWebKit/534.31 (KHTML, like Gecko) Mobile Safari/534.31"';
CefOnRegisterCustomSchemes := RegisterSchemes;
CefSingleProcess := False;
if not CefLoadLibDefault then
Exit;
CefRegisterSchemeHandlerFactory('local', '', False, TFileScheme);
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
ceflib.pas строка 5549
Var
UA: integer;
UAescojido: Ustring;
...
settings.cache_path := CefString(Cache);
UA:= Random(2)+1; //NEW LINE
if UA=1 then UAescojido:= 'xxxxxxxxxx'; //NEW LINE
if UA=2 then UAescojido:= 'xxxxxxxxxx'; //NEW LINE
settings.user_agent := cefstring(UAescojido); //ASSIGN VARIABLE
Не полное изменение, но это работает для меня.
procedure TForm1.Chromium1BeforeResourceLoad(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const request: ICefRequest; const callback: ICefRequestCallback; out
Result: TCefReturnValue);
Var
map: ICefStringMultimap;
begin
map := TCefStringMultimapOwn.Create;
request.GetHeaderMap(map);
map.Append('User-Agent','Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16');
request.SetHeaderMap(map);
callback.Cont(true);
end;
Моя (C++) реализация разветвляет CEF и добавляет следующий метод в CefRequestHandler:
virtual bool GetOverrideUserAgent(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDictionaryValue> request_info,
CefString& overrideUserAgent) { return false; }
Затем в cef\libcef\common\request_impl.cc:
void CefRequestImpl::Set(net::URLRequest* request) {
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
...
const content::ResourceRequestInfo* info =
content::ResourceRequestInfo::ForRequest(request);
if (info) {
...
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForRequest(request);
if(browser) {
...
CefString overrideUserAgent;
if(request_handler->**GetOverrideUserAgent**(browser.get(),
request_info, overrideUserAgent)) {
headermap_.erase(
net::HttpRequestHeaders::kUserAgent);
headermap_.insert(
std::make_pair(net::HttpRequestHeaders::kUserAgent,
overrideUserAgent));
}
...
Таким образом, (основные) шаги таковы: 1. разветвить CEF 2. добавить CefRequestHandler::GetOverrideUserAgent 3. в вашем приложении клиентский обработчик должен быть производным от CefRequestHandler и реализовать GetOverrideUserAgent 4. ваше приложение может установить UA по мере необходимости.
Однако я сделал это именно так. Возможно, он не подходит для ваших нужд.
Мы используем DCEF1 в течение нескольких лет и не обновлялись до DCEF3 (поскольку в нем отсутствует то, что нам нужно). Так что этот ответ может быть устаревшим, но для чего он стоит:
В DCEF1 в модуле ciflib есть глобальная переменная с именем CefUserAgent. Мы устанавливаем эту переменную в строку пользовательского агента нашего клиента в разделе инициализации одного из наших модулей проекта. Это просто и, кажется, работает хорошо для нас.
CefUserAgent := OutCustomUserAgentString;
Я не помню происхождение этого метода сейчас (это было слишком давно), но я полагаю, что мы сделали бы это только в разделе инициализации модуля, если бы это требовалось для правильной работы.
К сожалению, я понятия не имею, работает ли это в DCEF3.
Установите переменную CefUserAgent в разделе инициализации вашего основного программного модуля.
initialization
CefUserAgent := "Your Agent";
Альтернатива:
Если вы используете версию CEF, в которой нет глобальной переменной CefUserAgent, вы можете попробовать:
Пользовательский агент хранится в
var
settings: TCefSettings;
в файле ceflib, который объявлен в локальной функции, а не в глобальной переменной. Запись настроек содержит переменную settings.user_agent, которую можно изменить.
function CefLoadLib
здесь объявляется переменная, а CefLoadLibDefault вызывает CefLoadLib.
Сделать settings глобальными в верхней части файла модуля вместо того, чтобы оставлять его как локальную переменную функции, может быть решением, позволяющим изменять пользовательский агент в разделе инициализации другого модуля перед компонентами. загружаются на форму. Однако, поскольку глобальные переменные во многих случаях являются плохой вещью и могут вызвать непредвиденные последствия... Нужно проверить, не будет ли такая модификация небезопасной.
Если это еще не было сделано, это должен быть запрос функции, чтобы CEF для delphi содержал настройку пользовательского агента, которую можно изменить в компоненте vcl. Кто-нибудь просил эту функцию ... пока ... Если нет, это определенно было бы полезно.
Другое временное решение — создать глобальную строковую переменную вместо того, чтобы вся запись настроек была глобальной, и просто использовать глобальную строковую переменную, когда установлен пользовательский агент:
settings.user_agent := cefstring(YourGlobalVariableHere);
Это опять же не постоянное решение, и эту функцию действительно следует реализовать в самом компоненте.