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;
3 things:
- 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.