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;
You need to change the type to TInterfacedObject instead of TInterfacedPersistent for no memory leaks
Keep track of the token to remove the event handler
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.