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?
Changing the user agent in Chromium Embedded 3 (DCEF3) (CefVCL)
5.4k views Asked by D3F4ULT AtThere are 7 answers
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
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.
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.
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.
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!
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;
View the demo guiclient's project source