Reputation: 1025
I use Microsoft's WebView2 via a TEdgeBrowser in Delphi (currently 11.2, soon probably 11.3).
I want to delete a specific cookie.
This is possible, in principle, with the DeleteCookie method of CoreWebView2CookieManager, as explained for example here: https://stackoverflow.com/a/64293869/2776981
Now my question is: how can I access this from Delphi?
Upvotes: 1
Views: 911
Reputation: 1025
After the realization that, with a new enough version of WebView2 installed, the ICoreWebView2 returned by EdgeBrowser.ControllerInterface.Get_CoreWebView2() also supports the ICoreWebView2_2 interface (an extension of the interface ICoreWebView2), which has the Get_CookieManager method, I came up with this solution.
DeleteAllCookies and DeleteCookies both work. (Emtpy string works as a "wildcard" for domain or path in DeleteCookies.)
The main question, how to access CoreWebView2CookieManager from Delphi, seems to have been answered by this.
The interface declarations in this code were created with tlibimp.exe, as described in this Stackoverflow post: WebView2 (TEdgeBrowser) updated Delphi interface (e.g. ICoreWebView2Controller2).
unit WebView2Cookies;
interface
uses
Vcl.Edge;
procedure DeleteWebView2Cookies(EdgeBrowser: TCustomEdgeBrowser; const CookieName, CookieDomain, CookiePath: string);
procedure DeleteAllWebView2Cookies(EdgeBrowser: TCustomEdgeBrowser);
implementation
uses
System.SysUtils,
Winapi.ActiveX, Winapi.WebView2;
// Constants for enum COREWEBVIEW2_COOKIE_SAME_SITE_KIND
type
COREWEBVIEW2_COOKIE_SAME_SITE_KIND = TOleEnum;
const
COREWEBVIEW2_COOKIE_SAME_SITE_KIND_NONE = $00000000;
COREWEBVIEW2_COOKIE_SAME_SITE_KIND_LAX = $00000001;
COREWEBVIEW2_COOKIE_SAME_SITE_KIND_STRICT = $00000002;
const
IID_ICoreWebView2_2: TGUID = '{9E8F0CF8-E670-4B5E-B2BC-73E061E3184C}';
IID_ICoreWebView2CookieManager: TGUID = '{177CD9E7-B6F5-451A-94A0-5D7A3A4C4141}';
type
ICoreWebView2_2 = interface;
ICoreWebView2WebResourceResponseReceivedEventHandler = interface;
ICoreWebView2DOMContentLoadedEventHandler = interface;
ICoreWebView2WebResourceResponseReceivedEventArgs = interface;
ICoreWebView2DOMContentLoadedEventArgs = interface;
ICoreWebView2WebResourceResponseView = interface;
ICoreWebView2WebResourceResponseViewGetContentCompletedHandler = interface;
ICoreWebView2CookieManager = interface;
ICoreWebView2Cookie = interface;
ICoreWebView2GetCookiesCompletedHandler = interface;
ICoreWebView2CookieList = interface;
// *********************************************************************//
// Interface: ICoreWebView2_2
// Flags: (0)
// GUID: {9E8F0CF8-E670-4B5E-B2BC-73E061E3184C}
// *********************************************************************//
ICoreWebView2_2 = interface(ICoreWebView2)
['{9E8F0CF8-E670-4B5E-B2BC-73E061E3184C}']
function add_WebResourceResponseReceived(const eventHandler: ICoreWebView2WebResourceResponseReceivedEventHandler;
out token: EventRegistrationToken): HResult; stdcall;
function remove_WebResourceResponseReceived(token: EventRegistrationToken): HResult; stdcall;
function NavigateWithWebResourceRequest(const Request: ICoreWebView2WebResourceRequest): HResult; stdcall;
function add_DOMContentLoaded(const eventHandler: ICoreWebView2DOMContentLoadedEventHandler;
out token: EventRegistrationToken): HResult; stdcall;
function remove_DOMContentLoaded(token: EventRegistrationToken): HResult; stdcall;
function Get_CookieManager(out CookieManager: ICoreWebView2CookieManager): HResult; stdcall;
function Get_Environment(out Environment: ICoreWebView2Environment): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2WebResourceResponseReceivedEventHandler
// Flags: (0)
// GUID: {7DE9898A-24F5-40C3-A2DE-D4F458E69828}
// *********************************************************************//
ICoreWebView2WebResourceResponseReceivedEventHandler = interface(IUnknown)
['{7DE9898A-24F5-40C3-A2DE-D4F458E69828}']
function Invoke(const sender: ICoreWebView2;
const args: ICoreWebView2WebResourceResponseReceivedEventArgs): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2DOMContentLoadedEventHandler
// Flags: (0)
// GUID: {4BAC7E9C-199E-49ED-87ED-249303ACF019}
// *********************************************************************//
ICoreWebView2DOMContentLoadedEventHandler = interface(IUnknown)
['{4BAC7E9C-199E-49ED-87ED-249303ACF019}']
function Invoke(const sender: ICoreWebView2; const args: ICoreWebView2DOMContentLoadedEventArgs): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2WebResourceResponseReceivedEventArgs
// Flags: (0)
// GUID: {D1DB483D-6796-4B8B-80FC-13712BB716F4}
// *********************************************************************//
ICoreWebView2WebResourceResponseReceivedEventArgs = interface(IUnknown)
['{D1DB483D-6796-4B8B-80FC-13712BB716F4}']
function Get_Request(out Request: ICoreWebView2WebResourceRequest): HResult; stdcall;
function Get_Response(out Response: ICoreWebView2WebResourceResponseView): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2DOMContentLoadedEventArgs
// Flags: (0)
// GUID: {16B1E21A-C503-44F2-84C9-70ABA5031283}
// *********************************************************************//
ICoreWebView2DOMContentLoadedEventArgs = interface(IUnknown)
['{16B1E21A-C503-44F2-84C9-70ABA5031283}']
function Get_NavigationId(out NavigationId: Largeuint): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2WebResourceResponseView
// Flags: (0)
// GUID: {79701053-7759-4162-8F7D-F1B3F084928D}
// *********************************************************************//
ICoreWebView2WebResourceResponseView = interface(IUnknown)
['{79701053-7759-4162-8F7D-F1B3F084928D}']
function Get_Headers(out Headers: ICoreWebView2HttpResponseHeaders): HResult; stdcall;
function Get_StatusCode(out StatusCode: SYSINT): HResult; stdcall;
function Get_ReasonPhrase(out ReasonPhrase: PWideChar): HResult; stdcall;
function GetContent(const handler: ICoreWebView2WebResourceResponseViewGetContentCompletedHandler): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2WebResourceResponseViewGetContentCompletedHandler
// Flags: (0)
// GUID: {875738E1-9FA2-40E3-8B74-2E8972DD6FE7}
// *********************************************************************//
ICoreWebView2WebResourceResponseViewGetContentCompletedHandler = interface(IUnknown)
['{875738E1-9FA2-40E3-8B74-2E8972DD6FE7}']
function Invoke(errorCode: HResult; const Content: IStream): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2CookieManager
// Flags: (0)
// GUID: {177CD9E7-B6F5-451A-94A0-5D7A3A4C4141}
// *********************************************************************//
ICoreWebView2CookieManager = interface(IUnknown)
['{177CD9E7-B6F5-451A-94A0-5D7A3A4C4141}']
function CreateCookie(name: PWideChar; value: PWideChar; Domain: PWideChar; Path: PWideChar;
out cookie: ICoreWebView2Cookie): HResult; stdcall;
function CopyCookie(const cookieParam: ICoreWebView2Cookie; out cookie: ICoreWebView2Cookie): HResult; stdcall;
function GetCookies(uri: PWideChar; const handler: ICoreWebView2GetCookiesCompletedHandler): HResult; stdcall;
function AddOrUpdateCookie(const cookie: ICoreWebView2Cookie): HResult; stdcall;
function DeleteCookie(const cookie: ICoreWebView2Cookie): HResult; stdcall;
function DeleteCookies(name: PWideChar; uri: PWideChar): HResult; stdcall;
function DeleteCookiesWithDomainAndPath(name: PWideChar; Domain: PWideChar; Path: PWideChar): HResult; stdcall;
function DeleteAllCookies: HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2Cookie
// Flags: (0)
// GUID: {AD26D6BE-1486-43E6-BF87-A2034006CA21}
// *********************************************************************//
ICoreWebView2Cookie = interface(IUnknown)
['{AD26D6BE-1486-43E6-BF87-A2034006CA21}']
function Get_name(out name: PWideChar): HResult; stdcall;
function Get_value(out value: PWideChar): HResult; stdcall;
function Set_value(value: PWideChar): HResult; stdcall;
function Get_Domain(out Domain: PWideChar): HResult; stdcall;
function Get_Path(out Path: PWideChar): HResult; stdcall;
function Get_Expires(out Expires: Double): HResult; stdcall;
function Set_Expires(Expires: Double): HResult; stdcall;
function Get_IsHttpOnly(out IsHttpOnly: Integer): HResult; stdcall;
function Set_IsHttpOnly(IsHttpOnly: Integer): HResult; stdcall;
function Get_SameSite(out SameSite: COREWEBVIEW2_COOKIE_SAME_SITE_KIND): HResult; stdcall;
function Set_SameSite(SameSite: COREWEBVIEW2_COOKIE_SAME_SITE_KIND): HResult; stdcall;
function Get_IsSecure(out IsSecure: Integer): HResult; stdcall;
function Set_IsSecure(IsSecure: Integer): HResult; stdcall;
function Get_IsSession(out IsSession: Integer): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2GetCookiesCompletedHandler
// Flags: (0)
// GUID: {5A4F5069-5C15-47C3-8646-F4DE1C116670}
// *********************************************************************//
ICoreWebView2GetCookiesCompletedHandler = interface(IUnknown)
['{5A4F5069-5C15-47C3-8646-F4DE1C116670}']
function Invoke(result: HResult; const cookieList: ICoreWebView2CookieList): HResult; stdcall;
end;
// *********************************************************************//
// Interface: ICoreWebView2CookieList
// Flags: (0)
// GUID: {F7F6F714-5D2A-43C6-9503-346ECE02D186}
// *********************************************************************//
ICoreWebView2CookieList = interface(IUnknown)
['{F7F6F714-5D2A-43C6-9503-346ECE02D186}']
function Get_Count(out Count: SYSUINT): HResult; stdcall;
function GetValueAtIndex(index: SYSUINT; out cookie: ICoreWebView2Cookie): HResult; stdcall;
end;
procedure GetCookieManager(EdgeBrowser: TCustomEdgeBrowser; out CookieManager: ICoreWebView2CookieManager);
var
Core2: ICoreWebView2;
Core2_2: ICoreWebView2_2;
HR: HRESULT;
begin
EdgeBrowser.ControllerInterface.Get_CoreWebView2(Core2);
if not Assigned(Core2) then
raise Exception.Create('Get_CoreWebView2 not found');
Core2.QueryInterface(IID_ICoreWebView2_2, Core2_2);
if not Assigned(Core2_2) then
raise Exception.Create('IID_ICoreWebView2_2 not found');
HR := Core2_2.Get_CookieManager(CookieManager);
if not Succeeded(HR) then
raise Exception.Create('Get_CookieManager failed');
end;
procedure DeleteWebView2Cookies(EdgeBrowser: TCustomEdgeBrowser; const CookieName, CookieDomain, CookiePath: string);
var
CookieMan: ICoreWebView2CookieManager;
HR: HRESULT;
begin
GetCookieManager(EdgeBrowser, CookieMan);
HR := CookieMan.DeleteCookiesWithDomainAndPath(PWideChar(CookieName), PWideChar(CookieDomain), PWideChar(CookiePath));
if not Succeeded(HR) then
raise Exception.Create('DeleteCookiesWithDomainAndPath failed');
end;
procedure DeleteAllWebView2Cookies(EdgeBrowser: TCustomEdgeBrowser);
var
CookieMan: ICoreWebView2CookieManager;
HR: HRESULT;
begin
GetCookieManager(EdgeBrowser, CookieMan);
HR := CookieMan.DeleteAllCookies;
if not Succeeded(HR) then
raise Exception.Create('DeleteAllCookies failed');
end;
end.
Perhaps also helpful, for experimenting with the interface and studying cookies, is this ShowWebView2Cookies procedure:
uses Vcl.Dialogs;
type
TCompletedHandler = class(TInterfacedObject, ICoreWebView2GetCookiesCompletedHandler)
private
function Invoke(CallResult: HResult; const cookieList: ICoreWebView2CookieList): HResult; stdcall;
end;
procedure ShowWebView2Cookies(EdgeBrowser: TCustomEdgeBrowser);
var
CookieMan: ICoreWebView2CookieManager;
CompletedHandler: ICoreWebView2GetCookiesCompletedHandler;
begin
GetCookieManager(EdgeBrowser, CookieMan);
CompletedHandler := TCompletedHandler.Create;
CookieMan.GetCookies('', CompletedHandler);
end;
{ TCompletedHandler }
function TCompletedHandler.Invoke(CallResult: HResult;
const cookieList: ICoreWebView2CookieList): HResult;
var
s: string;
i, Count: SYSUINT;
LCookie: ICoreWebView2Cookie;
HR: HResult;
pwc: PWideChar;
begin
if not Succeeded(CallResult) then
raise Exception.Create('GetCookies failed');
HR := cookieList.Get_Count(Count);
if not Succeeded(HR) then
raise Exception.Create('cookieList.Get_Count failed');
s := 'Found ' + IntToStr(Count) + ' cookies:' + #13#10;
if Count > 0 then
begin
for i := 0 to Count - 1 do
begin
HR := cookieList.GetValueAtIndex(i, LCookie);
if not Succeeded(HR) then
raise Exception.Create('cookieList.GetValueAtIndex failed');
LCookie.Get_name(pwc);
s := s + 'name = ' + pwc;
CoTaskMemFree(pwc);
LCookie.Get_Domain(pwc);
s := s + ', domain = ' + pwc;
CoTaskMemFree(pwc);
LCookie.Get_Path(pwc);
s := s + ', path = ' + pwc;
CoTaskMemFree(pwc);
s := s + #13#10;
end;
end;
ShowMessage(s);
Result := S_OK;
end;
Upvotes: 1