Changing the user agent in Chromium Embedded 3 (DCEF3) (CefVCL)

5.4k views Asked by At

I'm trying to modify the User Agent of TChromium and I found no procedure for this, in case it is using CefVCL. Already by ceflib looks like it has to yes, I saw a variable "settings" that receives a value "user_agent" but the VCL already has, will have or is not possible this way?

7

There are 7 answers

0
Jinshaopu On

View the demo guiclient's project source

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.
1
Jhon On

ceflib.pas line 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
0
AudioBubble On

Set the CefUserAgent variable in the initialization section of your main program unit.

initialization
  CefUserAgent := "Your Agent";

Alternative:

If you are using a version of CEF that does not have a CefUserAgent global varaible then you may try:

The user agent is stored in the

var
  settings: TCefSettings;

in the ceflib file which is declared in a local function, not a global variable. The settings record contains a variable settings.user_agent that can be modified.

function CefLoadLib

is where the variable is declared, and CefLoadLibDefault calls CefLoadLib.

Making settings a global at the top of the unit file instead of leaving it as a local function variable, could be a solution so that you could modify the user agent in the initialization section of another unit before the components are loaded on the form. However since globals are in many cases a bad thing and can cause unintended consequences.... One would have to check to see that it is not going to be unsafe to do such a modification.

If it hasn't been done so already, this should be a feature request that CEF for delphi contains a user agent setting modifiable in the vcl component. Has anyone requested this feature...yet.. If not it would definitely be useful.

Another temporary solution, is to make a global string variable instead of the entire settings record being global, and just use the global string variable when the user agent is set:

settings.user_agent := cefstring(YourGlobalVariableHere);

This again is not a permanent solution and this feature should really be implemented in the component itself.

0
Cristian Amarie On

My (C++) implementation forks CEF and add the following method to the CefRequestHandler:

  virtual bool GetOverrideUserAgent(CefRefPtr<CefBrowser> browser, 
                                    CefRefPtr<CefDictionaryValue> request_info, 
                                    CefString& overrideUserAgent) { return false; }

Then, in 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));
        }
        ...

So the (basic) steps are these: 1. fork CEF 2. add CefRequestHandler::GetOverrideUserAgent 3. in your application, client handler should be derived from CefRequestHandler and implement GetOverrideUserAgent 4. your application can set the UA as needed.

This is, however, how I did it. It might not be suitable for your needs.

0
Neville Cook On

We've been using DCEF1 for several years, and we've have not upgrade to DCEF3 (as it is missing something we need). So this answer may be out of date, but for what it's worth:

In DCEF1 There is a global variable in the ciflib unit called CefUserAgent. We set that varible to our customer User Agent string in the initialization section of one of our project units. This is simple, and seems to work well for us.

CefUserAgent := OutCustomUserAgentString;

I dont remember the derivation of this method now (it was too long ago), but I expect we would only have done it in the initialization section of a unit if that is what was required to make it work properly.

Unfortunately I have no idea if this still works in DCEF3.

2
Endat Thaeman On

There is no built in way to do this. In my experience, the user-agent setting does nothing.. so you have to edit ceflib.pas directly (line ~8532) to achieve this effect.

    settings.user_agent := cefstring(UserAgent);

becomes:

    settings.user_agent := cefstring('My USERAGENT v1.0');

With the above, you may want to include your own OS and Browser Info as this blocks off CEF's implementation of those variables. Or append it, like this:

    settings.user_agent := cefstring(UserAgent+'; My UserAgent v1.0');

This is how I do it.. I've been working with DCEF1 and DCEF3 for about a year.. and still learning!

0
Aleksandr Andrusenko On

Not full change, but it work for me.

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;