Memory leak on using TAdvWebBrowser and TCoreWebView2HistoryChangedEventHandler

Hi,

We have been using the TAdvWebBrowser and TCoreWebView2HistoryChangedEventHandler in one of our forms. However when closing the application we notice a few memory leaks. Any idea on how to prevent these?

Probably it is caused by the creation of the TCoreWebView2HistoryChangedEventHandler in the code below.

type
  TCoreWebView2HistoryChangedEventHandler = class(TInterfacedPersistent, ICoreWebView2HistoryChangedEventHandler)
    function Invoke(sender: ICoreWebView2; args: IUnknown): HRESULT; stdcall;
  end;

..

procedure TFormFormCreate(Sender: TObject);
var
  w: ICoreWebView2;
  c: ICoreWebView2Controller;
  e: EventRegistrationToken;
begin
  c := ICoreWebView2Controller(AdvWebBrowserLogin.NativeBrowser);
  if c.get_CoreWebView2(w) = S_OK then
  begin
    w.add_HistoryChanged(TCoreWebView2HistoryChangedEventHandler.Create, @e);
  end;
end;


{ TCoreWebView2HistoryChangedEventHandler }

function TCoreWebView2HistoryChangedEventHandler.Invoke(sender: ICoreWebView2;
  args: IInterface): HRESULT;
var
  s: PWideChar;
  cText: string;
  oJSONValue: TJSONValue;
begin
  Result := S_OK;
  if sender.get_Source(@s) = S_OK then
  begin
    cText := PChar(s);
    AdvWebBrowserLogin.ExecuteJavaScript('window.sessionStorage.getItem("default_oauth")',
      procedure(const AValue: string)
      begin
        if (AValue<>'null') and (AValue<>'"null"') then
        begin
         cDefault_token := AnsiReplaceStr(AValue, '"', '');
        end;
      end);
    end;
  end;

afbeelding

3 things:

  1. You need to change the type to TInterfacedObject instead of TInterfacedPersistent for no memory leaks
  2. Keep track of the token to remove the event handler
  3. Move the code to the OnInitialized event

For the moment, you can only apply number 1). The other 2 items are not possible because we need to release an update first. The best tactics will be based on the code below.

unit Unit22;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, AdvCustomControl, AdvWebBrowser, AdvWebBrowser.Win;

type
  TForm22 = class(TForm)
    AdvWebBrowserLogin: TAdvWebBrowser;
    procedure FormCreate(Sender: TObject);
    procedure AdvWebBrowserLoginInitialized(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    cDefault_token: string;
    FToken: EventRegistrationToken;
  public
    { Public declarations }
  end;

var
  Form22: TForm22;

implementation

{$R *.dfm}

uses
  StrUtils, JSON;

type
  TCoreWebView2HistoryChangedEventHandler = class(TInterfacedObject, ICoreWebView2HistoryChangedEventHandler)
    function Invoke(sender: ICoreWebView2; args: IUnknown): HRESULT; stdcall;
  end;

procedure TForm22.AdvWebBrowserLoginInitialized(Sender: TObject);
var
  w: ICoreWebView2;
  c: ICoreWebView2Controller;
begin
  c := ICoreWebView2Controller(AdvWebBrowserLogin.NativeBrowser);
  if c.get_CoreWebView2(w) = S_OK then
    w.add_HistoryChanged(TCoreWebView2HistoryChangedEventHandler.Create, @FToken);
end;

procedure TForm22.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown := True;
end;

procedure TForm22.FormDestroy(Sender: TObject);
var
  w: ICoreWebView2;
  c: ICoreWebView2Controller;
begin
  c := ICoreWebView2Controller(AdvWebBrowserLogin.NativeBrowser);
  if c.get_CoreWebView2(w) = S_OK then
    w.remove_HistoryChanged(FToken);
end;

{ TCoreWebView2HistoryChangedEventHandler }

function TCoreWebView2HistoryChangedEventHandler.Invoke(sender: ICoreWebView2;
  args: IInterface): HRESULT;
var
  s: PWideChar;
  cText: string;
  oJSONValue: TJSONValue;
begin
  Result := S_OK;
  if sender.get_Source(@s) = S_OK then
  begin
    cText := PChar(s);
    Form22.AdvWebBrowserLogin.ExecuteJavaScript('window.sessionStorage.getItem("default_oauth")',
      procedure(const AValue: string)
      begin
        if (AValue<>'null') and (AValue<>'"null"') then
        begin
         Form22.cDefault_token := AnsiReplaceStr(AValue, '"', '');
        end;
      end);
    end;
  end;

end.