Disclosure Statement: This site contains affiliate links, which means that I may receive a commission if you make a purchase using these links. As an eBay Partner, I earn from qualifying purchases.
If you find these projects useful please consider becoming a sponsor with Patreon, GitHub or Liberapay.

How To Close Or ByPass Content Security Policy(CSP)

Post Reply
crystalxp
Posts: 39
Joined: Tue Jul 04, 2017 8:23 am

How To Close Or ByPass Content Security Policy(CSP)

Post by crystalxp »

How To Close Or ByPass Content Security Policy(CSP)?

I have tried these step ..
1, in event :onResourceResponse onResourceLoadComplete try to Modify the response with new map...because csp response to browser by headers...but it seemed not work.
2,
GlobalCEFApp.DisableWebSecurity := True;
GlobalCEFApp.DisableSafeBrowsing := True;

not work.....

3、 in firefox,we can set the csp option to false in about:config tab ,but cef seem have no choose on it .

Any other solution? Thanks very much.
User avatar
salvadordf
Posts: 4374
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by salvadordf »

I've never done that but this web page seems to show a way to disable it removing headers :
https://stackoverflow.com/questions/379 ... f-cefsharp
crystalxp
Posts: 39
Joined: Tue Jul 04, 2017 8:23 am

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by crystalxp »

yes, disable it by removing headers is a good idea , which is also the first one I'v tried, using event onResourceResponse onResourceLoadComplete, I want to remove or replace response header with the function :
procedure SetResponseHeaders(response: ICefResponse;
toAddHeaders: TDictionary<String, String>);
var
map: ICefStringMultimap;
ds: TDictionary<String, String>.TPairEnumerator;
begin
map := TCefStringMultimapOwn.Create;
response.GetHeaderMap(map);
ds := toAddHeaders.GetEnumerator;
while ds.MoveNext do
map.Append(ds.Current.Key, ds.Current.value);
// map.Append('User-Agent', 'CEF4Delphi Browser');
// map.Append('Accept-Language', 'en;q=0.8');
response.SetHeaderMap(map);
end;

but nothing changed after this step. maybe there is someting wrong in my codes?, could you share me some example about this aspect?
User avatar
salvadordf
Posts: 4374
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by salvadordf »

I just checked the code comments in the CEF code and it's not possible to change the response headers in the TChromium.OnResourceResponse, TChromium.OnResourceLoadComplete and TChromium.OnGetResourceResponseFilter events. :(

However, this old comment from the CEF maintainer states that it's possible to get the a ICefResourceHandler in the TChromium.OnGetResourceHandler event :
http://magpcss.org/ceforum/viewtopic.ph ... 794#p17348

With a ICefResourceHandler you can execute the request/return the response contents yourself using CefURLRequest.

I've never done this but this web page shows how to do that :
https://stackoverflow.com/questions/304 ... r-response
430am
Posts: 4
Joined: Tue Apr 03, 2018 2:39 pm

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by 430am »

salvadordf wrote: Thu Apr 05, 2018 6:37 pm With a ICefResourceHandler you can execute the request/return the response contents yourself using CefURLRequest.

I've never done this but this web page shows how to do that :
https://stackoverflow.com/questions/304 ... r-response
Has anyone implemented something like this with CEF4Delphi? I'm trying to implement a response header filter with a similar custom resource handler and it's sort of working but cookies aren't being set or passed on with the requests.

What I'm testing at the moment is the CRBrowser demo and I'm using

Code: Select all

  TCefUrlRequestRef.New(Request, TCustomCefUrlrequestClient.Create(Self), nil);
in ProcessRequest to handle the request.

The request context is nil so the global context should be used but I'm not sure if there should be the global cookie manager somewhere. CanSet/GetCookie is set to True but should I use that to set the cookie manually to the manager?
User avatar
salvadordf
Posts: 4374
Joined: Thu Feb 02, 2017 12:24 pm
Location: Spain
Contact:

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by salvadordf »

I recently added a new demo called URLRequest which uses a new component called TCEFUrlRequestClientComponent.

It should be easier to handle URLRequests with that component and the code from that demo. Read the code comments in that demo.

You need to set some flags in the ICefRequest to use the cookies. Try the UR_FLAG_ALLOW_STORED_CREDENTIALS flag but there are a few more available in the uCEFConstants unit.

These are code comments for the flags :

Code: Select all

  ///
  // Default behavior.
  ///
  UR_FLAG_NONE = 0,

  ///
  // If set the cache will be skipped when handling the request. Setting this
  // value is equivalent to specifying the "Cache-Control: no-cache" request
  // header. Setting this value in combination with UR_FLAG_ONLY_FROM_CACHE will
  // cause the request to fail.
  ///
  UR_FLAG_SKIP_CACHE = 1 << 0,

  ///
  // If set the request will fail if it cannot be served from the cache (or some
  // equivalent local store). Setting this value is equivalent to specifying the
  // "Cache-Control: only-if-cached" request header. Setting this value in
  // combination with UR_FLAG_SKIP_CACHE will cause the request to fail.
  ///
  UR_FLAG_ONLY_FROM_CACHE = 1 << 1,

  ///
  // If set user name, password, and cookies may be sent with the request, and
  // cookies may be saved from the response.
  ///
  UR_FLAG_ALLOW_STORED_CREDENTIALS = 1 << 2,

  ///
  // If set upload progress events will be generated when a request has a body.
  ///
  UR_FLAG_REPORT_UPLOAD_PROGRESS = 1 << 3,

  ///
  // If set the CefURLRequestClient::OnDownloadData method will not be called.
  ///
  UR_FLAG_NO_DOWNLOAD_DATA = 1 << 4,

  ///
  // If set 5XX redirect errors will be propagated to the observer instead of
  // automatically re-tried. This currently only applies for requests
  // originated in the browser process.
  ///
  UR_FLAG_NO_RETRY_ON_5XX = 1 << 5,

  ///
  // If set 3XX responses will cause the fetch to halt immediately rather than
  // continue through the redirect.
  ///
  UR_FLAG_STOP_ON_REDIRECT = 1 << 6,
friedrb
Posts: 1
Joined: Wed Dec 19, 2018 6:55 pm

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by friedrb »

Whoa, thanks! I was just trying to figure out how to use ICefUrlRequest to get Cef4Delphi to download a file using a POST without the full browser GUI. ...and lo and behold I just saw your reply about your new TCEFUrlRequestClientComponent.

Thanks again, :D
Bill.
430am
Posts: 4
Joined: Tue Apr 03, 2018 2:39 pm

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by 430am »

I finally had some time to get back to this and thanks to the ClientComponent I got this more or less working now. Using the ClientComponent did make things a bit easier. I think I was missing the UR_FLAG_ALLOW_STORED_CREDENTIALS and I was using a blank scheme in TCustomResourceHandler.Create, using http/https (from the original request) does make a difference.

Here's an example of filtering Response headers with a custom resource handler, this is based on the CRBrowser demo and the stackoverflow discussion mentioned before.

Code: Select all

// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
//         https://www.briskbard.com/index.php?lang=en&pageid=cef
//
//        Copyright © 2018 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
 *                       Delphi Chromium Embedded 3
 *
 * Usage allowed under the restrictions of the Lesser GNU General Public License
 * or alternatively the restrictions of the Mozilla Public License 1.1
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * Unit owner : Henri Gourvest <hgourvest@gmail.com>
 * Web site   : http://www.progdigy.com
 * Repository : http://code.google.com/p/delphichromiumembedded/
 * Group      : http://groups.google.com/group/delphichromiumembedded
 *
 * Embarcadero Technologies, Inc is not permitted to use or redistribute
 * this source code without explicit permission.
 *
 *)

unit uCustomResourceHandler;

{$I cef.inc}

interface
uses
  {$IFDEF DELPHI16_UP}
  System.Classes, WinApi.Windows, System.SysUtils, dialogs,
  {$ELSE}
  Classes, Windows, SysUtils,
  {$ENDIF}
  uCEFInterfaces, uCEFTypes, uCEFResourceHandler, uCEFStringMultimap, uCEFUrlrequestClient,
  uCEFUrlRequest, uCEFUrlRequestClientComponent, uCEFRequest;


type

  TCustomResourceHandler = class(TCefResourceHandlerOwn)
    private
      FOffset: NativeUInt;
      FStream: TMemoryStream;
      FCallback: ICefCallback;
      FResponse: ICefResponse;
      FClient: TCEFUrlRequestClientComponent;
      FRequest: ICefRequest;
      procedure GetResponseHeaders(const response: ICefResponse; out responseLength: Int64; out redirectUrl: ustring); override;
      function ProcessRequest(const Request: ICefRequest; const Callback: ICefCallback): Boolean; override;
      procedure OnRequestComplete(Sender: TObject; const request: ICefUrlRequest);
      procedure OnCreateURLRequest(Sender: TObject);
      procedure  OnDownloadData(Sender: TObject; const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
      function ReadResponse(const DataOut: Pointer; BytesToRead: Integer; var BytesRead: Integer; const Callback: ICefCallback): Boolean; override;
      procedure Cancel;
    public
      constructor Create(const browser: ICefBrowser; const frame: ICefFrame; const schemeName: ustring; const request: ICefRequest); reintroduce;
      destructor  Destroy; override;
      procedure CompleteRequest(const Request: ICefUrlRequest); virtual;

  end;

implementation

uses uCEFConstants;

procedure TCustomResourceHandler.Cancel;
begin

end;

procedure TCustomResourceHandler.CompleteRequest(const Request: ICefUrlRequest);
begin
  FStream.Position := 0;
  FResponse := Request.GetResponse;

  if Assigned(FCallback) then
    FCallback.Cont;

end;

constructor TCustomResourceHandler.Create(const browser    : ICefBrowser;
                                          const frame      : ICefFrame;
                                          const schemeName : ustring;
                                          const request    : ICefRequest);
begin
  inherited Create(browser, frame, schemeName, request);
  FStream := TMemoryStream.Create;
  FClient := TCEFUrlRequestClientComponent.Create(nil);
  FClient.OnRequestComplete := Self.OnRequestComplete;
  FClient.OnCreateURLRequest := Self.OnCreateURLRequest;
  FClient.OnDownloadData := Self.OnDownloadData;
  
end;

destructor TCustomResourceHandler.Destroy;
begin
  FStream.Destroy;
  FClient.Destroy;
  inherited Destroy;
  
end;

procedure TCustomResourceHandler.GetResponseHeaders(const response       : ICefResponse;
                                                    out   responseLength : Int64;
                                                    out   redirectUrl    : ustring);
var
  HeaderMapTemp: ICefStringMultimap;
  FinalHeaderMap: ICefStringMultiMap;
  i: Integer;
begin
  ResponseLength := FStream.Size;

  Response.Status := FResponse.Status;
  Response.StatusText := FResponse.StatusText;
  Response.MimeType := FResponse.MimeType;
  Response.Error := FResponse.Error;

  HeaderMapTemp := TCefStringMultimapOwn.Create;
  FinalHeaderMap := TCefStringMultimapOwn.Create;

  FResponse.GetHeaderMap(HeaderMapTemp);

  if HeaderMapTemp.Size <> 0 then
  begin
    for i := 0 to HeaderMapTemp.Size do
    begin
      if (Lowercase(HeaderMapTemp.Key[i]) <> 'x-frame-options') then
        FinalHeaderMap.Append(HeaderMapTemp.Key[i], HeaderMapTemp.Value[i]);

    end;
  end;

  Response.SetHeaderMap(FinalHeaderMap);
  
end;


procedure TCustomResourceHandler.OnCreateURLRequest(Sender: TObject);
begin
  TCefUrlRequestRef.New(FRequest, FClient.Client, nil);
end;

procedure TCustomResourceHandler.OnDownloadData(Sender: TObject;
  const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
begin
  if (data <> nil) and (dataLength > 0) then
    FStream.WriteBuffer(data^, dataLength);

end;

procedure TCustomResourceHandler.OnRequestComplete(Sender: TObject;
  const request: ICefUrlRequest);
begin
  Self.CompleteRequest(request);
  
end;

function TCustomResourceHandler.ProcessRequest(const Request: ICefRequest;
  const Callback: ICefCallback): Boolean;
var
  HeaderMapTemp: ICefStringMultimap;
  i: Integer;
begin
  Result := True;
  FOffset := 0;
  FCallback := Callback;

  FRequest        := TCefRequestRef.New;
  HeaderMapTemp := TCefStringMultimapOwn.Create;

  Request.GetHeaderMap(HeaderMapTemp);
  FRequest.SetReferrer(Request.ReferrerUrl, Request.ReferrerPolicy);
  FRequest.Assign(Request.Url, Request.Method, Request.PostData, HeaderMapTemp);

  FRequest.Flags  := UR_FLAG_ALLOW_STORED_CREDENTIALS;

  FClient.AddURLRequest;
  
end;

function TCustomResourceHandler.ReadResponse(const DataOut: Pointer;
  BytesToRead: Integer; var BytesRead: Integer;
  const Callback: ICefCallback): Boolean;
begin
  if FOffset < FStream.Size then
  begin
    Result := True;
    BytesRead := BytesToRead;
    Move(Pointer(NativeUInt(FStream.Memory) + FOffset)^, DataOut^, BytesRead);
    Inc(FOffset, BytesRead);
  end
  else
    Result := False;
    
end;

end.
The header filtering in GetResponseHeaders isn't pretty but there doesn't seem to be a way to manipulate them directly. I couldn't figure out how to cancel the request either but not sure if this makes a difference.
Student
Posts: 73
Joined: Tue Aug 07, 2018 9:20 am

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by Student »

430am wrote: Fri Jan 18, 2019 11:50 am I finally had some time to get back to this and thanks to the ClientComponent I got this more or less working now. Using the ClientComponent did make things a bit easier. I think I was missing the UR_FLAG_ALLOW_STORED_CREDENTIALS and I was using a blank scheme in TCustomResourceHandler.Create, using http/https (from the original request) does make a difference.

Here's an example of filtering Response headers with a custom resource handler, this is based on the CRBrowser demo and the stackoverflow discussion mentioned before.

Code: Select all

// ************************************************************************
// ***************************** CEF4Delphi *******************************
// ************************************************************************
//
// CEF4Delphi is based on DCEF3 which uses CEF3 to embed a chromium-based
// browser in Delphi applications.
//
// The original license of DCEF3 still applies to CEF4Delphi.
//
// For more information about CEF4Delphi visit :
//         https://www.briskbard.com/index.php?lang=en&pageid=cef
//
//        Copyright © 2018 Salvador Diaz Fau. All rights reserved.
//
// ************************************************************************
// ************ vvvv Original license and comments below vvvv *************
// ************************************************************************
(*
 *                       Delphi Chromium Embedded 3
 *
 * Usage allowed under the restrictions of the Lesser GNU General Public License
 * or alternatively the restrictions of the Mozilla Public License 1.1
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * Unit owner : Henri Gourvest <hgourvest@gmail.com>
 * Web site   : http://www.progdigy.com
 * Repository : http://code.google.com/p/delphichromiumembedded/
 * Group      : http://groups.google.com/group/delphichromiumembedded
 *
 * Embarcadero Technologies, Inc is not permitted to use or redistribute
 * this source code without explicit permission.
 *
 *)

unit uCustomResourceHandler;

{$I cef.inc}

interface
uses
  {$IFDEF DELPHI16_UP}
  System.Classes, WinApi.Windows, System.SysUtils, dialogs,
  {$ELSE}
  Classes, Windows, SysUtils,
  {$ENDIF}
  uCEFInterfaces, uCEFTypes, uCEFResourceHandler, uCEFStringMultimap, uCEFUrlrequestClient,
  uCEFUrlRequest, uCEFUrlRequestClientComponent, uCEFRequest;


type

  TCustomResourceHandler = class(TCefResourceHandlerOwn)
    private
      FOffset: NativeUInt;
      FStream: TMemoryStream;
      FCallback: ICefCallback;
      FResponse: ICefResponse;
      FClient: TCEFUrlRequestClientComponent;
      FRequest: ICefRequest;
      procedure GetResponseHeaders(const response: ICefResponse; out responseLength: Int64; out redirectUrl: ustring); override;
      function ProcessRequest(const Request: ICefRequest; const Callback: ICefCallback): Boolean; override;
      procedure OnRequestComplete(Sender: TObject; const request: ICefUrlRequest);
      procedure OnCreateURLRequest(Sender: TObject);
      procedure  OnDownloadData(Sender: TObject; const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
      function ReadResponse(const DataOut: Pointer; BytesToRead: Integer; var BytesRead: Integer; const Callback: ICefCallback): Boolean; override;
      procedure Cancel;
    public
      constructor Create(const browser: ICefBrowser; const frame: ICefFrame; const schemeName: ustring; const request: ICefRequest); reintroduce;
      destructor  Destroy; override;
      procedure CompleteRequest(const Request: ICefUrlRequest); virtual;

  end;

implementation

uses uCEFConstants;

procedure TCustomResourceHandler.Cancel;
begin

end;

procedure TCustomResourceHandler.CompleteRequest(const Request: ICefUrlRequest);
begin
  FStream.Position := 0;
  FResponse := Request.GetResponse;

  if Assigned(FCallback) then
    FCallback.Cont;

end;

constructor TCustomResourceHandler.Create(const browser    : ICefBrowser;
                                          const frame      : ICefFrame;
                                          const schemeName : ustring;
                                          const request    : ICefRequest);
begin
  inherited Create(browser, frame, schemeName, request);
  FStream := TMemoryStream.Create;
  FClient := TCEFUrlRequestClientComponent.Create(nil);
  FClient.OnRequestComplete := Self.OnRequestComplete;
  FClient.OnCreateURLRequest := Self.OnCreateURLRequest;
  FClient.OnDownloadData := Self.OnDownloadData;
  
end;

destructor TCustomResourceHandler.Destroy;
begin
  FStream.Destroy;
  FClient.Destroy;
  inherited Destroy;
  
end;

procedure TCustomResourceHandler.GetResponseHeaders(const response       : ICefResponse;
                                                    out   responseLength : Int64;
                                                    out   redirectUrl    : ustring);
var
  HeaderMapTemp: ICefStringMultimap;
  FinalHeaderMap: ICefStringMultiMap;
  i: Integer;
begin
  ResponseLength := FStream.Size;

  Response.Status := FResponse.Status;
  Response.StatusText := FResponse.StatusText;
  Response.MimeType := FResponse.MimeType;
  Response.Error := FResponse.Error;

  HeaderMapTemp := TCefStringMultimapOwn.Create;
  FinalHeaderMap := TCefStringMultimapOwn.Create;

  FResponse.GetHeaderMap(HeaderMapTemp);

  if HeaderMapTemp.Size <> 0 then
  begin
    for i := 0 to HeaderMapTemp.Size do
    begin
      if (Lowercase(HeaderMapTemp.Key[i]) <> 'x-frame-options') then
        FinalHeaderMap.Append(HeaderMapTemp.Key[i], HeaderMapTemp.Value[i]);

    end;
  end;

  Response.SetHeaderMap(FinalHeaderMap);
  
end;


procedure TCustomResourceHandler.OnCreateURLRequest(Sender: TObject);
begin
  TCefUrlRequestRef.New(FRequest, FClient.Client, nil);
end;

procedure TCustomResourceHandler.OnDownloadData(Sender: TObject;
  const request: ICefUrlRequest; data: Pointer; dataLength: NativeUInt);
begin
  if (data <> nil) and (dataLength > 0) then
    FStream.WriteBuffer(data^, dataLength);

end;

procedure TCustomResourceHandler.OnRequestComplete(Sender: TObject;
  const request: ICefUrlRequest);
begin
  Self.CompleteRequest(request);
  
end;

function TCustomResourceHandler.ProcessRequest(const Request: ICefRequest;
  const Callback: ICefCallback): Boolean;
var
  HeaderMapTemp: ICefStringMultimap;
  i: Integer;
begin
  Result := True;
  FOffset := 0;
  FCallback := Callback;

  FRequest        := TCefRequestRef.New;
  HeaderMapTemp := TCefStringMultimapOwn.Create;

  Request.GetHeaderMap(HeaderMapTemp);
  FRequest.SetReferrer(Request.ReferrerUrl, Request.ReferrerPolicy);
  FRequest.Assign(Request.Url, Request.Method, Request.PostData, HeaderMapTemp);

  FRequest.Flags  := UR_FLAG_ALLOW_STORED_CREDENTIALS;

  FClient.AddURLRequest;
  
end;

function TCustomResourceHandler.ReadResponse(const DataOut: Pointer;
  BytesToRead: Integer; var BytesRead: Integer;
  const Callback: ICefCallback): Boolean;
begin
  if FOffset < FStream.Size then
  begin
    Result := True;
    BytesRead := BytesToRead;
    Move(Pointer(NativeUInt(FStream.Memory) + FOffset)^, DataOut^, BytesRead);
    Inc(FOffset, BytesRead);
  end
  else
    Result := False;
    
end;

end.
The header filtering in GetResponseHeaders isn't pretty but there doesn't seem to be a way to manipulate them directly. I couldn't figure out how to cancel the request either but not sure if this makes a difference.

Code: Select all

function TCustomResourceHandler.ReadResponse(const DataOut: Pointer;
  BytesToRead: Integer; var BytesRead: Integer;
  const Callback: ICefCallback): Boolean;
begin
  if FOffset < FStream.Size then
  begin
    Result := True;
    BytesRead := BytesToRead;
    Move(Pointer(NativeUInt(FStream.Memory) + FOffset)^, DataOut^, BytesRead);
    Inc(FOffset, BytesRead);
  end
  else
    Result := False;
    
end;
For a correct entry in response data, I think it is necessary make a check so that it doesn't exceed the size of the data.

Code: Select all

if FStream.Size-FOffset<BytesToRead then
    BytesRead:=FStream.Size-FOffset else
    BytesRead := BytesToRead;
Am I right?
Zuzlan
Posts: 1
Joined: Tue Nov 28, 2023 6:44 am

Re: How To Close Or ByPass Content Security Policy(CSP)

Post by Zuzlan »

Thank you for the solution
The only thing I would change is ReadResponse function.
I think it will be better:

Code: Select all

function TCustomResourceHandler.ReadResponse(const DataOut: Pointer;
  BytesToRead: Integer; var BytesRead: Integer;
  const Callback: ICefCallback): Boolean;
begin
  Result := False;
  BytesRead := 0;

  if Assigned(FStream) and (FOffset < FStream.Size) then
  begin
    BytesRead:=Min(BytesToRead, FStream.Size - FOffset);
    Move(Pointer(NativeUInt(FStream.Memory) + FOffset)^, DataOut^, BytesRead);
    Inc(FOffset, BytesRead);
    Result:=True;
  end;
end;
Post Reply