From 417c0d7d8d67d43d55dff25fb27548f7b053d3ea Mon Sep 17 00:00:00 2001 From: salvadordf Date: Mon, 9 May 2022 21:37:05 +0200 Subject: [PATCH] Update to WebView2 NuGet 1.0.1210.39 Added workaround memory leak with custom context menu items --- README.md | 2 +- bin32/WebView2Loader.dll | Bin 111560 -> 111544 bytes bin64/WebView2Loader.dll | Bin 142288 -> 142264 bytes .../Delphi_VCL/KioskBrowser/KioskBrowser.dpr | 1 + .../KioskBrowser/KioskBrowser.dproj | 16 +- .../Delphi_VCL/KioskBrowser/uKioskBrowser.dfm | 1 - .../Delphi_VCL/MiniBrowser/MiniBrowser.dproj | 14 +- demos/Delphi_VCL/MiniBrowser/uMiniBrowser.dfm | 1 - demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas | 5 +- packages/WebView4DelphiVCLRTL.dpk | 4 +- packages/WebView4DelphiVCLRTL.dproj | 2 + packages/webview4delphi.lpk | 2 +- source/uWVBrowserBase.pas | 265 ++++++++++++------ source/uWVConstants.pas | 12 +- source/uWVCoreWebView2.pas | 22 +- source/uWVCoreWebView2ContextMenuItem.pas | 10 +- ...VCoreWebView2ContextMenuItemCollection.pas | 7 + source/uWVCoreWebView2ControllerOptions.pas | 97 +++++++ source/uWVCoreWebView2Environment.pas | 91 +++++- source/uWVCoreWebView2EnvironmentOptions.pas | 6 - source/uWVCoreWebView2Profile.pas | 148 ++++++++++ source/uWVTypeLibrary.pas | 85 +++++- source/uWVTypes.pas | 1 + update_WebView4Delphi.json | 4 +- 24 files changed, 648 insertions(+), 148 deletions(-) create mode 100644 source/uWVCoreWebView2ControllerOptions.pas create mode 100644 source/uWVCoreWebView2Profile.pas diff --git a/README.md b/README.md index 1921a6e..e821ac1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ WebView4Delphi is an open source project created by Salvador Díaz Fau to embed WebView4Delphi only supports Windows. If you need to embed a web browser in Linux, Windows or MacOS consider using [CEF4Delphi](https://github.com/salvadordf/CEF4Delphi) instead. -WebView4Delphi uses the [Microsoft Edge WebView2 Runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/) and [Microsoft.Web.WebView2 NuGet package version 1.0.1185.39](https://www.nuget.org/packages/Microsoft.Web.WebView2) to embed a web browser. +WebView4Delphi uses the [Microsoft Edge WebView2 Runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/) and [Microsoft.Web.WebView2 NuGet package version 1.0.1210.39](https://www.nuget.org/packages/Microsoft.Web.WebView2) to embed a web browser. WebView4Delphi was developed and tested on Delphi 11.1, Delphi XE3 and Lazarus 2.2.0/FPC 3.2.2. diff --git a/bin32/WebView2Loader.dll b/bin32/WebView2Loader.dll index 05fac9e52f64c7ce1e99c485384172a5c9075093..0dd8a78074bb268817d626dbfd091f3b58f79262 100644 GIT binary patch delta 4159 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 IoApBeA6$LwMF0Q* delta 4011 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

-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 {1424089C-DBAE-4E95-AC2D-1A511736D664} - 19.3 + 19.4 VCL KioskBrowser.dpr True @@ -965,17 +965,17 @@ 1 - - - - - - - + + + + + + + True diff --git a/demos/Delphi_VCL/KioskBrowser/uKioskBrowser.dfm b/demos/Delphi_VCL/KioskBrowser/uKioskBrowser.dfm index 0d33b25..0b63670 100644 --- a/demos/Delphi_VCL/KioskBrowser/uKioskBrowser.dfm +++ b/demos/Delphi_VCL/KioskBrowser/uKioskBrowser.dfm @@ -14,7 +14,6 @@ object MainForm: TMainForm WindowState = wsMaximized OnCreate = FormCreate OnShow = FormShow - PixelsPerInch = 96 TextHeight = 15 object WVWindowParent1: TWVWindowParent Left = 0 diff --git a/demos/Delphi_VCL/MiniBrowser/MiniBrowser.dproj b/demos/Delphi_VCL/MiniBrowser/MiniBrowser.dproj index 0e84606..a33d61c 100644 --- a/demos/Delphi_VCL/MiniBrowser/MiniBrowser.dproj +++ b/demos/Delphi_VCL/MiniBrowser/MiniBrowser.dproj @@ -1,7 +1,7 @@  {727B56F4-AE61-4F6D-B73E-6F9DF40B4EB7} - 19.3 + 19.4 VCL MiniBrowser.dpr True @@ -972,17 +972,17 @@ 1 + + + + + + - - - - - - True diff --git a/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.dfm b/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.dfm index e832d37..b09a73c 100644 --- a/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.dfm +++ b/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.dfm @@ -14,7 +14,6 @@ object MiniBrowserFrm: TMiniBrowserFrm OnCreate = FormCreate OnDestroy = FormDestroy OnShow = FormShow - PixelsPerInch = 96 TextHeight = 15 object NavControlPnl: TPanel Left = 0 diff --git a/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas b/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas index be02316..e7bca1d 100644 --- a/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas +++ b/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas @@ -106,8 +106,7 @@ TMiniBrowserFrm = class(TForm) procedure WVBrowser1RetrieveTextCompleted(Sender: TObject; aResult: Boolean; const aText: wvstring); procedure WVBrowser1RetrieveMHTMLCompleted(Sender: TObject; aResult: Boolean; const aMHTML: wvstring); procedure WVBrowser1BasicAuthenticationRequested(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2BasicAuthenticationRequestedEventArgs); - procedure WVBrowser1StatusBarTextChanged(Sender: TObject; - const aWebView: ICoreWebView2); + procedure WVBrowser1StatusBarTextChanged(Sender: TObject; const aWebView: ICoreWebView2); protected FDownloadOperation : TCoreWebView2DownloadOperation; @@ -299,7 +298,7 @@ procedure TMiniBrowserFrm.FormCreate(Sender: TObject); FBlockImages := False; FDownloadIDGen := 0; FDownloadOperation := nil; - WVBrowser1.DefaultURL := URLCbx.Text; + WVBrowser1.DefaultURL := URLCbx.Text; end; procedure TMiniBrowserFrm.FormDestroy(Sender: TObject); diff --git a/packages/WebView4DelphiVCLRTL.dpk b/packages/WebView4DelphiVCLRTL.dpk index 07d8e6a..62fbf23 100644 --- a/packages/WebView4DelphiVCLRTL.dpk +++ b/packages/WebView4DelphiVCLRTL.dpk @@ -79,6 +79,8 @@ contains uWVCoreWebView2BasicAuthenticationResponse in '..\source\uWVCoreWebView2BasicAuthenticationResponse.pas', uWVCoreWebView2ContextMenuItemCollection in '..\source\uWVCoreWebView2ContextMenuItemCollection.pas', uWVCoreWebView2ContextMenuItem in '..\source\uWVCoreWebView2ContextMenuItem.pas', - uWVCoreWebView2ContextMenuTarget in '..\source\uWVCoreWebView2ContextMenuTarget.pas'; + uWVCoreWebView2ContextMenuTarget in '..\source\uWVCoreWebView2ContextMenuTarget.pas', + uWVCoreWebView2Profile in '..\source\uWVCoreWebView2Profile.pas', + uWVCoreWebView2ControllerOptions in '..\source\uWVCoreWebView2ControllerOptions.pas'; end. diff --git a/packages/WebView4DelphiVCLRTL.dproj b/packages/WebView4DelphiVCLRTL.dproj index 5234aca..4a43978 100644 --- a/packages/WebView4DelphiVCLRTL.dproj +++ b/packages/WebView4DelphiVCLRTL.dproj @@ -143,6 +143,8 @@ + + Base diff --git a/packages/webview4delphi.lpk b/packages/webview4delphi.lpk index 40614ef..e5a6a93 100644 --- a/packages/webview4delphi.lpk +++ b/packages/webview4delphi.lpk @@ -12,7 +12,7 @@ - + diff --git a/source/uWVBrowserBase.pas b/source/uWVBrowserBase.pas index 65b4e58..84ce318 100644 --- a/source/uWVBrowserBase.pas +++ b/source/uWVBrowserBase.pas @@ -19,7 +19,7 @@ interface uWVInterfaces, uWVEvents, uWVCoreWebView2, uWVCoreWebView2Settings, uWVCoreWebView2Environment, uWVCoreWebView2Controller, uWVCoreWebView2PrintSettings, uWVCoreWebView2CompositionController, - uWVCoreWebView2CookieManager; + uWVCoreWebView2CookieManager, uWVCoreWebView2Delegates; type TWVBrowserBase = class(TComponent, IWVBrowserEvents) @@ -45,6 +45,9 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) FZoomStep : byte; FOffline : boolean; FIsNavigating : boolean; + FProfileName : wvstring; + FIsInPrivateModeEnabled : boolean; + FMenuItemHandler : ICoreWebView2CustomItemSelectedEventHandler; FOldWidget0CompWndPrc : TFNWndProc; FOldWidget1CompWndPrc : TFNWndProc; @@ -184,6 +187,7 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) function GetStatusBarText : wvstring; function GetAllowExternalDrop : boolean; function GetHiddenPdfToolbarItems : TWVPDFToolbarItems; + function GetCustomItemSelectedEventHandler : ICoreWebView2CustomItemSelectedEventHandler; procedure SetBuiltInErrorPageEnabled(aValue: boolean); procedure SetDefaultContextMenusEnabled(aValue: boolean); @@ -218,8 +222,11 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) procedure SetDefaultDownloadDialogMargin(aValue : TPoint); procedure SetAllowExternalDrop(aValue : boolean); procedure SetHiddenPdfToolbarItems(aValue : TWVPDFToolbarItems); + procedure SetProfileName(const aValue : wvstring); function CreateEnvironment : boolean; + function CreateCompositionController: boolean; + function CreateController : boolean; procedure DestroyEnvironment; procedure DestroyController; @@ -227,6 +234,7 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) procedure DestroyWebView; procedure DestroySettings; procedure DestroyPrintSettings; + procedure DestroyMenuItemHandler; procedure UpdateZoomStep(aInc : boolean); procedure UpdateZoomPct(const aValue : double); @@ -476,21 +484,22 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) function SendPointerInput(aEventKind : TWVPointerEventKind; const aPointerInfo : ICoreWebView2PointerInfo) : boolean; // Custom properties - property Initialized : boolean read GetInitialized; - property CoreWebView2PrintSettings : TCoreWebView2PrintSettings read FCoreWebView2PrintSettings; - property CoreWebView2Settings : TCoreWebView2Settings read FCoreWebView2Settings; - property CoreWebView2Environment : TCoreWebView2Environment read FCoreWebView2Environment; - property CoreWebView2Controller : TCoreWebView2Controller read FCoreWebView2Controller; - property CoreWebView2CompositionController : TCoreWebView2CompositionController read FCoreWebView2CompositionController; - property CoreWebView2 : TCoreWebView2 read FCoreWebView2; - property DefaultURL : wvstring read FDefaultURL write FDefaultURL; - property IsNavigating : boolean read FIsNavigating; - property ZoomPct : double read GetZoomPct write SetZoomPct; // ICoreWebView2Controller.get_ZoomFactor - property ZoomStep : byte read FZoomStep write SetZoomStep; // ICoreWebView2Controller.get_ZoomFactor - property Widget0CompHWND : THandle read FWidget0CompHWND; - property Widget1CompHWND : THandle read FWidget1CompHWND; - property RenderCompHWND : THandle read FRenderCompHWND; - property D3DWindowCompHWND : THandle read FD3DWindowCompHWND; + property Initialized : boolean read GetInitialized; + property CoreWebView2PrintSettings : TCoreWebView2PrintSettings read FCoreWebView2PrintSettings; + property CoreWebView2Settings : TCoreWebView2Settings read FCoreWebView2Settings; + property CoreWebView2Environment : TCoreWebView2Environment read FCoreWebView2Environment; + property CoreWebView2Controller : TCoreWebView2Controller read FCoreWebView2Controller; + property CoreWebView2CompositionController : TCoreWebView2CompositionController read FCoreWebView2CompositionController; + property CoreWebView2 : TCoreWebView2 read FCoreWebView2; + property DefaultURL : wvstring read FDefaultURL write FDefaultURL; + property IsNavigating : boolean read FIsNavigating; + property ZoomPct : double read GetZoomPct write SetZoomPct; // ICoreWebView2Controller.get_ZoomFactor + property ZoomStep : byte read FZoomStep write SetZoomStep; // ICoreWebView2Controller.get_ZoomFactor + property Widget0CompHWND : THandle read FWidget0CompHWND; + property Widget1CompHWND : THandle read FWidget1CompHWND; + property RenderCompHWND : THandle read FRenderCompHWND; + property D3DWindowCompHWND : THandle read FD3DWindowCompHWND; + property CustomItemSelectedEventHandler : ICoreWebView2CustomItemSelectedEventHandler read GetCustomItemSelectedEventHandler; // Custom properties created using DevTool methods property Offline : boolean read FOffline write SetOffline; @@ -587,10 +596,14 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) property SystemCursorID : cardinal read GetSystemCursorID; // ICoreWebView2CompositionController.get_SystemCursorId // ICoreWebView2CompositionController2 properties - property AutomationProvider : IUnknown read GetAutomationProvider; // ICoreWebView2CompositionController2.get_UIAProvider + property AutomationProvider : IUnknown read GetAutomationProvider; // ICoreWebView2CompositionController2.get_UIAProvider // ICoreWebView2Environment8 properties - property ProcessInfos : ICoreWebView2ProcessInfoCollection read GetProcessInfos; + property ProcessInfos : ICoreWebView2ProcessInfoCollection read GetProcessInfos; // ICoreWebView2Environment8.GetProcessInfos + + // ICoreWebView2ControllerOptions properties + property ProfileName : wvstring read FProfileName write SetProfileName; // ICoreWebView2ControllerOptions.Get_ProfileName + property IsInPrivateModeEnabled : boolean read FIsInPrivateModeEnabled write FIsInPrivateModeEnabled; // ICoreWebView2ControllerOptions.Get_IsInPrivateModeEnabled // ICoreWebView2Environment5 events property OnBrowserProcessExited : TOnBrowserProcessExitedEvent read FOnBrowserProcessExited write FOnBrowserProcessExited; @@ -714,7 +727,7 @@ TWVBrowserBase = class(TComponent, IWVBrowserEvents) implementation uses - uWVMiscFunctions, uWVCoreWebView2Delegates, uWVCoreWebView2EnvironmentOptions; + uWVMiscFunctions, uWVCoreWebView2EnvironmentOptions, uWVCoreWebView2ControllerOptions; constructor TWVBrowserBase.Create(AOwner: TComponent); begin @@ -737,6 +750,9 @@ constructor TWVBrowserBase.Create(AOwner: TComponent); FZoomStep := ZOOM_STEP_DEF; FOffline := False; FIsNavigating := False; + FProfileName := ''; + FIsInPrivateModeEnabled := False; + FMenuItemHandler := nil; FOldWidget0CompWndPrc := nil; FOldWidget1CompWndPrc := nil; @@ -839,6 +855,7 @@ destructor TWVBrowserBase.Destroy; DestroyWebView; DestroyController; DestroyCompositionController; + DestroyMenuItemHandler; finally inherited Destroy; end; @@ -880,6 +897,23 @@ procedure TWVBrowserBase.DestroyPrintSettings; FreeAndNil(FCoreWebView2PrintSettings); end; +procedure TWVBrowserBase.DestroyMenuItemHandler; +begin + try + try + // WebView2 doesn't release any ICoreWebView2CustomItemSelectedEventHandler instance + while assigned(FMenuItemHandler) and + (TCoreWebView2CustomItemSelectedEventHandler(FMenuItemHandler).RefCount > 1) do + FMenuItemHandler._Release; + except + on e : exception do + if CustomExceptionHandler('TWVBrowserBase.DestroyMenuItemHandler', e) then raise; + end; + finally + FMenuItemHandler := nil; + end; +end; + {$IFNDEF FPC} // Windows XP and newer (older Delphi version < XE don't have them and newer // require a call to InitCommonControl what isn't necessary. @@ -1128,8 +1162,7 @@ function TWVBrowserBase.CapturePreview(aImageFormat: TWVCapturePreviewImageForma function TWVBrowserBase.EnvironmentCompletedHandler_Invoke(errorCode: HRESULT; const createdEnvironment: ICoreWebView2Environment): HRESULT; var - TempError : wvstring; - TempHResult : HRESULT; + TempError : wvstring; begin Result := S_OK; @@ -1141,35 +1174,9 @@ function TWVBrowserBase.EnvironmentCompletedHandler_Invoke(errorCode: HRESULT; c doOnEnvironmentCompleted; if FUseCompositionController then - begin - if not(FCoreWebView2Environment.CreateCoreWebView2CompositionController(FWindowParentHandle, self, TempHResult)) then - begin - TempError := 'There was an error creating the composition controller. (1)' + CRLF + - 'Error code : 0x' + - {$IFDEF FPC} - UTF8Decode(inttohex(TempHResult, 8)) - {$ELSE} - inttohex(TempHResult, 8) - {$ENDIF} - + CRLF + CompositionControllerCreationErrorToString(TempHResult); - - doOnInitializationError(TempHResult, TempError); - end; - end + CreateCompositionController else - if not(FCoreWebView2Environment.CreateCoreWebView2Controller(FWindowParentHandle, self, TempHResult)) then - begin - TempError := 'There was an error creating the controller. (1)' + CRLF + - 'Error code : 0x' + - {$IFDEF FPC} - UTF8Decode(inttohex(TempHResult, 8)) - {$ELSE} - inttohex(TempHResult, 8) - {$ENDIF} - + CRLF + ControllerCreationErrorToString(TempHResult); - - doOnInitializationError(TempHResult, TempError); - end; + CreateController; end else begin @@ -1965,6 +1972,7 @@ function TWVBrowserBase.ContextMenuRequestedEventHandler_Invoke(const sender : I const args : ICoreWebView2ContextMenuRequestedEventArgs): HRESULT; begin Result := S_OK; + DestroyMenuItemHandler; doOnContextMenuRequestedEvent(sender, args); end; @@ -2038,9 +2046,6 @@ function TWVBrowserBase.CreateBrowser(aHandle : THandle; aUseDefaultEnvironment // This function is asynchronous and it triggers the TWVBrowserBase.OnAfterCreated event when the browser is fully initialized function TWVBrowserBase.CreateBrowser(aHandle : THandle; const aEnvironment : ICoreWebView2Environment) : boolean; -var - TempError : wvstring; - TempHResult : HRESULT; begin Result := False; @@ -2057,21 +2062,7 @@ function TWVBrowserBase.CreateBrowser(aHandle : THandle; const aEnvironment : IC DestroyEnvironment; FUseDefaultEnvironment := True; FCoreWebView2Environment := TCoreWebView2Environment.Create(aEnvironment); - Result := FCoreWebView2Environment.CreateCoreWebView2Controller(FWindowParentHandle, self, TempHResult); - - if not(Result) then - begin - TempError := 'There was an error creating the controller. (4)' + CRLF + - 'Error code : 0x' + - {$IFDEF FPC} - UTF8Decode(inttohex(TempHResult, 8)) - {$ELSE} - inttohex(TempHResult, 8) - {$ENDIF} - + CRLF + ControllerCreationErrorToString(TempHResult); - - doOnInitializationError(TempHResult, TempError); - end; + Result := CreateController; end else Result := CreateEnvironment; @@ -2086,11 +2077,90 @@ function TWVBrowserBase.CreateWindowlessBrowser(aHandle : THandle; aUseDefaultEn Result := CreateWindowlessBrowser(aHandle, nil); end; +function TWVBrowserBase.CreateCompositionController: boolean; +var + TempError : wvstring; + TempHResult : HRESULT; + TempOptions : TCoreWebView2ControllerOptions; + TempOptionsIntf : ICoreWebView2ControllerOptions; +begin + if FCoreWebView2Environment.CreateCoreWebView2ControllerOptions(TempOptionsIntf) then + try + TempOptions := TCoreWebView2ControllerOptions.Create(TempOptionsIntf); + TempOptions.ProfileName := FProfileName; + TempOptions.IsInPrivateModeEnabled := FIsInPrivateModeEnabled; + + Result := FCoreWebView2Environment.CreateCoreWebView2CompositionControllerWithOptions(FWindowParentHandle, + TempOptions.BaseIntf, + self, + TempHResult); + finally + FreeAndNil(TempOptions); + TempOptionsIntf := nil; + end + else + Result := FCoreWebView2Environment.CreateCoreWebView2CompositionController(FWindowParentHandle, + self, + TempHResult); + + if not(Result) then + begin + TempError := 'There was an error creating the composition controller. (3)' + CRLF + + 'Error code : 0x' + + {$IFDEF FPC} + UTF8Decode(inttohex(TempHResult, 8)) + {$ELSE} + inttohex(TempHResult, 8) + {$ENDIF} + + CRLF + CompositionControllerCreationErrorToString(TempHResult); + + doOnInitializationError(TempHResult, TempError); + end; +end; + +function TWVBrowserBase.CreateController : boolean; +var + TempError : wvstring; + TempHResult : HRESULT; + TempOptions : TCoreWebView2ControllerOptions; + TempOptionsIntf : ICoreWebView2ControllerOptions; +begin + if FCoreWebView2Environment.CreateCoreWebView2ControllerOptions(TempOptionsIntf) then + try + TempOptions := TCoreWebView2ControllerOptions.Create(TempOptionsIntf); + TempOptions.ProfileName := FProfileName; + TempOptions.IsInPrivateModeEnabled := FIsInPrivateModeEnabled; + + Result := FCoreWebView2Environment.CreateCoreWebView2ControllerWithOptions(FWindowParentHandle, + TempOptions.BaseIntf, + self, + TempHResult); + finally + FreeAndNil(TempOptions); + TempOptionsIntf := nil; + end + else + Result := FCoreWebView2Environment.CreateCoreWebView2Controller(FWindowParentHandle, + self, + TempHResult); + + if not(Result) then + begin + TempError := 'There was an error creating the controller. (4)' + CRLF + + 'Error code : 0x' + + {$IFDEF FPC} + UTF8Decode(inttohex(TempHResult, 8)) + {$ELSE} + inttohex(TempHResult, 8) + {$ENDIF} + + CRLF + ControllerCreationErrorToString(TempHResult); + + doOnInitializationError(TempHResult, TempError); + end; +end; + // This function is asynchronous and it triggers the TWVBrowserBase.OnAfterCreated event when the browser is fully initialized function TWVBrowserBase.CreateWindowlessBrowser(aHandle : THandle; const aEnvironment : ICoreWebView2Environment) : boolean; -var - TempError : wvstring; - TempHResult : HRESULT; begin Result := False; @@ -2110,23 +2180,7 @@ function TWVBrowserBase.CreateWindowlessBrowser(aHandle : THandle; const aEnviro FCoreWebView2Environment := TCoreWebView2Environment.Create(aEnvironment); if FCoreWebView2Environment.SupportsCompositionController then - begin - Result := FCoreWebView2Environment.CreateCoreWebView2CompositionController(FWindowParentHandle, self, TempHResult); - - if not(Result) then - begin - TempError := 'There was an error creating the composition controller. (3)' + CRLF + - 'Error code : 0x' + - {$IFDEF FPC} - UTF8Decode(inttohex(TempHResult, 8)) - {$ELSE} - inttohex(TempHResult, 8) - {$ENDIF} - + CRLF + CompositionControllerCreationErrorToString(TempHResult); - - doOnInitializationError(TempHResult, TempError); - end; - end + Result := CreateCompositionController else doOnInitializationError(E_FAIL, 'The environment doesn' + #39 + 't support a composition controller.'); end @@ -2466,6 +2520,14 @@ function TWVBrowserBase.GetHiddenPdfToolbarItems : TWVPDFToolbarItems; Result := 0; end; +function TWVBrowserBase.GetCustomItemSelectedEventHandler : ICoreWebView2CustomItemSelectedEventHandler; +begin + if not(assigned(FMenuItemHandler)) then + FMenuItemHandler := TCoreWebView2CustomItemSelectedEventHandler.Create(self); + + Result := FMenuItemHandler; +end; + function TWVBrowserBase.GetZoomFactor: Double; begin if Initialized then @@ -2655,6 +2717,35 @@ procedure TWVBrowserBase.SetHiddenPdfToolbarItems(aValue : TWVPDFToolbarItems); FCoreWebView2Settings.HiddenPdfToolbarItems := aValue; end; +procedure TWVBrowserBase.SetProfileName(const aValue : wvstring); +const + PROFILENAME_VALID_CHARS = ['a'..'z', 'A'..'Z', '0'..'9', '#', '@', '$', '(', ')', '+', '-', '_', '~', '.', ' ']; + PROFILENAME_INVALID_ENDCHARS = ['.', ' ']; + PROFILENAME_MAX_LENGTH = 64; +var + i : integer; + TempValue : wvstring; +begin + TempValue := ''; + i := 1; + + while (i <= length(aValue)) do + begin + if CharInSet(aValue[i], PROFILENAME_VALID_CHARS) then + TempValue := TempValue + aValue[i]; + + inc(i); + end; + + TempValue := copy(TempValue, 1, PROFILENAME_MAX_LENGTH); + + while (length(TempValue) > 0) and + CharInSet(TempValue[length(TempValue)], PROFILENAME_INVALID_ENDCHARS) do + TempValue := copy(TempValue, 1, pred(length(TempValue))); + + FProfileName := TempValue; +end; + procedure TWVBrowserBase.SetBuiltInErrorPageEnabled(aValue: boolean); begin if Initialized then diff --git a/source/uWVConstants.pas b/source/uWVConstants.pas index 5037dc2..3e3bd22 100644 --- a/source/uWVConstants.pas +++ b/source/uWVConstants.pas @@ -7,13 +7,13 @@ interface const WEBVIEW2LOADERLIB_VERSION_MAJOR = 1; WEBVIEW2LOADERLIB_VERSION_MINOR = 0; - WEBVIEW2LOADERLIB_VERSION_RELEASE = 1072; - WEBVIEW2LOADERLIB_VERSION_BUILD = 54; + WEBVIEW2LOADERLIB_VERSION_RELEASE = 1210; + WEBVIEW2LOADERLIB_VERSION_BUILD = 39; - CHROMIUM_VERSION_MAJOR = 97; + CHROMIUM_VERSION_MAJOR = 101; CHROMIUM_VERSION_MINOR = 0; - CHROMIUM_VERSION_RELEASE = 1072; - CHROMIUM_VERSION_BUILD = 55; + CHROMIUM_VERSION_RELEASE = 1210; + CHROMIUM_VERSION_BUILD = 39; CRLF = #13 + #10; @@ -21,7 +21,7 @@ interface USER_DEFAULT_SCREEN_DPI = 96; {$ENDIF} - // These contants are declared in the "Windows" unit but + // These constants are declared in the "Windows" unit but // some old Delphi versions don't have them. // We have to add "WV2_" to be compatible with C++ Builder. WV2_IMAGE_FILE_MACHINE_I386 = $014C; diff --git a/source/uWVCoreWebView2.pas b/source/uWVCoreWebView2.pas index a506997..0b9d09d 100644 --- a/source/uWVCoreWebView2.pas +++ b/source/uWVCoreWebView2.pas @@ -27,6 +27,7 @@ TCoreWebView2 = class FBaseIntf10 : ICoreWebView2_10; FBaseIntf11 : ICoreWebView2_11; FBaseIntf12 : ICoreWebView2_12; + FBaseIntf13 : ICoreWebView2_13; FContainsFullScreenElementChangedToken : EventRegistrationToken; FContentLoadingToken : EventRegistrationToken; FDocumentTitleChangedToken : EventRegistrationToken; @@ -75,6 +76,7 @@ TCoreWebView2 = class function GetDefaultDownloadDialogCornerAlignment : TWVDefaultDownloadDialogCornerAlignment; function GetDefaultDownloadDialogMargin : TPoint; function GetStatusBarText : wvstring; + function GetProfile : ICoreWebView2Profile; procedure SetIsMuted(aValue : boolean); procedure SetDefaultDownloadDialogCornerAlignment(aValue : TWVDefaultDownloadDialogCornerAlignment); @@ -166,6 +168,7 @@ TCoreWebView2 = class property DefaultDownloadDialogCornerAlignment : TWVDefaultDownloadDialogCornerAlignment read GetDefaultDownloadDialogCornerAlignment write SetDefaultDownloadDialogCornerAlignment; property DefaultDownloadDialogMargin : TPoint read GetDefaultDownloadDialogMargin write SetDefaultDownloadDialogMargin; property StatusBarText : wvstring read GetStatusBarText; + property Profile : ICoreWebView2Profile read GetProfile; end; implementation @@ -191,8 +194,9 @@ constructor TCoreWebView2.Create(const aBaseIntf : ICoreWebView2); succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2_8, FBaseIntf8)) and succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2_9, FBaseIntf9)) and succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2_10, FBaseIntf10)) and - succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2_11, FBaseIntf11)) then - FBaseIntf.QueryInterface(IID_ICoreWebView2_12, FBaseIntf12); + succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2_11, FBaseIntf11)) and + succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2_12, FBaseIntf12)) then + FBaseIntf.QueryInterface(IID_ICoreWebView2_13, FBaseIntf13); end; destructor TCoreWebView2.Destroy; @@ -236,6 +240,7 @@ procedure TCoreWebView2.InitializeFields; FBaseIntf10 := nil; FBaseIntf11 := nil; FBaseIntf12 := nil; + FBaseIntf13 := nil; FDevToolsEventTokens := nil; FDevToolsEventNames := nil; @@ -1304,6 +1309,19 @@ function TCoreWebView2.GetStatusBarText : wvstring; end; end; +function TCoreWebView2.GetProfile : ICoreWebView2Profile; +var + TempResult : ICoreWebView2Profile; +begin + Result := nil; + TempResult := nil; + + if assigned(FBaseIntf13) and + succeeded(FBaseIntf13.Get_Profile(TempResult)) and + assigned(TempResult) then + Result := TempResult; +end; + procedure TCoreWebView2.SetIsMuted(aValue : boolean); begin if assigned(FBaseIntf8) then diff --git a/source/uWVCoreWebView2ContextMenuItem.pas b/source/uWVCoreWebView2ContextMenuItem.pas index a3f25bd..4b17399 100644 --- a/source/uWVCoreWebView2ContextMenuItem.pas +++ b/source/uWVCoreWebView2ContextMenuItem.pas @@ -203,18 +203,14 @@ procedure TCoreWebView2ContextMenuItem.SetIsChecked(aValue : boolean); function TCoreWebView2ContextMenuItem.AddCustomItemSelectedEvent(const aBrowserComponent : TComponent) : boolean; var - TempHandler : ICoreWebView2CustomItemSelectedEventHandler; - TempToken : EventRegistrationToken; + TempToken : EventRegistrationToken; begin Result := False; if Initialized then - try - TempHandler := TCoreWebView2CustomItemSelectedEventHandler.Create(TWVBrowserBase(aBrowserComponent)); + begin TempToken.value := 0; - Result := succeeded(FBaseIntf.add_CustomItemSelected(TempHandler, TempToken)); - finally - TempHandler := nil; + Result := succeeded(FBaseIntf.add_CustomItemSelected(TWVBrowserBase(aBrowserComponent).CustomItemSelectedEventHandler, TempToken)); end; end; diff --git a/source/uWVCoreWebView2ContextMenuItemCollection.pas b/source/uWVCoreWebView2ContextMenuItemCollection.pas index b43d77d..6b89473 100644 --- a/source/uWVCoreWebView2ContextMenuItemCollection.pas +++ b/source/uWVCoreWebView2ContextMenuItemCollection.pas @@ -21,6 +21,7 @@ TCoreWebView2ContextMenuItemCollection = class destructor Destroy; override; function RemoveValueAtIndex(index: cardinal): boolean; function InsertValueAtIndex(index: cardinal; const aValue: ICoreWebView2ContextMenuItem): boolean; + function AppendValue(const aValue: ICoreWebView2ContextMenuItem): boolean; procedure RemoveAllMenuItems; procedure RemoveMenuItem(aCommandId : integer); overload; procedure RemoveMenuItem(const aLabel : wvstring); overload; @@ -97,6 +98,12 @@ function TCoreWebView2ContextMenuItemCollection.InsertValueAtIndex(index: cardin succeeded(FBaseIntf.InsertValueAtIndex(index, aValue)); end; +function TCoreWebView2ContextMenuItemCollection.AppendValue(const aValue: ICoreWebView2ContextMenuItem): boolean; +begin + Result := Initialized and + InsertValueAtIndex(Count, aValue); +end; + procedure TCoreWebView2ContextMenuItemCollection.RemoveAllMenuItems; var i : cardinal; diff --git a/source/uWVCoreWebView2ControllerOptions.pas b/source/uWVCoreWebView2ControllerOptions.pas new file mode 100644 index 0000000..62896f6 --- /dev/null +++ b/source/uWVCoreWebView2ControllerOptions.pas @@ -0,0 +1,97 @@ +unit uWVCoreWebView2ControllerOptions; + +{$IFDEF FPC}{$MODE Delphi}{$ENDIF} + +interface + +uses + uWVTypeLibrary, uWVTypes; + +type + TCoreWebView2ControllerOptions = class + protected + FBaseIntf : ICoreWebView2ControllerOptions; + + function GetInitialized : boolean; + function GetProfileName : wvstring; + function GetIsInPrivateModeEnabled : boolean; + + procedure SetProfileName(const aValue : wvstring); + procedure SetIsInPrivateModeEnabled(aValue : boolean); + + public + constructor Create(const aBaseIntf : ICoreWebView2ControllerOptions); reintroduce; + destructor Destroy; override; + + property Initialized : boolean read GetInitialized; + property BaseIntf : ICoreWebView2ControllerOptions read FBaseIntf write FBaseIntf; + property ProfileName : wvstring read GetProfileName write SetProfileName; + property IsInPrivateModeEnabled : boolean read GetIsInPrivateModeEnabled write SetIsInPrivateModeEnabled; + end; + +implementation + +uses + {$IFDEF FPC} + ActiveX; + {$ELSE} + Winapi.ActiveX; + {$ENDIF} + +constructor TCoreWebView2ControllerOptions.Create(const aBaseIntf : ICoreWebView2ControllerOptions); +begin + inherited Create; + + FBaseIntf := aBaseIntf; +end; + +destructor TCoreWebView2ControllerOptions.Destroy; +begin + FBaseIntf := nil; + + inherited Destroy; +end; + +function TCoreWebView2ControllerOptions.GetInitialized : boolean; +begin + Result := assigned(FBaseIntf); +end; + +function TCoreWebView2ControllerOptions.GetProfileName : wvstring; +var + TempResult : PWideChar; +begin + Result := ''; + TempResult := nil; + + if Initialized and + succeeded(FBaseIntf.Get_ProfileName(TempResult)) and + (TempResult <> nil) then + begin + Result := TempResult; + CoTaskMemFree(TempResult); + end; +end; + +function TCoreWebView2ControllerOptions.GetIsInPrivateModeEnabled : boolean; +var + TempResult : integer; +begin + Result := Initialized and + succeeded(FBaseIntf.Get_IsInPrivateModeEnabled(TempResult)) and + (TempResult <> 0); +end; + +procedure TCoreWebView2ControllerOptions.SetProfileName(const aValue : wvstring); +begin + if Initialized then + FBaseIntf.Set_ProfileName(PWideChar(aValue)); +end; + +procedure TCoreWebView2ControllerOptions.SetIsInPrivateModeEnabled(aValue : boolean); +begin + if Initialized then + FBaseIntf.Set_IsInPrivateModeEnabled(ord(aValue)); +end; + +end. diff --git a/source/uWVCoreWebView2Environment.pas b/source/uWVCoreWebView2Environment.pas index 93893ee..5586a45 100644 --- a/source/uWVCoreWebView2Environment.pas +++ b/source/uWVCoreWebView2Environment.pas @@ -24,6 +24,7 @@ TCoreWebView2Environment = class FBaseIntf7 : ICoreWebView2Environment7; FBaseIntf8 : ICoreWebView2Environment8; FBaseIntf9 : ICoreWebView2Environment9; + FBaseIntf10 : ICoreWebView2Environment10; FNewBrowserVersionAvailableEventToken : EventRegistrationToken; FBrowserProcessExitedEventToken : EventRegistrationToken; FProcessInfosChangedEventToken : EventRegistrationToken; @@ -31,6 +32,7 @@ TCoreWebView2Environment = class function GetInitialized : boolean; function GetBrowserVersionInfo : wvstring; function GetSupportsCompositionController : boolean; + function GetSupportsControllerOptions : boolean; function GetUserDataFolder : wvstring; function GetProcessInfos : ICoreWebView2ProcessInfoCollection; @@ -57,11 +59,15 @@ TCoreWebView2Environment = class function GetAutomationProviderForWindow(aHandle : THandle; var aProvider : IUnknown) : boolean; function CreatePrintSettings(var aPrintSettings : ICoreWebView2PrintSettings) : boolean; function CreateContextMenuItem(const aLabel : wvstring; const aIconStream : IStream; aKind : TWVMenuItemKind; var aMenuItem : ICoreWebView2ContextMenuItem) : boolean; + function CreateCoreWebView2ControllerOptions(var aOptions: ICoreWebView2ControllerOptions): boolean; + function CreateCoreWebView2ControllerWithOptions(aParentWindow: HWND; const aOptions: ICoreWebView2ControllerOptions; const aBrowserEvents: IWVBrowserEvents; var aResult: HResult): boolean; + function CreateCoreWebView2CompositionControllerWithOptions(aParentWindow: HWND; const aOptions: ICoreWebView2ControllerOptions; const aBrowserEvents: IWVBrowserEvents; var aResult: HResult): boolean; property Initialized : boolean read GetInitialized; property BaseIntf : ICoreWebView2Environment read FBaseIntf; property BrowserVersionInfo : wvstring read GetBrowserVersionInfo; property SupportsCompositionController : boolean read GetSupportsCompositionController; + property SupportsControllerOptions : boolean read GetSupportsControllerOptions; property UserDataFolder : wvstring read GetUserDataFolder; property ProcessInfos : ICoreWebView2ProcessInfoCollection read GetProcessInfos; end; @@ -86,8 +92,9 @@ constructor TCoreWebView2Environment.Create(const aBaseIntf : ICoreWebView2Envir succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2Environment5, FBaseIntf5)) and succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2Environment6, FBaseIntf6)) and succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2Environment7, FBaseIntf7)) and - succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2Environment8, FBaseIntf8)) then - FBaseIntf.QueryInterface(IID_ICoreWebView2Environment9, FBaseIntf9); + succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2Environment8, FBaseIntf8)) and + succeeded(FBaseIntf.QueryInterface(IID_ICoreWebView2Environment9, FBaseIntf9)) then + FBaseIntf.QueryInterface(IID_ICoreWebView2Environment10, FBaseIntf10); end; destructor TCoreWebView2Environment.Destroy; @@ -102,15 +109,16 @@ destructor TCoreWebView2Environment.Destroy; procedure TCoreWebView2Environment.InitializeFields; begin - FBaseIntf := nil; - FBaseIntf2 := nil; - FBaseIntf3 := nil; - FBaseIntf4 := nil; - FBaseIntf5 := nil; - FBaseIntf6 := nil; - FBaseIntf7 := nil; - FBaseIntf8 := nil; - FBaseIntf9 := nil; + FBaseIntf := nil; + FBaseIntf2 := nil; + FBaseIntf3 := nil; + FBaseIntf4 := nil; + FBaseIntf5 := nil; + FBaseIntf6 := nil; + FBaseIntf7 := nil; + FBaseIntf8 := nil; + FBaseIntf9 := nil; + FBaseIntf10 := nil; InitializeTokens; end; @@ -232,7 +240,9 @@ function TCoreWebView2Environment.AddProcessInfosChangedBrowserEvent(const aBrow end; end; -function TCoreWebView2Environment.CreateCoreWebView2Controller(aParentWindow : THandle; const aBrowserEvents: IWVBrowserEvents; var aResult: HRESULT) : boolean; +function TCoreWebView2Environment.CreateCoreWebView2Controller( aParentWindow : THandle; + const aBrowserEvents : IWVBrowserEvents; + var aResult : HRESULT) : boolean; var TempHandler : ICoreWebView2CreateCoreWebView2ControllerCompletedHandler; begin @@ -301,7 +311,14 @@ function TCoreWebView2Environment.GetSupportsCompositionController : boolean; Result := assigned(FBaseIntf3); end; -function TCoreWebView2Environment.CreateCoreWebView2CompositionController(aParentWindow : THandle; const aBrowserEvents: IWVBrowserEvents; var aResult: HRESULT) : boolean; +function TCoreWebView2Environment.GetSupportsControllerOptions : boolean; +begin + Result := assigned(FBaseIntf10); +end; + +function TCoreWebView2Environment.CreateCoreWebView2CompositionController( aParentWindow : THandle; + const aBrowserEvents : IWVBrowserEvents; + var aResult : HRESULT) : boolean; var TempHandler : ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler; begin @@ -350,6 +367,54 @@ function TCoreWebView2Environment.CreateContextMenuItem(const aLabel : wvst assigned(aMenuItem); end; +function TCoreWebView2Environment.CreateCoreWebView2ControllerOptions(var aOptions: ICoreWebView2ControllerOptions): boolean; +begin + aOptions := nil; + Result := assigned(FBaseIntf10) and + succeeded(FBaseIntf10.CreateCoreWebView2ControllerOptions(aOptions)) and + assigned(aOptions); +end; + +function TCoreWebView2Environment.CreateCoreWebView2ControllerWithOptions( aParentWindow : HWND; + const aOptions : ICoreWebView2ControllerOptions; + const aBrowserEvents : IWVBrowserEvents; + var aResult : HResult): boolean; +var + TempHandler : ICoreWebView2CreateCoreWebView2ControllerCompletedHandler; +begin + Result := False; + aResult := E_FAIL; + + if assigned(FBaseIntf10) then + try + TempHandler := TCoreWebView2CreateCoreWebView2ControllerCompletedHandler.Create(aBrowserEvents); + aResult := FBaseIntf10.CreateCoreWebView2ControllerWithOptions(aParentWindow, aOptions, TempHandler); + Result := succeeded(aResult); + finally + TempHandler := nil; + end; +end; + +function TCoreWebView2Environment.CreateCoreWebView2CompositionControllerWithOptions( aParentWindow : HWND; + const aOptions : ICoreWebView2ControllerOptions; + const aBrowserEvents : IWVBrowserEvents; + var aResult : HResult): boolean; +var + TempHandler: ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler; +begin + Result := False; + aResult := E_FAIL; + + if assigned(FBaseIntf10) then + try + TempHandler := TCoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler.Create(aBrowserEvents); + aResult := FBaseIntf10.CreateCoreWebView2CompositionControllerWithOptions(aParentWindow, aOptions, TempHandler); + Result := succeeded(aResult); + finally + TempHandler := nil; + end; +end; + function TCoreWebView2Environment.GetUserDataFolder : wvstring; var TempString : PWideChar; diff --git a/source/uWVCoreWebView2EnvironmentOptions.pas b/source/uWVCoreWebView2EnvironmentOptions.pas index 3cfdec6..3d81403 100644 --- a/source/uWVCoreWebView2EnvironmentOptions.pas +++ b/source/uWVCoreWebView2EnvironmentOptions.pas @@ -37,7 +37,6 @@ TCoreWebView2EnvironmentOptions = class(TInterfacedObject, ICoreWebView2Enviro public constructor Create(const aAdditionalBrowserArguments, aLanguage, aTargetCompatibleBrowserVersion : wvstring; aAllowSingleSignOnUsingOSPrimaryAccount, aExclusiveUserDataFolderAccess : boolean); - destructor Destroy; override; end; implementation @@ -60,11 +59,6 @@ constructor TCoreWebView2EnvironmentOptions.Create(const aAdditionalBrowserArgum FExclusiveUserDataFolderAccess := aExclusiveUserDataFolderAccess; end; -destructor TCoreWebView2EnvironmentOptions.Destroy; -begin - inherited Destroy; -end; - function TCoreWebView2EnvironmentOptions.Get_AdditionalBrowserArguments(out value: PWideChar): HResult; stdcall; begin Result := S_OK; diff --git a/source/uWVCoreWebView2Profile.pas b/source/uWVCoreWebView2Profile.pas new file mode 100644 index 0000000..a4666ee --- /dev/null +++ b/source/uWVCoreWebView2Profile.pas @@ -0,0 +1,148 @@ +unit uWVCoreWebView2Profile; + +{$IFDEF FPC}{$MODE Delphi}{$ENDIF} + +interface + +uses + uWVTypeLibrary, uWVTypes; + +type + TCoreWebView2Profile = class + protected + FBaseIntf : ICoreWebView2Profile; + + function GetInitialized : boolean; + function GetProfileName : wvstring; + function GetIsInPrivateModeEnabled : boolean; + function GetProfilePath : wvstring; + function GetDefaultDownloadFolderPath : wvstring; + function GetPreferredColorScheme : TWVPreferredColorScheme; + + procedure SetDefaultDownloadFolderPath(const aValue : wvstring); + procedure SetPreferredColorScheme(aValue : TWVPreferredColorScheme); + + public + constructor Create(const aBaseIntf : ICoreWebView2Profile); reintroduce; + destructor Destroy; override; + + property Initialized : boolean read GetInitialized; + property BaseIntf : ICoreWebView2Profile read FBaseIntf write FBaseIntf; + property ProfileName : wvstring read GetProfileName; + property IsInPrivateModeEnabled : boolean read GetIsInPrivateModeEnabled; + property ProfilePath : wvstring read GetProfilePath; + property DefaultDownloadFolderPath : wvstring read GetDefaultDownloadFolderPath write SetDefaultDownloadFolderPath; + property PreferredColorScheme : TWVPreferredColorScheme read GetPreferredColorScheme write SetPreferredColorScheme; + end; + +implementation + +uses + {$IFDEF FPC} + ActiveX; + {$ELSE} + Winapi.ActiveX; + {$ENDIF} + +constructor TCoreWebView2Profile.Create(const aBaseIntf: ICoreWebView2Profile); +begin + inherited Create; + + FBaseIntf := aBaseIntf; +end; + +destructor TCoreWebView2Profile.Destroy; +begin + FBaseIntf := nil; + + inherited Destroy; +end; + +function TCoreWebView2Profile.GetInitialized : boolean; +begin + Result := assigned(FBaseIntf); +end; + +function TCoreWebView2Profile.GetProfileName : wvstring; +var + TempResult : PWideChar; +begin + Result := ''; + TempResult := nil; + + if Initialized and + succeeded(FBaseIntf.Get_ProfileName(TempResult)) and + (TempResult <> nil) then + begin + Result := TempResult; + CoTaskMemFree(TempResult); + end; +end; + +function TCoreWebView2Profile.GetIsInPrivateModeEnabled : boolean; +var + TempResult : integer; +begin + Result := Initialized and + succeeded(FBaseIntf.Get_IsInPrivateModeEnabled(TempResult)) and + (TempResult <> 0); +end; + +function TCoreWebView2Profile.GetProfilePath : wvstring; +var + TempResult : PWideChar; +begin + Result := ''; + TempResult := nil; + + if Initialized and + succeeded(FBaseIntf.Get_ProfilePath(TempResult)) and + (TempResult <> nil) then + begin + Result := TempResult; + CoTaskMemFree(TempResult); + end; +end; + +function TCoreWebView2Profile.GetDefaultDownloadFolderPath : wvstring; +var + TempResult : PWideChar; +begin + Result := ''; + TempResult := nil; + + if Initialized and + succeeded(FBaseIntf.Get_DefaultDownloadFolderPath(TempResult)) and + (TempResult <> nil) then + begin + Result := TempResult; + CoTaskMemFree(TempResult); + end; +end; + +function TCoreWebView2Profile.GetPreferredColorScheme : TWVPreferredColorScheme; +var + TempResult : COREWEBVIEW2_PREFERRED_COLOR_SCHEME; +begin + Result := 0; + TempResult := 0; + + if Initialized and + succeeded(FBaseIntf.Get_PreferredColorScheme(TempResult)) then + Result := TempResult; +end; + +procedure TCoreWebView2Profile.SetDefaultDownloadFolderPath(const aValue : wvstring); +begin + if Initialized then + FBaseIntf.Set_DefaultDownloadFolderPath(PWideChar(aValue)); +end; + +procedure TCoreWebView2Profile.SetPreferredColorScheme(aValue : TWVPreferredColorScheme); +begin + if Initialized then + FBaseIntf.Set_PreferredColorScheme(aValue); +end; + +end. + diff --git a/source/uWVTypeLibrary.pas b/source/uWVTypeLibrary.pas index f5934f7..f3d8915 100644 --- a/source/uWVTypeLibrary.pas +++ b/source/uWVTypeLibrary.pas @@ -28,10 +28,10 @@ // ************************************************************************ // // $Rev: 98336 $ -// File generated on 13/04/2022 10:14:53 from Type Library described below. +// File generated on 09/05/2022 20:43:26 from Type Library described below. // ************************************************************************ // -// Type Lib: T:\microsoft.web.webview2.1.0.1185.39.nupkg_FILES\WebView2.tlb (1) +// Type Lib: Z:\microsoft.web.webview2.1.0.1210.39.nupkg_FILES\WebView2.tlb (1) // LIBID: {26D34152-879F-4065-BEA2-3DAA2CFADFB8} // LCID: 0 // Helpfile: @@ -190,6 +190,7 @@ interface IID_ICoreWebView2Controller3: TGUID = '{F9614724-5D2B-41DC-AEF7-73D62B51543B}'; IID_ICoreWebView2RasterizationScaleChangedEventHandler: TGUID = '{9C98C8B1-AC53-427E-A345-3049B5524BBE}'; IID_ICoreWebView2Controller4: TGUID = '{97D418D5-A426-4E49-A151-E1A10F327D9E}'; + IID_ICoreWebView2ControllerOptions: TGUID = '{12AAE616-8CCB-44EC-BCB3-EB1831881635}'; IID_ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler: TGUID = '{02FAB84B-1428-4FB7-AD45-1B2E64736184}'; IID_ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler: TGUID = '{4E8A3389-C9D8-4BD2-B6B5-124FEE6CC14D}'; IID_ICoreWebView2DevToolsProtocolEventReceivedEventArgs2: TGUID = '{2DC4959D-1494-4393-95BA-BEA4CB9EBD1B}'; @@ -204,6 +205,7 @@ interface IID_ICoreWebView2ProcessInfoCollection: TGUID = '{402B99CD-A0CC-4FA5-B7A5-51D86A1D2339}'; IID_ICoreWebView2ProcessInfo: TGUID = '{84FA7612-3F3D-4FBF-889D-FAD000492D72}'; IID_ICoreWebView2Environment9: TGUID = '{F06F41BF-4B5A-49D8-B9F6-FA16CD29F274}'; + IID_ICoreWebView2Environment10: TGUID = '{EE0EB9DF-6F12-46CE-B53F-3F47B9C928E0}'; IID_ICoreWebView2EnvironmentOptions: TGUID = '{2FDE08A8-1E9A-4766-8C05-95A9CEB9D1C5}'; IID_ICoreWebView2EnvironmentOptions2: TGUID = '{FF85C98A-1BA7-4A6B-90C8-2B752C89E9E2}'; IID_ICoreWebView2Frame2: TGUID = '{7A6A5834-D185-4DBF-B63F-4A9BC43107D4}'; @@ -221,12 +223,14 @@ interface IID_ICoreWebView2NavigationStartingEventArgs2: TGUID = '{9086BE93-91AA-472D-A7E0-579F2BA006AD}'; IID_ICoreWebView2NewWindowRequestedEventArgs2: TGUID = '{BBC7BAED-74C6-4C92-B63A-7F5AEAE03DE3}'; IID_ICoreWebView2ProcessFailedEventArgs2: TGUID = '{4DAB9422-46FA-4C3E-A5D2-41D2071D3680}'; + IID_ICoreWebView2Profile: TGUID = '{79110AD3-CD5D-4373-8BC3-C60658F17A5F}'; IID_ICoreWebView2Settings2: TGUID = '{EE9A0F68-F46C-4E32-AC23-EF8CAC224D2A}'; IID_ICoreWebView2Settings3: TGUID = '{FDB5AB74-AF33-4854-84F0-0A631DEB5EBA}'; IID_ICoreWebView2Settings4: TGUID = '{CB56846C-4168-4D53-B04F-03B6D6796FF2}'; IID_ICoreWebView2Settings5: TGUID = '{183E7052-1D03-43A0-AB99-98E043B66B39}'; IID_ICoreWebView2Settings6: TGUID = '{11CB3ACD-9BC8-43B8-83BF-F40753714F87}'; IID_ICoreWebView2Settings7: TGUID = '{488DC902-35EF-42D2-BC7D-94B65C4BC49C}'; + IID_ICoreWebView2_13: TGUID = '{F75F09A8-667E-4983-88D6-C8773F315E84}'; // *********************************************************************// // Declaration of Enumerations defined in Type Library @@ -530,6 +534,14 @@ interface COREWEBVIEW2_PROCESS_FAILED_REASON_LAUNCH_FAILED = $00000004; COREWEBVIEW2_PROCESS_FAILED_REASON_OUT_OF_MEMORY = $00000005; +// Constants for enum COREWEBVIEW2_PREFERRED_COLOR_SCHEME +type + COREWEBVIEW2_PREFERRED_COLOR_SCHEME = TOleEnum; +const + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_AUTO = $00000000; + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_LIGHT = $00000001; + COREWEBVIEW2_PREFERRED_COLOR_SCHEME_DARK = $00000002; + // Constants for enum COREWEBVIEW2_PDF_TOOLBAR_ITEMS type COREWEBVIEW2_PDF_TOOLBAR_ITEMS = TOleEnum; @@ -538,6 +550,14 @@ interface COREWEBVIEW2_PDF_TOOLBAR_ITEMS_SAVE = $00000001; COREWEBVIEW2_PDF_TOOLBAR_ITEMS_PRINT = $00000002; COREWEBVIEW2_PDF_TOOLBAR_ITEMS_SAVE_AS = $00000004; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_ZOOM_IN = $00000008; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_ZOOM_OUT = $00000010; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_ROTATE = $00000020; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_FIT_PAGE = $00000040; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_PAGE_LAYOUT = $00000080; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_BOOKMARKS = $00000100; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_PAGE_SELECTOR = $00000200; + COREWEBVIEW2_PDF_TOOLBAR_ITEMS_SEARCH = $00000400; type @@ -657,6 +677,7 @@ interface ICoreWebView2Controller3 = interface; ICoreWebView2RasterizationScaleChangedEventHandler = interface; ICoreWebView2Controller4 = interface; + ICoreWebView2ControllerOptions = interface; ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler = interface; ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler = interface; ICoreWebView2DevToolsProtocolEventReceivedEventArgs2 = interface; @@ -671,6 +692,7 @@ interface ICoreWebView2ProcessInfoCollection = interface; ICoreWebView2ProcessInfo = interface; ICoreWebView2Environment9 = interface; + ICoreWebView2Environment10 = interface; ICoreWebView2EnvironmentOptions = interface; ICoreWebView2EnvironmentOptions2 = interface; ICoreWebView2Frame2 = interface; @@ -688,12 +710,14 @@ interface ICoreWebView2NavigationStartingEventArgs2 = interface; ICoreWebView2NewWindowRequestedEventArgs2 = interface; ICoreWebView2ProcessFailedEventArgs2 = interface; + ICoreWebView2Profile = interface; ICoreWebView2Settings2 = interface; ICoreWebView2Settings3 = interface; ICoreWebView2Settings4 = interface; ICoreWebView2Settings5 = interface; ICoreWebView2Settings6 = interface; ICoreWebView2Settings7 = interface; + ICoreWebView2_13 = interface; // *********************************************************************// // Declaration of structures, unions and aliases. @@ -2429,6 +2453,19 @@ COREWEBVIEW2_COLOR = record function Set_AllowExternalDrop(value: Integer): HResult; stdcall; end; +// *********************************************************************// +// Interface: ICoreWebView2ControllerOptions +// Flags: (0) +// GUID: {12AAE616-8CCB-44EC-BCB3-EB1831881635} +// *********************************************************************// + ICoreWebView2ControllerOptions = interface(IUnknown) + ['{12AAE616-8CCB-44EC-BCB3-EB1831881635}'] + function Get_ProfileName(out value: PWideChar): HResult; stdcall; + function Set_ProfileName(value: PWideChar): HResult; stdcall; + function Get_IsInPrivateModeEnabled(out value: Integer): HResult; stdcall; + function Set_IsInPrivateModeEnabled(value: Integer): HResult; stdcall; + end; + // *********************************************************************// // Interface: ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler // Flags: (0) @@ -2584,6 +2621,24 @@ COREWEBVIEW2_COLOR = record out item: ICoreWebView2ContextMenuItem): HResult; stdcall; end; +// *********************************************************************// +// Interface: ICoreWebView2Environment10 +// Flags: (0) +// GUID: {EE0EB9DF-6F12-46CE-B53F-3F47B9C928E0} +// *********************************************************************// + ICoreWebView2Environment10 = interface(ICoreWebView2Environment9) + ['{EE0EB9DF-6F12-46CE-B53F-3F47B9C928E0}'] + function CreateCoreWebView2ControllerOptions(out options: ICoreWebView2ControllerOptions): HResult; stdcall; + // var ParentWindow: _RemotableHandle --> ParentWindow: HWND ************** WEBVIEW4DELPHI ************** + function CreateCoreWebView2ControllerWithOptions(ParentWindow: HWND; + const options: ICoreWebView2ControllerOptions; + const handler: ICoreWebView2CreateCoreWebView2ControllerCompletedHandler): HResult; stdcall; + // var ParentWindow: _RemotableHandle --> ParentWindow: HWND ************** WEBVIEW4DELPHI ************** + function CreateCoreWebView2CompositionControllerWithOptions(ParentWindow: HWND; + const options: ICoreWebView2ControllerOptions; + const handler: ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler): HResult; stdcall; + end; + // *********************************************************************// // Interface: ICoreWebView2EnvironmentOptions // Flags: (0) @@ -2796,6 +2851,22 @@ COREWEBVIEW2_COLOR = record function Get_FrameInfosForFailedProcess(out frames: ICoreWebView2FrameInfoCollection): HResult; stdcall; end; +// *********************************************************************// +// Interface: ICoreWebView2Profile +// Flags: (0) +// GUID: {79110AD3-CD5D-4373-8BC3-C60658F17A5F} +// *********************************************************************// + ICoreWebView2Profile = interface(IUnknown) + ['{79110AD3-CD5D-4373-8BC3-C60658F17A5F}'] + function Get_ProfileName(out value: PWideChar): HResult; stdcall; + function Get_IsInPrivateModeEnabled(out value: Integer): HResult; stdcall; + function Get_ProfilePath(out value: PWideChar): HResult; stdcall; + function Get_DefaultDownloadFolderPath(out value: PWideChar): HResult; stdcall; + function Set_DefaultDownloadFolderPath(value: PWideChar): HResult; stdcall; + function Get_PreferredColorScheme(out value: COREWEBVIEW2_PREFERRED_COLOR_SCHEME): HResult; stdcall; + function Set_PreferredColorScheme(value: COREWEBVIEW2_PREFERRED_COLOR_SCHEME): HResult; stdcall; + end; + // *********************************************************************// // Interface: ICoreWebView2Settings2 // Flags: (0) @@ -2864,6 +2935,16 @@ COREWEBVIEW2_COLOR = record function Set_HiddenPdfToolbarItems(hidden_pdf_toolbar_items: COREWEBVIEW2_PDF_TOOLBAR_ITEMS): HResult; stdcall; end; +// *********************************************************************// +// Interface: ICoreWebView2_13 +// Flags: (0) +// GUID: {F75F09A8-667E-4983-88D6-C8773F315E84} +// *********************************************************************// + ICoreWebView2_13 = interface(ICoreWebView2_12) + ['{F75F09A8-667E-4983-88D6-C8773F315E84}'] + function Get_Profile(out value: ICoreWebView2Profile): HResult; stdcall; + end; + implementation uses diff --git a/source/uWVTypes.pas b/source/uWVTypes.pas index ff2cfd1..91e0c6e 100644 --- a/source/uWVTypes.pas +++ b/source/uWVTypes.pas @@ -46,6 +46,7 @@ interface TWVMenuItemKind = type COREWEBVIEW2_CONTEXT_MENU_ITEM_KIND; TWVMenuTargetKind = type COREWEBVIEW2_CONTEXT_MENU_TARGET_KIND; TWVPDFToolbarItems = type COREWEBVIEW2_PDF_TOOLBAR_ITEMS; + TWVPreferredColorScheme = type COREWEBVIEW2_PREFERRED_COLOR_SCHEME; TWV2LoaderStatus = (wvlsCreated, wvlsLoading, diff --git a/update_WebView4Delphi.json b/update_WebView4Delphi.json index 6b55271..36879a1 100644 --- a/update_WebView4Delphi.json +++ b/update_WebView4Delphi.json @@ -2,9 +2,9 @@ "UpdateLazPackages" : [ { "ForceNotify" : true, - "InternalVersion" : 53, + "InternalVersion" : 54, "Name" : "webview4delphi.lpk", - "Version" : "1.0.1185.39" + "Version" : "1.0.1210.39" } ], "UpdatePackageData" : {