1

I am trying to replace the data that webbrowser requests with a local file but the result is not displayed in the browser. So how to properly use TCefStreamReaderRef?

procedure TForm1.Chromium1BeforeResourceLoad(Sender: TObject;
  const browser: ICefBrowser; const request: ICefRequest;
  var redirectUrl: ustring; var resourceStream: ICefStreamReader;
  const response: ICefResponse; loadFlags: Integer; out Result: Boolean);
var
  strm: ICefStreamReader;
begin
  strm := TCefStreamReaderRef.CreateForFile('c:\sometxtfile.txt');
  resourceStream:=strm;

  result:=True;
end;
  • You need to load a resource for which you have a usage in the loaded page, don't you ? I don't think that if you load some resource that is automatically shown somewhere on the site (even in case of text file). – TLama Aug 13 '13 at 20:48
  • @TLama If a user requests `http:\\www.google.com` it should load this `c:\sometxtfile.txt` :). I tried this in DCEF Groups but it will not work. [Link](https://groups.google.com/forum/#!topicsearchin/delphichromiumembedded/after$3A2011$2F01$2F01$20before$3A2011$2F01$2F31/delphichromiumembedded/pKAvd8Hgo4I) –  Aug 13 '13 at 20:49
  • You're using that stream reader correctly (you might remove the `strm` variable though). But it seems to me that you're using the [`OnBeforeResourceLoad`](http://magpcss.org/ceforum/apidocs/projects/(default)/CefRequestHandler.html#OnBeforeResourceLoad) event for something different. What is your goal ? Are you going to redirect navigation from one site to another; e.g. instead of navigating to `google.com` navigate (or load in other words) to a text file ? – TLama Aug 13 '13 at 21:10
  • @TLama But why won't the txt contents appear in the browser? Hmm I think in need to use TScheme to intercept requests. –  Aug 13 '13 at 21:12
  • I understand resources as additional files needed for a certain site. Like fonts, images, scripts and stylesheets. And I just can't imagine how would you load a text file instead of image for instance. There's a specific HTML tag expecting the type of a resource (the renderer can't just render a text file instead of expected image). There's no problem to load a text file in a browser, but I don't think that as a resource. – TLama Aug 13 '13 at 21:25
  • @TLama Can we chat? :) I have a few extra related questions regarding this question. –  Aug 13 '13 at 21:28
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/35391/discussion-between-tlama-and-user2665920) – TLama Aug 13 '13 at 21:28
  • @TLama Im here, lets chat. :) –  Aug 15 '13 at 08:01

1 Answers1

2

You're using the TCefStreamReaderRef correctly, but you're having two issues in the code. You must return False to the Result parameter and you're trying to load a text file for all requested resources.

The first problem is related to what is stated in the OnBeforeResourceLoad event reference (quote is emphasized by me):

OnBeforeResourceLoad

Called on the IO thread before a resource is loaded. To allow the resource to load normally return false. To redirect the resource to a new url populate the |redirectUrl| value and return false. To specify data for the resource return a CefStream object in |resourceStream|, use the |response| object to set mime type, HTTP status code and optional header values, and return false. To cancel loading of the resource return true. Any modifications to |request| will be observed. If the URL in |request| is changed and |redirectUrl| is also set, the URL in |request| will be used.

The second problem is that the site can for instance expect to load and render an image from a certain resource, but you have forcely tell the resource loader to load a text file instead. Now imagine what can renderer do with a text file resource for an image tag to be rendered. You just confused it, so it renders nothing.

For a proof of concept example you can try the following code e.g. It loads a sprite of the StackOverflow site from file (you can get an example green sprite image from here):

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, cefvcl, ceflib;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FChromium: TChromium;
    procedure BeforeResourceLoad(Sender: TObject; const browser: ICefBrowser;
      const request: ICefRequest; var redirectUrl: ustring; var resourceStream: ICefStreamReader;
      const response: ICefResponse; loadFlags: Integer; out Result: Boolean);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FChromium := TChromium.Create(nil);
  FChromium.Parent := Self;
  FChromium.Anchors := [akLeft, akTop, akRight, akBottom];
  FChromium.SetBounds(8, 8, ClientWidth - 16, ClientHeight - 16);
  FChromium.Load('http://stackoverflow.com');
  FChromium.OnBeforeResourceLoad := BeforeResourceLoad;
end;

procedure TForm1.BeforeResourceLoad(Sender: TObject; const browser: ICefBrowser;
  const request: ICefRequest; var redirectUrl: ustring; var resourceStream: ICefStreamReader;
  const response: ICefResponse; loadFlags: Integer; out Result: Boolean);
begin
  // return False here, since returning True means cancel loading of the resource
  Result := False;
  // check if the site is requesting a specific resource and if so, then...
  if Request.Url = 'http://cdn.sstatic.net/stackoverflow/img/sprites.png?v=6' then
  begin
    // load a resource from file and set the HTTP status code and MIME type
    ResourceStream := TCefStreamReaderRef.CreateForFile('sprites.png');
    response.Status := 200;
    response.MimeType := 'image/png';
  end;
end;

end.

The full project you can get from here.

TLama
  • 75,147
  • 17
  • 214
  • 392
  • 1
    how to make this with the last version of DCEF3 ? the response and resourceStream objects doesn't exist in the version. the prototype in DCEF3 is BeforeResourceLoad(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; out Result: Boolean) – Nono Jun 25 '14 at 14:51
  • 2
    @Nono with DEF3, you must use OnGetResourceHandler event and return an object that extends TCefResourceHandlerOwn – Stéphane B. Jun 18 '15 at 12:35