Изменение пользовательского агента в Chromium Embedded 3 (DCEF3) (CefVCL)

Я пытаюсь изменить пользовательский агент TChromium и не нашел для этого процедуры, если он использует CefVCL. Уже по ceflib похоже, что да, я видел переменную «настройки», которая получает значение «user_agent», но VCL уже есть, будет или это невозможно?


person D3F4ULT    schedule 10.09.2013    source источник


Ответы (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 около года... и все еще учусь!

person Endat Thaeman    schedule 12.11.2013
comment
К сожалению, это устаревшая ссылка. Теперь это строка 11091. - person Jerry Dodge; 31.07.2016
comment
Спасибо за обновление спустя 4 года после оригинального поста. К сожалению, эта информация сейчас неактуальна, поскольку DCEF больше не обновляется и не поддерживается. Переход на CEF4Delphi — разумный шаг, если вы не хотите устаревать. - person Endat Thaeman; 21.03.2018

Просмотр исходного кода проекта демонстрационного 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.
person Jinshaopu    schedule 07.01.2015

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
person Jhon    schedule 11.06.2014
comment
К сожалению, это устаревшая ссылка. Теперь это строка 11091. - person Jerry Dodge; 31.07.2016

Не полное изменение, но это работает для меня.

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;

person Aleksandr Andrusenko    schedule 21.11.2017

Моя (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 по мере необходимости.

Однако я сделал это именно так. Возможно, он не подходит для ваших нужд.

person Cristian Amarie    schedule 21.10.2016

Мы используем DCEF1 в течение нескольких лет и не обновлялись до DCEF3 (поскольку в нем отсутствует то, что нам нужно). Так что этот ответ может быть устаревшим, но для чего он стоит:

В DCEF1 в модуле ciflib есть глобальная переменная с именем CefUserAgent. Мы устанавливаем эту переменную в строку пользовательского агента нашего клиента в разделе инициализации одного из наших модулей проекта. Это просто и, кажется, работает хорошо для нас.

CefUserAgent := OutCustomUserAgentString;

Я не помню происхождение этого метода сейчас (это было слишком давно), но я полагаю, что мы сделали бы это только в разделе инициализации модуля, если бы это требовалось для правильной работы.

К сожалению, я понятия не имею, работает ли это в DCEF3.

person Neville Cook    schedule 30.10.2016

Установите переменную 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);

Это опять же не постоянное решение, и эту функцию действительно следует реализовать в самом компоненте.

person Community    schedule 18.10.2016