From 77121dc5104a4b94dbc3b9700f35ec44ab0abc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salvador=20D=C3=ADaz=20Fau?= Date: Sun, 13 Oct 2019 18:50:23 +0200 Subject: [PATCH] Added TCEFSentinel to more demos - Check that all frames are valid before using them - Added an error page to MiniBrowser. --- .../CookieVisitor/uCookieVisitor.dfm | 5 + .../CookieVisitor/uCookieVisitor.pas | 16 +- .../CustomResourceBrowser/uMainForm.dfm | 5 + .../CustomResourceBrowser/uMainForm.pas | 43 +++- demos/Delphi_VCL/DOMVisitor/uDOMVisitor.dfm | 5 + demos/Delphi_VCL/DOMVisitor/uDOMVisitor.pas | 73 ++++--- .../EditorBrowser/uEditorBrowser.dfm | 5 + .../EditorBrowser/uEditorBrowser.pas | 18 +- .../uExternalPumpBrowser.dfm | 5 + .../uExternalPumpBrowser.pas | 25 ++- .../FullScreenBrowser/uMainForm.dfm | 5 + .../FullScreenBrowser/uMainForm.pas | 20 +- .../JavaScript/JSDialog/uJSDialogBrowser.dfm | 5 + .../JavaScript/JSDialog/uJSDialogBrowser.pas | 22 +- .../Delphi_VCL/JavaScript/JSEval/uJSEval.dfm | 5 + .../Delphi_VCL/JavaScript/JSEval/uJSEval.pas | 24 +- .../uJSExecutingFunctions.dfm | 6 + .../uJSExecutingFunctions.pas | 16 +- .../JavaScript/JSExtension/uJSExtension.dfm | 5 + .../JavaScript/JSExtension/uJSExtension.pas | 24 +- .../JSExtension/uTestExtensionHandler.pas | 49 +++-- .../uJSExtensionWithFunction.dfm | 5 + .../uJSExtensionWithFunction.pas | 16 +- .../JSExtensionWithFunction/uMyV8Handler.pas | 31 ++- .../uJSExtensionWithObjectParameter.dfm | 5 + .../uJSExtensionWithObjectParameter.pas | 17 +- .../JSRTTIExtension/uJSRTTIExtension.dfm | 5 + .../JSRTTIExtension/uJSRTTIExtension.pas | 24 +- .../JSRTTIExtension/uTestExtension.pas | 37 +++- .../JSSimpleExtension/uJSSimpleExtension.dfm | 5 + .../JSSimpleExtension/uJSSimpleExtension.pas | 16 +- .../uJSSimpleWindowBinding.dfm | 5 + .../uJSSimpleWindowBinding.pas | 16 +- .../uJSSimpleWindowBinding.dfm | 5 + .../uJSSimpleWindowBinding.pas | 16 +- .../uJSWindowBindingWithArrayBuffer.dfm | 5 + .../uJSWindowBindingWithArrayBuffer.pas | 17 +- .../uJSWindowBindingWithFunction.dfm | 5 + .../uJSWindowBindingWithFunction.pas | 17 +- .../uJSWindowBindingWithObject.dfm | 5 + .../uJSWindowBindingWithObject.pas | 16 +- .../KioskOSRBrowser/uKioskOSRBrowser.dfm | 5 + .../KioskOSRBrowser/uKioskOSRBrowser.pas | 17 +- demos/Delphi_VCL/MDIBrowser/uMainForm.dfm | 5 + demos/Delphi_VCL/MDIBrowser/uMainForm.pas | 19 +- .../MDIExternalPumpBrowser/uMainForm.dfm | 5 + .../MDIExternalPumpBrowser/uMainForm.pas | 16 +- demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas | 36 ++- .../uOSRExternalPumpBrowser.dfm | 5 + .../uOSRExternalPumpBrowser.pas | 13 +- demos/Delphi_VCL/PopupBrowser/uMainForm.dfm | 5 + demos/Delphi_VCL/PopupBrowser/uMainForm.pas | 16 +- demos/Delphi_VCL/PopupBrowser2/uMainForm.dfm | 5 + demos/Delphi_VCL/PopupBrowser2/uMainForm.pas | 16 +- .../uPostInspectorBrowser.dfm | 5 + .../uPostInspectorBrowser.pas | 16 +- .../uResponseFilterBrowser.dfm | 5 + .../uResponseFilterBrowser.pas | 20 +- .../uSchemeRegistrationBrowser.dfm | 5 + .../uSchemeRegistrationBrowser.pas | 16 +- .../SimpleBrowser/uSimpleBrowser.dfm | 5 + .../SimpleBrowser/uSimpleBrowser.pas | 20 +- .../SimpleBrowser2/uSimpleBrowser2.pas | 3 +- .../uSimpleExternalPumpBrowser.dfm | 5 + .../uSimpleExternalPumpBrowser.pas | 15 +- .../SimpleOSRBrowser/uSimpleOSRBrowser.dfm | 5 + .../SimpleOSRBrowser/uSimpleOSRBrowser.pas | 17 +- .../Delphi_VCL/SubProcess/uSimpleBrowser.dfm | 5 + .../Delphi_VCL/SubProcess/uSimpleBrowser.pas | 18 +- demos/Delphi_VCL/TabbedBrowser/uMainForm.pas | 4 +- demos/Delphi_VCL/ToolBoxBrowser/uMainForm.pas | 3 +- demos/Delphi_VCL/URLRequest/uURLRequest.dfm | 5 + demos/Delphi_VCL/URLRequest/uURLRequest.pas | 22 +- demos/Lazarus/DOMVisitor/uDOMVisitor.pas | 41 ++-- .../Lazarus/EditorBrowser/uEditorBrowser.pas | 4 +- demos/Lazarus/JavaScript/JSEval/uJSEval.pas | 11 +- .../JavaScript/JSExtension/uJSExtension.pas | 8 +- .../JSExtension/uTestExtensionHandler.pas | 51 +++-- .../JSExtensionWithFunction/uMyV8Handler.pas | 33 ++- demos/Lazarus/MiniBrowser/uMiniBrowser.pas | 14 +- demos/Lazarus/PopupBrowser2/PopupBrowser2.lps | 96 ++++---- demos/Lazarus/PopupBrowser2/uMainForm.lfm | 8 +- demos/Lazarus/PopupBrowser2/uMainForm.pas | 5 +- .../uPostInspectorBrowser.pas | 4 +- source/uCEFChromium.pas | 206 +++++++++--------- source/uCEFFMXChromium.pas | 56 ++--- source/uCEFMiscFunctions.pas | 24 ++ source/uCEFRequestHandler.pas | 48 ++-- update_CEF4Delphi.json | 4 +- 89 files changed, 1097 insertions(+), 522 deletions(-) diff --git a/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.dfm b/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.dfm index 88222ee7..7f422052 100644 --- a/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.dfm +++ b/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.dfm @@ -82,4 +82,9 @@ object CookieVisitorFrm: TCookieVisitorFrm Left = 32 Top = 280 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 336 + end end diff --git a/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.pas b/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.pas index 9b885b31..07143090 100644 --- a/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.pas +++ b/demos/Delphi_VCL/CookieVisitor/uCookieVisitor.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFCookieManager, uCEFCookieVisitor, uCEFWinControl; + uCEFCookieManager, uCEFCookieVisitor, uCEFWinControl, uCEFSentinel; const MINIBROWSER_SHOWCOOKIES = WM_APP + $101; @@ -68,6 +68,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); @@ -96,6 +97,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); private procedure WMMove(var aMessage : TWMMove); message WM_MOVE; @@ -141,7 +143,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -229,6 +232,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TCookieVisitorFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TCookieVisitorFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -236,8 +245,7 @@ end; procedure TCookieVisitorFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TCookieVisitorFrm.Chromium1BeforeContextMenu(Sender: TObject; diff --git a/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.dfm b/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.dfm index 76d85e3c..9494b165 100644 --- a/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.dfm +++ b/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.dfm @@ -72,4 +72,9 @@ object MainForm: TMainForm Left = 48 Top = 240 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 48 + Top = 304 + end end diff --git a/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.pas b/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.pas index cd143261..11884096 100644 --- a/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/CustomResourceBrowser/uMainForm.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFChromiumWindow, uCEFInterfaces, uCustomResourceHandler, - uCEFConstants, uCEFTypes, uCEFWinControl; + uCEFConstants, uCEFTypes, uCEFWinControl, uCEFSentinel; type TMainForm = class(TForm) @@ -59,6 +59,7 @@ type Edit1: TEdit; Button1: TButton; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormCreate(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); @@ -69,6 +70,7 @@ type procedure ChromiumWindow1Close(Sender: TObject); procedure ChromiumWindow1BeforeClose(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); private procedure WMMove(var aMessage : TWMMove); message WM_MOVE; @@ -86,6 +88,7 @@ type procedure Chromium_OnAfterCreated(Sender: TObject); procedure Chromium_OnGetResourceHandler(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; var aResourceHandler : ICefResourceHandler); procedure Chromium_OnBeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean); + procedure Chromium_OnGetResourceRequestHandler(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; is_navigation, is_download: boolean; const request_initiator: ustring; var disable_default_handling: boolean; var aExternalResourceRequestHandler : ICefResourceRequestHandler; var aUseInternalResourceRequestHandler : boolean); public { Public declarations } @@ -107,7 +110,8 @@ uses // ================= // 1. The FormCloseQuery event sets CanClose to False and calls TChromiumWindow.CloseBrowser, which triggers the TChromiumWindow.OnClose event. // 2. The TChromiumWindow.OnClose event calls TChromiumWindow.DestroyChildWindow which triggers the TChromiumWindow.OnBeforeClose event. -// 3. TChromiumWindow.OnBeforeClose sets FCanClose to True and closes the form. +// 3. TChromiumWindow.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -157,9 +161,10 @@ end; procedure TMainForm.FormShow(Sender: TObject); begin - ChromiumWindow1.OnAfterCreated := Chromium_OnAfterCreated; - ChromiumWindow1.ChromiumBrowser.OnGetResourceHandler := Chromium_OnGetResourceHandler; - ChromiumWindow1.ChromiumBrowser.OnBeforePopup := Chromium_OnBeforePopup; + ChromiumWindow1.OnAfterCreated := Chromium_OnAfterCreated; + ChromiumWindow1.ChromiumBrowser.OnGetResourceHandler := Chromium_OnGetResourceHandler; + ChromiumWindow1.ChromiumBrowser.OnGetResourceRequestHandler := Chromium_OnGetResourceRequestHandler; + ChromiumWindow1.ChromiumBrowser.OnBeforePopup := Chromium_OnBeforePopup; // GlobalCEFApp.GlobalContextInitialized has to be TRUE before creating any browser // If it's not initialized yet, we use a simple timer to create the browser later. @@ -173,20 +178,21 @@ begin Timer1.Enabled := True; end; -procedure TMainForm.ChromiumWindow1BeforeClose(Sender: TObject); +procedure TMainForm.CEFSentinel1Close(Sender: TObject); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); end; +procedure TMainForm.ChromiumWindow1BeforeClose(Sender: TObject); +begin + CEFSentinel1.Start; +end; + procedure TMainForm.ChromiumWindow1Close(Sender: TObject); begin // DestroyChildWindow will destroy the child window created by CEF at the top of the Z order. - if not(ChromiumWindow1.DestroyChildWindow) then - begin - FCanClose := True; - Close; - end; + if not(ChromiumWindow1.DestroyChildWindow) then CEFSentinel1.Start; end; procedure TMainForm.Chromium_OnAfterCreated(Sender: TObject); @@ -223,6 +229,21 @@ begin Result := (targetDisposition in [WOD_NEW_FOREGROUND_TAB, WOD_NEW_BACKGROUND_TAB, WOD_NEW_POPUP, WOD_NEW_WINDOW]); end; +procedure TMainForm.Chromium_OnGetResourceRequestHandler( Sender : TObject; + const browser : ICefBrowser; + const frame : ICefFrame; + const request : ICefRequest; + is_navigation : boolean; + is_download : boolean; + const request_initiator : ustring; + var disable_default_handling : boolean; + var aExternalResourceRequestHandler : ICefResourceRequestHandler; + var aUseInternalResourceRequestHandler : boolean); +begin + disable_default_handling := True; + aUseInternalResourceRequestHandler := True; +end; + procedure TMainForm.WMMove(var aMessage : TWMMove); begin inherited; diff --git a/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.dfm b/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.dfm index 53e478d0..559f9b73 100644 --- a/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.dfm +++ b/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.dfm @@ -110,4 +110,9 @@ object DOMVisitorFrm: TDOMVisitorFrm Left = 16 Top = 96 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 16 + Top = 160 + end end diff --git a/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.pas b/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.pas index d83fae57..1f88efed 100644 --- a/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.pas +++ b/demos/Delphi_VCL/DOMVisitor/uDOMVisitor.pas @@ -51,7 +51,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const MINIBROWSER_VISITDOM_PARTIAL = WM_APP + $101; @@ -81,6 +81,7 @@ type Panel1: TPanel; GoBtn: TButton; VisitDOMBtn: TButton; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; @@ -111,6 +112,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); private { Private declarations } protected @@ -165,7 +167,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure SimpleDOMIteration(const aDocument: ICefDomDocument); var @@ -226,7 +229,7 @@ end; procedure DOMVisitor_OnDocAvailable(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument); var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; begin // This function is called from a different process. // document is only valid inside this function. @@ -247,21 +250,33 @@ begin // Sending back some custom results to the browser process // Notice that the DOMVISITOR_MSGNAME_PARTIAL message name needs to be recognized in // Chromium1ProcessMessageReceived - msg := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_PARTIAL); - msg.ArgumentList.SetString(0, 'document.Title : ' + document.Title); - frame.SendProcessMessage(PID_BROWSER, msg); + try + TempMessage := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_PARTIAL); + TempMessage.ArgumentList.SetString(0, 'document.Title : ' + document.Title); + + if (frame <> nil) and frame.IsValid then + frame.SendProcessMessage(PID_BROWSER, TempMessage); + finally + TempMessage := nil; + end; end; procedure DOMVisitor_OnDocAvailableFullMarkup(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument); var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; begin // Sending back some custom results to the browser process // Notice that the DOMVISITOR_MSGNAME_FULL message name needs to be recognized in // Chromium1ProcessMessageReceived - msg := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_FULL); - msg.ArgumentList.SetString(0, document.Body.AsMarkup); - frame.SendProcessMessage(PID_BROWSER, msg); + try + TempMessage := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_FULL); + TempMessage.ArgumentList.SetString(0, document.Body.AsMarkup); + + if (frame <> nil) and frame.IsValid then + frame.SendProcessMessage(PID_BROWSER, TempMessage); + finally + TempMessage := nil; + end; end; procedure DOMVisitor_GetFrameIDs(const browser: ICefBrowser; const frame : ICefFrame); @@ -285,9 +300,15 @@ begin inc(i); end; - TempMsg := TCefProcessMessageRef.New(FRAMEIDS_MSGNAME); - TempMsg.ArgumentList.SetString(0, TempString); - frame.SendProcessMessage(PID_BROWSER, TempMsg); + try + TempMsg := TCefProcessMessageRef.New(FRAMEIDS_MSGNAME); + TempMsg.ArgumentList.SetString(0, TempString); + + if (frame <> nil) and frame.IsValid then + frame.SendProcessMessage(PID_BROWSER, TempMsg); + finally + TempMsg := nil; + end; end; end; @@ -297,7 +318,6 @@ procedure GlobalCEFApp_OnProcessMessageReceived(const browser : ICefBrowse const message : ICefProcessMessage; var aHandled : boolean); var - TempFrame : ICefFrame; TempVisitor : TCefFastDomVisitor2; begin aHandled := False; @@ -306,12 +326,10 @@ begin begin if (message.name = RETRIEVEDOM_MSGNAME_PARTIAL) then begin - TempFrame := browser.MainFrame; - - if (TempFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin - TempVisitor := TCefFastDomVisitor2.Create(browser, TempFrame, DOMVisitor_OnDocAvailable); - TempFrame.VisitDom(TempVisitor); + TempVisitor := TCefFastDomVisitor2.Create(browser, frame, DOMVisitor_OnDocAvailable); + frame.VisitDom(TempVisitor); end; aHandled := True; @@ -319,12 +337,10 @@ begin else if (message.name = RETRIEVEDOM_MSGNAME_FULL) then begin - TempFrame := browser.MainFrame; - - if (TempFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin - TempVisitor := TCefFastDomVisitor2.Create(browser, TempFrame, DOMVisitor_OnDocAvailableFullMarkup); - TempFrame.VisitDom(TempVisitor); + TempVisitor := TCefFastDomVisitor2.Create(browser, frame, DOMVisitor_OnDocAvailableFullMarkup); + frame.VisitDom(TempVisitor); end; aHandled := True; @@ -351,6 +367,12 @@ begin GlobalCEFApp.LogSeverity := LOGSEVERITY_INFO; end; +procedure TDOMVisitorFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TDOMVisitorFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -359,8 +381,7 @@ end; procedure TDOMVisitorFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TDOMVisitorFrm.Chromium1BeforeContextMenu(Sender: TObject; diff --git a/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.dfm b/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.dfm index 27380698..086fa2b6 100644 --- a/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.dfm +++ b/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.dfm @@ -1122,4 +1122,9 @@ object Form1: TForm1 Left = 128 Top = 200 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 256 + end end diff --git a/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.pas b/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.pas index 97955bd7..e5f5b371 100644 --- a/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.pas +++ b/demos/Delphi_VCL/EditorBrowser/uEditorBrowser.pas @@ -52,7 +52,7 @@ uses ImageList, ImgList, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TForm1 = class(TForm) @@ -91,6 +91,7 @@ type RemoveFormatBtn: TToolButton; OutdentBtn: TToolButton; Separator7: TToolButton; + CEFSentinel1: TCEFSentinel; procedure Timer1Timer(Sender: TObject); @@ -124,6 +125,7 @@ type procedure FillColorBtnClick(Sender: TObject); procedure RemoveFormatBtnClick(Sender: TObject); procedure OutdentBtnClick(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely @@ -170,7 +172,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -226,6 +229,12 @@ begin if not(Chromium1.CreateBrowser(CEFWindowParent1)) then Timer1.Enabled := True; end; +procedure TForm1.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TForm1.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin // Now the browser is fully initialized we can send a message to the main form to load the initial web page. @@ -235,8 +244,7 @@ end; procedure TForm1.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TForm1.Chromium1Close(Sender: TObject; @@ -250,7 +258,7 @@ procedure TForm1.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer); begin - if (frame <> nil) and not(frame.isMain) then exit; + if (frame <> nil) and (not(frame.IsValid) or not(frame.isMain)) then exit; // Enable the "designMode" for all loaded files to edit them EnableDesignMode; diff --git a/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.dfm b/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.dfm index 8f052feb..e11f474c 100644 --- a/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.dfm +++ b/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.dfm @@ -99,4 +99,9 @@ object ExternalPumpBrowserFrm: TExternalPumpBrowserFrm Left = 56 Top = 152 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 224 + end end diff --git a/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.pas b/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.pas index dc7e219e..545de05b 100644 --- a/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.pas +++ b/demos/Delphi_VCL/ExternalPumpBrowser/uExternalPumpBrowser.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFTypes, uCEFConstants, uCEFInterfaces, uCEFWorkScheduler, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TExternalPumpBrowserFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; URLCbx: TComboBox; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); @@ -79,6 +80,7 @@ type var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean); + procedure CEFSentinel1Close(Sender: TObject); private FCanClose : boolean; @@ -110,6 +112,13 @@ uses // This demo has a simple browser with a TChromium + TCEFWindowParent combination // It was necessary to destroy the browser following the destruction sequence described in the MDIBrowser demo. +// Destruction steps +// ================= +// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. +// 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. + procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); begin if (GlobalCEFWorkScheduler <> nil) then GlobalCEFWorkScheduler.ScheduleMessagePumpWork(aDelayMS); @@ -142,9 +151,8 @@ begin if not(FClosing) then begin - FClosing := True; - Visible := False; - AddressPnl.Enabled := False; + FClosing := True; + Visible := False; Chromium1.CloseBrowser(True); end; end; @@ -156,6 +164,12 @@ begin if not(Chromium1.CreateBrowser(CEFWindowParent1, '')) then Timer1.Enabled := True; end; +procedure TExternalPumpBrowserFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TExternalPumpBrowserFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -163,8 +177,7 @@ end; procedure TExternalPumpBrowserFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TExternalPumpBrowserFrm.Chromium1BeforePopup(Sender: TObject; diff --git a/demos/Delphi_VCL/FullScreenBrowser/uMainForm.dfm b/demos/Delphi_VCL/FullScreenBrowser/uMainForm.dfm index ae4f530f..6cdeddbe 100644 --- a/demos/Delphi_VCL/FullScreenBrowser/uMainForm.dfm +++ b/demos/Delphi_VCL/FullScreenBrowser/uMainForm.dfm @@ -45,4 +45,9 @@ object MainForm: TMainForm Left = 272 Top = 120 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 328 + Top = 120 + end end diff --git a/demos/Delphi_VCL/FullScreenBrowser/uMainForm.pas b/demos/Delphi_VCL/FullScreenBrowser/uMainForm.pas index 4691edd2..979e9924 100644 --- a/demos/Delphi_VCL/FullScreenBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/FullScreenBrowser/uMainForm.pas @@ -49,13 +49,14 @@ uses Controls, Forms, Dialogs, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFTypes, uCEFConstants, - Vcl.ExtCtrls, uCEFWinControl; + Vcl.ExtCtrls, uCEFWinControl, uCEFSentinel; type TMainForm = class(TForm) CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure Chromium1PreKeyEvent(Sender: TObject; const browser: ICefBrowser; const event: PCefKeyEvent; osEvent: PMsg; out isKeyboardShortcut, Result: Boolean); @@ -80,6 +81,7 @@ type const browser: ICefBrowser); procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction); + procedure CEFSentinel1Close(Sender: TObject); private { Private declarations } protected @@ -112,6 +114,13 @@ implementation uses uCEFApplication; +// Destruction steps +// ================= +// 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. +// 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. + procedure CreateGlobalCEFApp; begin GlobalCEFApp := TCefApplication.Create; @@ -157,6 +166,12 @@ begin if (TempKeyMsg.CharCode = VK_ESCAPE) then aHandled := True; end; +procedure TMainForm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TMainForm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -164,8 +179,7 @@ end; procedure TMainForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TMainForm.Chromium1BeforePopup(Sender: TObject; diff --git a/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.dfm b/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.dfm index c837e2fc..fed2877c 100644 --- a/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.dfm +++ b/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.dfm @@ -72,4 +72,9 @@ object JSDialogBrowserFrm: TJSDialogBrowserFrm Left = 56 Top = 88 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 152 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.pas b/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.pas index ce262982..23a86896 100644 --- a/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.pas +++ b/demos/Delphi_VCL/JavaScript/JSDialog/uJSDialogBrowser.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFChromiumWindow, uCEFInterfaces, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const CEFBROWSER_SHOWJSDIALOG = WM_APP + $101; @@ -62,6 +62,7 @@ type AddressEdt: TEdit; GoBtn: TButton; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure ChromiumWindow1AfterCreated(Sender: TObject); @@ -71,6 +72,7 @@ type procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure ChromiumWindow1Close(Sender: TObject); procedure ChromiumWindow1BeforeClose(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); protected FJSDialogInfoCS : TCriticalSection; @@ -114,7 +116,8 @@ uses // ================= // 1. The FormCloseQuery event sets CanClose to False and calls TChromiumWindow.CloseBrowser, which triggers the TChromiumWindow.OnClose event. // 2. The TChromiumWindow.OnClose event calls TChromiumWindow.DestroyChildWindow which triggers the TChromiumWindow.OnBeforeClose event. -// 3. TChromiumWindow.OnBeforeClose sets FCanClose to True and closes the form. +// 3. TChromiumWindow.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -164,6 +167,12 @@ begin if not(ChromiumWindow1.CreateBrowser) then Timer1.Enabled := True; end; +procedure TJSDialogBrowserFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSDialogBrowserFrm.ChromiumWindow1AfterCreated(Sender: TObject); begin Caption := 'JS Dialog Browser'; @@ -248,18 +257,13 @@ end; procedure TJSDialogBrowserFrm.ChromiumWindow1BeforeClose(Sender: TObject); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSDialogBrowserFrm.ChromiumWindow1Close(Sender: TObject); begin // DestroyChildWindow will destroy the child window created by CEF at the top of the Z order. - if not(ChromiumWindow1.DestroyChildWindow) then - begin - FCanClose := True; - Close; - end; + if not(ChromiumWindow1.DestroyChildWindow) then CEFSentinel1.Start; end; procedure TJSDialogBrowserFrm.Chromium_OnBeforePopup(Sender: TObject; diff --git a/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.dfm b/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.dfm index 185ea0f1..b64f2335 100644 --- a/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.dfm +++ b/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.dfm @@ -79,4 +79,9 @@ object JSEvalFrm: TJSEvalFrm Left = 16 Top = 96 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 16 + Top = 160 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.pas b/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.pas index ecade24c..53ae5da4 100644 --- a/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.pas +++ b/demos/Delphi_VCL/JavaScript/JSEval/uJSEval.pas @@ -51,7 +51,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd, EncdDecd, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const MINIBROWSER_SHOWTEXTVIEWER = WM_APP + $101; @@ -74,6 +74,7 @@ type GoBtn: TButton; AddressEdt: TEdit; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); @@ -102,6 +103,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); private { Private declarations } @@ -178,8 +180,14 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. +procedure TJSEvalFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; procedure TJSEvalFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin @@ -189,8 +197,7 @@ end; procedure TJSEvalFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSEvalFrm.Chromium1BeforeContextMenu(Sender : TObject; @@ -435,7 +442,8 @@ begin end; end; - pFrame.SendProcessMessage(PID_BROWSER, pAnswer); + if (pFrame <> nil) and pFrame.IsValid then + pFrame.SendProcessMessage(PID_BROWSER, pAnswer); end; procedure ParseBinaryValue(const pBrowser : ICefBrowser; const pFrame : ICefFrame; const aBinaryValue : ICefBinaryValue); @@ -464,7 +472,7 @@ begin TempString := 'Image size : ' + inttostr(TempSize) + #13 + #10 + 'Encoded image : ' + EncodeBase64(TempPointer, TempSize); - if pAnswer.ArgumentList.SetString(0, TempString) then + if (pFrame <> nil) and pFrame.IsValid and pAnswer.ArgumentList.SetString(0, TempString) then pFrame.SendProcessMessage(PID_BROWSER, pAnswer); end; end; @@ -497,9 +505,9 @@ begin begin TempScript := pMessage.ArgumentList.GetString(0); - if (length(TempScript) > 0) then + if (length(TempScript) > 0) and (pFrame <> nil) and pFrame.IsValid then begin - pV8Context := pBrowser.MainFrame.GetV8Context; + pV8Context := pFrame.GetV8Context; if pV8Context.Enter then begin diff --git a/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.dfm b/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.dfm index 826440ec..d5d809ba 100644 --- a/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.dfm +++ b/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.dfm @@ -79,4 +79,10 @@ object JSExecutingFunctionsFrm: TJSExecutingFunctionsFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + MinInitDelayMs = 2000 + OnClose = CEFSentinel1Close + Left = 32 + Top = 360 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.pas b/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.pas index 44622364..eb4301a1 100644 --- a/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.pas +++ b/demos/Delphi_VCL/JavaScript/JSExecutingFunctions/uJSExecutingFunctions.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, - uCEFConstants, uCEFv8Value, uCEFWinControl; + uCEFConstants, uCEFv8Value, uCEFWinControl, uCEFSentinel; const JSDEMO_CONTEXTMENU_EXECFUNCTION = MENU_ID_USER_FIRST + 1; @@ -65,6 +65,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -91,6 +92,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -134,7 +136,8 @@ implementation // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. uses uCEFProcessMessage, uMyV8Handler; @@ -181,6 +184,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSExecutingFunctionsFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSExecutingFunctionsFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -189,8 +198,7 @@ end; procedure TJSExecutingFunctionsFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSExecutingFunctionsFrm.Chromium1BeforeContextMenu( diff --git a/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.dfm b/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.dfm index 7cbbd875..de625531 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.dfm +++ b/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.dfm @@ -89,4 +89,9 @@ object JSExtensionFrm: TJSExtensionFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 360 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.pas b/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.pas index f2a9f659..fec856df 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.pas +++ b/demos/Delphi_VCL/JavaScript/JSExtension/uJSExtension.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const MINIBROWSER_SHOWTEXTVIEWER = WM_APP + $100; @@ -71,6 +71,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1BeforeContextMenu(Sender: TObject; @@ -99,6 +100,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected FText : string; // Variables to control when can we destroy the form safely @@ -273,7 +275,8 @@ uses // the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 // in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnWebKitInitialized; @@ -326,6 +329,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSExtensionFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSExtensionFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -334,8 +343,7 @@ end; procedure TJSExtensionFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSExtensionFrm.Chromium1BeforeContextMenu(Sender: TObject; @@ -382,7 +390,7 @@ begin case commandId of MINIBROWSER_CONTEXTMENU_SETJSEVENT : - if (browser <> nil) and (browser.MainFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempJSCode := 'document.body.addEventListener("mouseover", function(evt){'+ 'function getpath(n){'+ @@ -393,16 +401,16 @@ begin 'myextension.mouseover(getpath(evt.target))}'+ ')'; - browser.MainFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); + frame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); end; MINIBROWSER_CONTEXTMENU_JSVISITDOM : - if (browser <> nil) and (browser.MainFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempJSCode := 'var testhtml = document.body.innerHTML; ' + 'myextension.sendresulttobrowser(testhtml, ' + quotedstr(CUSTOMNAME_MESSAGE_NAME) + ');'; - browser.MainFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); + frame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); end; MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS : diff --git a/demos/Delphi_VCL/JavaScript/JSExtension/uTestExtensionHandler.pas b/demos/Delphi_VCL/JavaScript/JSExtension/uTestExtensionHandler.pas index b47473b7..4a19f534 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtension/uTestExtensionHandler.pas +++ b/demos/Delphi_VCL/JavaScript/JSExtension/uTestExtensionHandler.pas @@ -67,35 +67,46 @@ function TTestExtensionHandler.Execute(const name : ustring; var retval : ICefv8Value; var exception : ustring): Boolean; var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; + TempFrame : ICefFrame; begin - if (name = 'mouseover') then - begin - if (length(arguments) > 0) and arguments[0].IsString then - begin - msg := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME); - msg.ArgumentList.SetString(0, arguments[0].GetStringValue); + Result := False; - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); - end; - - Result := True; - end - else - if (name = 'sendresulttobrowser') then + try + if (name = 'mouseover') then begin - if (length(arguments) > 1) and arguments[0].IsString and arguments[1].IsString then + if (length(arguments) > 0) and arguments[0].IsString then begin - msg := TCefProcessMessageRef.New(arguments[1].GetStringValue); - msg.ArgumentList.SetString(0, arguments[0].GetStringValue); + TempMessage := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME); + TempMessage.ArgumentList.SetString(0, arguments[0].GetStringValue); - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); end; Result := True; end else - Result := False; + if (name = 'sendresulttobrowser') then + begin + if (length(arguments) > 1) and arguments[0].IsString and arguments[1].IsString then + begin + TempMessage := TCefProcessMessageRef.New(arguments[1].GetStringValue); + TempMessage.ArgumentList.SetString(0, arguments[0].GetStringValue); + + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); + end; + + Result := True; + end; + finally + TempMessage := nil; + end; end; end. diff --git a/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.dfm b/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.dfm index d668e4cf..f58c6095 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.dfm +++ b/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.dfm @@ -87,4 +87,9 @@ object JSExtensionWithFunctionFrm: TJSExtensionWithFunctionFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 352 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.pas b/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.pas index 3f823515..ddcefb58 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.pas +++ b/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uJSExtensionWithFunction.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TJSExtensionWithFunctionFrm = class(TForm) @@ -61,6 +61,7 @@ type Chromium1: TChromium; Timer1: TTimer; StatusBar1: TStatusBar; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -82,6 +83,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -121,7 +123,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. {$IFDEF DELPHI12_UP}procedure {$ELSE}class procedure TJSSimpleExtensionFrm.{$ENDIF}GlobalCEFApp_OnWebKitInitializedEvent; @@ -159,6 +162,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSExtensionWithFunctionFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSExtensionWithFunctionFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -167,8 +176,7 @@ end; procedure TJSExtensionWithFunctionFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSExtensionWithFunctionFrm.Chromium1BeforePopup(Sender: TObject; diff --git a/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas b/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas index c4b60a99..13f26591 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas +++ b/demos/Delphi_VCL/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas @@ -61,19 +61,28 @@ function TMyV8Handler.Execute(const name : ustring; var retval : ICefv8Value; var exception : ustring): Boolean; var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; + TempFrame : ICefFrame; begin - if (name = 'myfunc') then - begin - msg := TCefProcessMessageRef.New(TEST_MESSAGE_NAME); - msg.ArgumentList.SetString(0, 'Message received!'); - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); + Result := False; - retval := TCefv8ValueRef.NewString('My Value!'); - Result := True; - end - else - Result := False; + try + if (name = 'myfunc') then + begin + TempMessage := TCefProcessMessageRef.New(TEST_MESSAGE_NAME); + TempMessage.ArgumentList.SetString(0, 'Message received!'); + + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); + + retval := TCefv8ValueRef.NewString('My Value!'); + Result := True; + end; + finally + TempMessage := nil; + end; end; diff --git a/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.dfm b/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.dfm index 19e1706f..0277d1b0 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.dfm +++ b/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.dfm @@ -76,4 +76,9 @@ object JSExtensionWithObjectParameterFrm: TJSExtensionWithObjectParameterFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 352 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.pas b/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.pas index c9bc17d5..1ff9d835 100644 --- a/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.pas +++ b/demos/Delphi_VCL/JavaScript/JSExtensionWithObjectParameter/uJSExtensionWithObjectParameter.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TJSExtensionWithObjectParameterFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -120,7 +122,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. {$IFDEF DELPHI12_UP}procedure {$ELSE}class procedure TJSSimpleExtensionFrm.{$ENDIF}GlobalCEFApp_OnWebKitInitializedEvent; @@ -162,6 +165,13 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSExtensionWithObjectParameterFrm.CEFSentinel1Close( + Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSExtensionWithObjectParameterFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -170,8 +180,7 @@ end; procedure TJSExtensionWithObjectParameterFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSExtensionWithObjectParameterFrm.Chromium1BeforePopup( diff --git a/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.dfm b/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.dfm index b9d4b1e0..7156bab3 100644 --- a/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.dfm +++ b/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.dfm @@ -89,4 +89,9 @@ object JSRTTIExtensionFrm: TJSRTTIExtensionFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 352 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.pas b/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.pas index a119e00c..2e994476 100644 --- a/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.pas +++ b/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uJSRTTIExtension.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const MINIBROWSER_SHOWTEXTVIEWER = WM_APP + $100; @@ -72,6 +72,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1BeforeContextMenu(Sender: TObject; @@ -100,6 +101,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected FText : string; // Variables to control when can we destroy the form safely @@ -155,7 +157,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnWebKitInitialized; begin @@ -184,6 +187,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSRTTIExtensionFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSRTTIExtensionFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -228,7 +237,7 @@ begin // Here is the code executed for each custom context menu entry case commandId of MINIBROWSER_CONTEXTMENU_SETJSEVENT : - if (browser <> nil) and (browser.MainFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempJSCode := 'document.body.addEventListener("mouseover", function(evt){'+ 'function getpath(n){'+ @@ -239,17 +248,17 @@ begin 'myextension.mouseover(getpath(evt.target))}'+ // This is the call from JavaScript to the extension with DELPHI code in uTestExtension.pas ')'; - browser.MainFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); + frame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); end; MINIBROWSER_CONTEXTMENU_JSVISITDOM : - if (browser <> nil) and (browser.MainFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin // This is the call from JavaScript to the extension with DELPHI code in uTestExtension.pas TempJSCode := 'var testhtml = document.body.innerHTML; ' + 'myextension.sendresulttobrowser(testhtml, ' + quotedstr(CUSTOMNAME_MESSAGE_NAME) + ');'; - browser.MainFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); + frame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); end; MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS : @@ -342,8 +351,7 @@ end; procedure TJSRTTIExtensionFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSRTTIExtensionFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uTestExtension.pas b/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uTestExtension.pas index 720e368e..aa25ab33 100644 --- a/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uTestExtension.pas +++ b/demos/Delphi_VCL/JavaScript/JSRTTIExtension/uTestExtension.pas @@ -63,24 +63,41 @@ uses class procedure TTestExtension.mouseover(const data: string); var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; + TempFrame : ICefFrame; begin - msg := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME); - msg.ArgumentList.SetString(0, data); + try + TempMessage := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME); + TempMessage.ArgumentList.SetString(0, data); - // Sending a message back to the browser. It'll be received in the TChromium.OnProcessMessageReceived event. - // TCefv8ContextRef.Current returns the v8 context for the frame that is currently executing Javascript. - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); + // Sending a message back to the browser. It'll be received in the TChromium.OnProcessMessageReceived event. + // TCefv8ContextRef.Current returns the v8 context for the frame that is currently executing Javascript. + + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); + finally + TempMessage := nil; + end; end; class procedure TTestExtension.sendresulttobrowser(const msgtext, msgname : string); var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; + TempFrame : ICefFrame; begin - msg := TCefProcessMessageRef.New(msgname); - msg.ArgumentList.SetString(0, msgtext); + try + TempMessage := TCefProcessMessageRef.New(msgname); + TempMessage.ArgumentList.SetString(0, msgtext); - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); + finally + TempMessage := nil; + end; end; end. diff --git a/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.dfm b/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.dfm index 3435c774..82d23110 100644 --- a/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.dfm +++ b/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.dfm @@ -76,4 +76,9 @@ object JSSimpleExtensionFrm: TJSSimpleExtensionFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 344 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.pas b/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.pas index 64fee3de..a87a8b70 100644 --- a/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.pas +++ b/demos/Delphi_VCL/JavaScript/JSSimpleExtension/uJSSimpleExtension.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TJSSimpleExtensionFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -117,7 +119,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. {$IFDEF DELPHI12_UP}procedure {$ELSE}class procedure TJSSimpleExtensionFrm.{$ENDIF}GlobalCEFApp_OnWebKitInitializedEvent; @@ -149,6 +152,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSSimpleExtensionFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSSimpleExtensionFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -220,8 +229,7 @@ end; procedure TJSSimpleExtensionFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSSimpleExtensionFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.dfm b/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.dfm index 55816cca..001fdecb 100644 --- a/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.dfm +++ b/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.dfm @@ -76,4 +76,9 @@ object JSSimpleWindowBindingFrm: TJSSimpleWindowBindingFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 344 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.pas b/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.pas index 24cbb5f6..dde70dca 100644 --- a/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.pas +++ b/demos/Delphi_VCL/JavaScript/JSSimpleWindowBinding/uJSSimpleWindowBinding.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, - uCEFConstants, uCEFv8Value, uCEFWinControl; + uCEFConstants, uCEFv8Value, uCEFWinControl, uCEFSentinel; type TJSSimpleWindowBindingFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -112,7 +114,8 @@ implementation // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnContextCreated(const browser: ICefBrowser; const frame: ICefFrame; const context: ICefv8Context); var @@ -137,6 +140,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSSimpleWindowBindingFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSSimpleWindowBindingFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -208,8 +217,7 @@ end; procedure TJSSimpleWindowBindingFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSSimpleWindowBindingFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.dfm b/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.dfm index 55816cca..63fac2e0 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.dfm +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.dfm @@ -76,4 +76,9 @@ object JSSimpleWindowBindingFrm: TJSSimpleWindowBindingFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 352 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.pas b/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.pas index fd64cd5d..7ddf4728 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.pas +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingSubProcess/uJSSimpleWindowBinding.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, - uCEFConstants, uCEFv8Value, uCEFWinControl; + uCEFConstants, uCEFv8Value, uCEFWinControl, uCEFSentinel; type TJSSimpleWindowBindingFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected FText : string; // Variables to control when can we destroy the form safely @@ -113,7 +115,8 @@ implementation // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -138,6 +141,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSSimpleWindowBindingFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSSimpleWindowBindingFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -209,8 +218,7 @@ end; procedure TJSSimpleWindowBindingFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSSimpleWindowBindingFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.dfm b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.dfm index 8a48eb21..fcea4705 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.dfm +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.dfm @@ -76,4 +76,9 @@ object JSWindowBindingWithArrayBufferFrm: TJSWindowBindingWithArrayBufferFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 344 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.pas b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.pas index 37e4fef7..cf0503e1 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.pas +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithArrayBuffer/uJSWindowBindingWithArrayBuffer.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TJSWindowBindingWithArrayBufferFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -115,7 +117,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure FreeCustomArrayBufer(buffer : Pointer); begin @@ -162,6 +165,13 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSWindowBindingWithArrayBufferFrm.CEFSentinel1Close( + Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSWindowBindingWithArrayBufferFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -233,8 +243,7 @@ end; procedure TJSWindowBindingWithArrayBufferFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSWindowBindingWithArrayBufferFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.dfm b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.dfm index 1b4a4075..985eec52 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.dfm +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.dfm @@ -76,4 +76,9 @@ object JSWindowBindingWithFunctionFrm: TJSWindowBindingWithFunctionFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 352 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.pas b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.pas index 515e8d2b..e873eff8 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.pas +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithFunction/uJSWindowBindingWithFunction.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TJSWindowBindingWithFunctionFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -115,7 +117,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnContextCreated(const browser: ICefBrowser; const frame: ICefFrame; const context: ICefv8Context); var @@ -142,6 +145,13 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSWindowBindingWithFunctionFrm.CEFSentinel1Close( + Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSWindowBindingWithFunctionFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -213,8 +223,7 @@ end; procedure TJSWindowBindingWithFunctionFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSWindowBindingWithFunctionFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.dfm b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.dfm index 597ca244..0742a1f5 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.dfm +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.dfm @@ -76,4 +76,9 @@ object JSWindowBindingWithObjectFrm: TJSWindowBindingWithObjectFrm Left = 32 Top = 288 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 352 + end end diff --git a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.pas b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.pas index fcbdf24c..c83a4501 100644 --- a/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.pas +++ b/demos/Delphi_VCL/JavaScript/JSWindowBindingWithObject/uJSWindowBindingWithObject.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFTypes, uCEFConstants, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TJSWindowBindingWithObjectFrm = class(TForm) @@ -60,6 +60,7 @@ type CEFWindowParent1: TCEFWindowParent; Chromium1: TChromium; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure FormShow(Sender: TObject); procedure GoBtnClick(Sender: TObject); procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); @@ -78,6 +79,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -115,7 +117,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnContextCreated(const browser: ICefBrowser; const frame: ICefFrame; const context: ICefv8Context); var @@ -143,6 +146,12 @@ begin Chromium1.LoadURL(Edit1.Text); end; +procedure TJSWindowBindingWithObjectFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TJSWindowBindingWithObjectFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -214,8 +223,7 @@ end; procedure TJSWindowBindingWithObjectFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TJSWindowBindingWithObjectFrm.Chromium1Close( diff --git a/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.dfm b/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.dfm index cbbf729e..0316fe1b 100644 --- a/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.dfm +++ b/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.dfm @@ -80,4 +80,9 @@ object Form1: TForm1 Left = 24 Top = 206 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 24 + Top = 280 + end end diff --git a/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.pas b/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.pas index 012b3916..1a27c2d4 100644 --- a/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.pas +++ b/demos/Delphi_VCL/KioskOSRBrowser/uKioskOSRBrowser.pas @@ -50,7 +50,8 @@ uses Windows, Messages, SysUtils, Variants, Classes, SyncObjs, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, AppEvnts, Keyboard, {$ENDIF} - uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel; + uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, + uCEFSentinel; const HOMEPAGE_URL = 'https://www.google.com'; @@ -72,9 +73,11 @@ type Timer1: TTimer; Panel1: TBufferPanel; TouchKeyboard1: TTouchKeyboard; + CEFSentinel1: TCEFSentinel; procedure AppEventsMessage(var Msg: tagMSG; var Handled: Boolean); procedure Timer1Timer(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); procedure Panel1Enter(Sender: TObject); procedure Panel1Exit(Sender: TObject); @@ -167,7 +170,8 @@ uses // 2- chrmosr.CloseBrowser(True) will trigger chrmosr.OnClose and we have to // set "Result" to false and CEF3 will destroy the internal browser immediately. // 3- chrmosr.OnBeforeClose is triggered because the internal browser was destroyed. -// Now we set FCanClose to True and send WM_CLOSE to the form. +// Now we call TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4- TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -299,8 +303,7 @@ end; procedure TForm1.chrmosrBeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TForm1.chrmosrBeforeContextMenu( Sender : TObject; @@ -861,6 +864,12 @@ begin (cardinal(aCurrentTime - FLastClickTime) > GetDoubleClickTime); end; +procedure TForm1.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TForm1.Panel1Enter(Sender: TObject); begin chrmosr.SendFocusEvent(True); diff --git a/demos/Delphi_VCL/MDIBrowser/uMainForm.dfm b/demos/Delphi_VCL/MDIBrowser/uMainForm.dfm index 3bca3c50..c122f6d5 100644 --- a/demos/Delphi_VCL/MDIBrowser/uMainForm.dfm +++ b/demos/Delphi_VCL/MDIBrowser/uMainForm.dfm @@ -80,4 +80,9 @@ object MainForm: TMainForm TabOrder = 0 end end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 80 + end end diff --git a/demos/Delphi_VCL/MDIBrowser/uMainForm.pas b/demos/Delphi_VCL/MDIBrowser/uMainForm.pas index f5432216..dc93c4f0 100644 --- a/demos/Delphi_VCL/MDIBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/MDIBrowser/uMainForm.pas @@ -45,12 +45,13 @@ uses {$IFDEF DELPHI16_UP} Winapi.Windows, System.SysUtils, System.Classes, Vcl.Graphics, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, Vcl.Dialogs, Vcl.Buttons, Winapi.Messages, - Vcl.ExtCtrls, Vcl.ComCtrls; + Vcl.ExtCtrls, Vcl.ComCtrls, {$ELSE} Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls, Dialogs, Buttons, Messages, - ExtCtrls, ComCtrls; + ExtCtrls, ComCtrls, {$ENDIF} + uCEFSentinel; const CEFBROWSER_CREATED = WM_APP + $100; @@ -64,10 +65,12 @@ type NewBtn: TSpeedButton; ExitBtn: TSpeedButton; NewContextChk: TCheckBox; + CEFSentinel1: TCEFSentinel; procedure FormCreate(Sender: TObject); procedure NewBtnClick(Sender: TObject); procedure ExitBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); private // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True when all the child forms are closed @@ -104,7 +107,8 @@ uses // Destruction steps // ================= // 1. Destroy all child forms -// 2. Wait until all the child forms are closed before closing the main form and terminating the application. +// 2. Wait until all the child forms are closed before calling TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when all renderer processes are closed +// 3. TCEFSentinel.OnClose closes the main form. procedure GlobalCEFApp_OnContextInitialized; begin @@ -181,14 +185,19 @@ begin CloseAllChildForms; end; +procedure TMainForm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TMainForm.ChildDestroyedMsg(var aMessage : TMessage); begin // If there are no more child forms we can destroy the main form if FClosing and (MDIChildCount = 0) then begin ButtonPnl.Enabled := False; - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; end; diff --git a/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.dfm b/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.dfm index b24e73ad..e7c4edb8 100644 --- a/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.dfm +++ b/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.dfm @@ -80,4 +80,9 @@ object MainForm: TMainForm TabOrder = 0 end end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 32 + Top = 56 + end end diff --git a/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.pas b/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.pas index c5d0c1ba..ed9ce522 100644 --- a/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/MDIExternalPumpBrowser/uMainForm.pas @@ -51,7 +51,7 @@ uses Controls, StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, {$ENDIF} - uCEFWorkScheduler; + uCEFWorkScheduler, uCEFSentinel; const CEFBROWSER_CREATED = WM_APP + $100; @@ -65,10 +65,12 @@ type NewBtn: TSpeedButton; ExitBtn: TSpeedButton; NewContextChk: TCheckBox; + CEFSentinel1: TCEFSentinel; procedure FormCreate(Sender: TObject); procedure NewBtnClick(Sender: TObject); procedure ExitBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); private // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True when all the child forms are closed @@ -103,7 +105,8 @@ uses // Destruction steps // ================= // 1. Destroy all child forms -// 2. Wait until all the child forms are closed before closing the main form and terminating the application. +// 2. Wait until all the child forms are closed before calling TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when all renderer processes are closed +// 3. TCEFSentinel.OnClose closes the main form. procedure GlobalCEFApp_OnContextInitialized; begin @@ -198,11 +201,16 @@ begin if FClosing and (MDIChildCount = 0) then begin ButtonPnl.Enabled := False; - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; end; +procedure TMainForm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TMainForm.CEFInitializedMsg(var aMessage : TMessage); begin Caption := 'MDI External Pump Browser'; diff --git a/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas b/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas index 71a53864..19027f1c 100644 --- a/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas +++ b/demos/Delphi_VCL/MiniBrowser/uMiniBrowser.pas @@ -292,7 +292,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -472,7 +473,8 @@ begin if Chromium1.IsSameBrowser(browser) and (frame <> nil) and - frame.IsMain then + frame.IsMain and + frame.IsValid then InspectRequest(request); end; @@ -544,8 +546,8 @@ begin end; MINIBROWSER_CONTEXTMENU_JSWRITEDOC : - if (browser <> nil) and (browser.MainFrame <> nil) then - browser.MainFrame.ExecuteJavaScript( + if (frame <> nil) and frame.IsValid then + frame.ExecuteJavaScript( 'var css = ' + chr(39) + '@page {size: A4; margin: 0;} @media print {html, body {width: 210mm; height: 297mm;}}' + chr(39) + '; ' + 'var style = document.createElement(' + chr(39) + 'style' + chr(39) + '); ' + 'style.type = ' + chr(39) + 'text/css' + chr(39) + '; ' + @@ -554,8 +556,8 @@ begin 'about:blank', 0); MINIBROWSER_CONTEXTMENU_JSPRINTDOC : - if (browser <> nil) and (browser.MainFrame <> nil) then - browser.MainFrame.ExecuteJavaScript('window.print();', 'about:blank', 0); + if (frame <> nil) and frame.IsValid then + frame.ExecuteJavaScript('window.print();', 'about:blank', 0); MINIBROWSER_CONTEXTMENU_UNMUTEAUDIO : Chromium1.AudioMuted := False; @@ -708,6 +710,8 @@ procedure TMiniBrowserFrm.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer); begin + if (frame = nil) or not(frame.IsValid) then exit; + if frame.IsMain then StatusBar1.Panels[1].Text := 'main frame loaded : ' + quotedstr(frame.name) else @@ -717,10 +721,17 @@ end; procedure TMiniBrowserFrm.Chromium1LoadError(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; errorCode: Integer; const errorText, failedUrl: ustring); +var + TempString : string; begin - CefDebugLog('Error code:' + inttostr(errorCode) + - ' - Error text :' + quotedstr(errorText) + - ' - URL:' + failedUrl, CEF_LOG_SEVERITY_ERROR); + if (errorCode = ERR_ABORTED) then exit; + + TempString := '' + + '

Failed to load URL ' + failedUrl + + ' with error ' + errorText + + ' (' + inttostr(errorCode) + ').

'; + + frame.LoadURL(CefGetDataURI(TempString, 'text/html')); end; procedure TMiniBrowserFrm.Chromium1LoadingProgressChange(Sender: TObject; @@ -890,7 +901,8 @@ begin if Chromium1.IsSameBrowser(browser) and (frame <> nil) and - frame.IsMain then + frame.IsMain and + frame.IsValid then InspectResponse(response); end; @@ -1084,9 +1096,9 @@ begin TempFile.LoadFromFile(OpenDialog1.FileName); if (OpenDialog1.FilterIndex = 1) then - TempDATA := 'data:text/html;charset=utf-8;base64,' + CefBase64Encode(TempFile.Memory, TempFile.Size) + TempDATA := CefGetDataURI(TempFile.Memory, TempFile.Size, 'text/html', 'utf-8') else - TempDATA := 'data:application/pdf;charset=utf-8;base64,' + CefBase64Encode(TempFile.Memory, TempFile.Size); + TempDATA := CefGetDataURI(TempFile.Memory, TempFile.Size, 'application/pdf', 'utf-8'); Chromium1.LoadURL(TempDATA); end; diff --git a/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.dfm b/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.dfm index 139392ba..d12f3f5c 100644 --- a/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.dfm +++ b/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.dfm @@ -157,4 +157,9 @@ object OSRExternalPumpBrowserFrm: TOSRExternalPumpBrowserFrm Left = 24 Top = 206 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 24 + Top = 342 + end end diff --git a/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.pas b/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.pas index ca2d5de5..9b890640 100644 --- a/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.pas +++ b/demos/Delphi_VCL/OSRExternalPumpBrowser/uOSRExternalPumpBrowser.pas @@ -50,7 +50,8 @@ uses Windows, Messages, SysUtils, Variants, Classes, SyncObjs, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, AppEvnts, {$ENDIF} - uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, uCEFWorkScheduler; + uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, uCEFWorkScheduler, + uCEFSentinel; type TOSRExternalPumpBrowserFrm = class(TForm) @@ -64,6 +65,7 @@ type SaveDialog1: TSaveDialog; Timer1: TTimer; Panel1: TBufferPanel; + CEFSentinel1: TCEFSentinel; procedure AppEventsMessage(var Msg: tagMSG; var Handled: Boolean); @@ -107,6 +109,7 @@ type procedure Timer1Timer(Sender: TObject); procedure ComboBox1Enter(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); protected FPopUpBitmap : TBitmap; @@ -152,7 +155,8 @@ var // 2- chrmosr.CloseBrowser(True) will trigger chrmosr.OnClose and we have to // set "Result" to false and CEF3 will destroy the internal browser immediately. // 3- chrmosr.OnBeforeClose is triggered because the internal browser was destroyed. -// Now we set FCanClose to True and send WM_CLOSE to the form. +// Now we call TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4- TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); @@ -325,6 +329,11 @@ begin end; procedure TOSRExternalPumpBrowserFrm.chrmosrBeforeClose(Sender: TObject; const browser: ICefBrowser); +begin + CEFSentinel1.Start; +end; + +procedure TOSRExternalPumpBrowserFrm.CEFSentinel1Close(Sender: TObject); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); diff --git a/demos/Delphi_VCL/PopupBrowser/uMainForm.dfm b/demos/Delphi_VCL/PopupBrowser/uMainForm.dfm index 9385b60c..cbdcbdda 100644 --- a/demos/Delphi_VCL/PopupBrowser/uMainForm.dfm +++ b/demos/Delphi_VCL/PopupBrowser/uMainForm.dfm @@ -82,4 +82,9 @@ object MainForm: TMainForm Left = 56 Top = 216 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 288 + end end diff --git a/demos/Delphi_VCL/PopupBrowser/uMainForm.pas b/demos/Delphi_VCL/PopupBrowser/uMainForm.pas index 1fd4c3ac..4bb2b9f4 100644 --- a/demos/Delphi_VCL/PopupBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/PopupBrowser/uMainForm.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, uChildForm, - Vcl.AppEvnts, uCEFWinControl; + Vcl.AppEvnts, uCEFWinControl, uCEFSentinel; const CEF_CREATENEXTCHILD = WM_APP + $A50; @@ -65,6 +65,7 @@ type Chromium1: TChromium; CEFWindowParent1: TCEFWindowParent; AppEvents: TApplicationEvents; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); @@ -79,6 +80,7 @@ type procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean); procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); protected FChildForm : TChildForm; @@ -142,7 +144,8 @@ uses // 1. FormCloseQuery sets CanClose to FALSE and it closes all child forms. // 2. When all the child forms are closed then FormCloseQuery is triggered again, sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 3. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 4. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 4. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 5. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -243,8 +246,7 @@ end; procedure TMainForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; function TMainForm.CreateClientHandler(var windowInfo : TCefWindowInfo; @@ -352,6 +354,12 @@ begin end; end; +procedure TMainForm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TMainForm.ChildDestroyedMsg(var aMessage : TMessage); begin if FClosingChildren and (PopupChildCount = 0) then Close; diff --git a/demos/Delphi_VCL/PopupBrowser2/uMainForm.dfm b/demos/Delphi_VCL/PopupBrowser2/uMainForm.dfm index 2f239092..f7a0525c 100644 --- a/demos/Delphi_VCL/PopupBrowser2/uMainForm.dfm +++ b/demos/Delphi_VCL/PopupBrowser2/uMainForm.dfm @@ -77,4 +77,9 @@ object MainForm: TMainForm Left = 56 Top = 152 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 48 + Top = 208 + end end diff --git a/demos/Delphi_VCL/PopupBrowser2/uMainForm.pas b/demos/Delphi_VCL/PopupBrowser2/uMainForm.pas index 750ff632..f71b6707 100644 --- a/demos/Delphi_VCL/PopupBrowser2/uMainForm.pas +++ b/demos/Delphi_VCL/PopupBrowser2/uMainForm.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, uChildForm, - Vcl.AppEvnts, uCEFWinControl; + Vcl.AppEvnts, uCEFWinControl, uCEFSentinel; const CEF_CREATENEXTCHILD = WM_APP + $A50; @@ -64,6 +64,7 @@ type Timer1: TTimer; Chromium1: TChromium; CEFWindowParent1: TCEFWindowParent; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); @@ -77,6 +78,7 @@ type procedure Chromium1BeforePopup(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const targetUrl, targetFrameName: ustring; targetDisposition: TCefWindowOpenDisposition; userGesture: Boolean; const popupFeatures: TCefPopupFeatures; var windowInfo: TCefWindowInfo; var client: ICefClient; var settings: TCefBrowserSettings; var extra_info: ICefDictionaryValue; var noJavascriptAccess: Boolean; var Result: Boolean); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); procedure Chromium1Close(Sender: TObject; const browser: ICefBrowser; var aAction: TCefCloseBrowserAction); + procedure CEFSentinel1Close(Sender: TObject); protected FChildForm : TChildForm; @@ -140,7 +142,8 @@ uses // 1. FormCloseQuery sets CanClose to FALSE and it closes all child forms. // 2. When all the child forms are closed then FormCloseQuery is triggered again, sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 3. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 4. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 4. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 5. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -208,8 +211,7 @@ end; procedure TMainForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TMainForm.Chromium1BeforePopup(Sender : TObject; @@ -333,6 +335,12 @@ begin end; end; +procedure TMainForm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TMainForm.ChildDestroyedMsg(var aMessage : TMessage); begin if FClosingChildren and (PopupChildCount = 0) then Close; diff --git a/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.dfm b/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.dfm index 278b7a11..618ddc18 100644 --- a/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.dfm +++ b/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.dfm @@ -98,4 +98,9 @@ object Form1: TForm1 Left = 56 Top = 152 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 224 + end end diff --git a/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.pas b/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.pas index 13227b86..8ade34a5 100644 --- a/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.pas +++ b/demos/Delphi_VCL/PostInspectorBrowser/uPostInspectorBrowser.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const CEF_SHOWDATA = WM_APP + $B00; @@ -65,6 +65,7 @@ type Memo1: TMemo; AddressCb: TComboBox; Splitter1: TSplitter; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure Timer1Timer(Sender: TObject); @@ -88,6 +89,7 @@ type const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const callback: ICefRequestCallback; out Result: TCefReturnValue); + procedure CEFSentinel1Close(Sender: TObject); protected // Variables to control when can we destroy the form safely FCanClose : boolean; // Set to True in TChromium.OnBeforeClose @@ -141,7 +143,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -357,7 +360,9 @@ procedure TForm1.Chromium1BeforeResourceLoad(Sender: TObject; begin // This event is called before a resource request is loaded. // The request object may be modified. - HandleRequest(request, frame.IsMain); + if (frame <> nil) and frame.IsValid then + HandleRequest(request, frame.IsMain); + Result := RV_CONTINUE; end; @@ -379,6 +384,11 @@ begin end; procedure TForm1.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); +begin + CEFSentinel1.Start; +end; + +procedure TForm1.CEFSentinel1Close(Sender: TObject); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); diff --git a/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.dfm b/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.dfm index e3ba3193..acb9480f 100644 --- a/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.dfm +++ b/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.dfm @@ -167,4 +167,9 @@ object ResponseFilterBrowserFrm: TResponseFilterBrowserFrm Left = 56 Top = 160 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 232 + end end diff --git a/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.pas b/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.pas index 19df8d2d..277db43f 100644 --- a/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.pas +++ b/demos/Delphi_VCL/ResponseFilterBrowser/uResponseFilterBrowser.pas @@ -51,7 +51,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs, ComCtrls, pngimage, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, uCEFResponseFilter, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; const STREAM_COPY_COMPLETE = WM_APP + $B00; @@ -72,6 +72,7 @@ type StatusBar1: TStatusBar; CopyScriptBtn: TRadioButton; ReplaceLogoBtn: TRadioButton; + CEFSentinel1: TCEFSentinel; procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); procedure Chromium1GetResourceResponseFilter(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; out Result: ICefResponseFilter); @@ -90,6 +91,7 @@ type procedure GoBtnClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); protected FFilter : ICefResponseFilter; // CEF Filter interface that receives the resource contents @@ -159,8 +161,9 @@ uses // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy // CEFWindowParent1 in the main thread, which triggers the // TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE -// to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger +// TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. // TCustomResponseFilter.OnFilter event might be called multiple times // when the resource is too big. In that case the resource will be split into @@ -403,8 +406,7 @@ end; procedure TResponseFilterBrowserFrm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TResponseFilterBrowserFrm.Chromium1BeforePopup( Sender : TObject; @@ -506,7 +508,7 @@ const var TempPath : string; begin - if frame.IsMain then + if (frame <> nil) and frame.IsValid and frame.IsMain then try try FStreamCS.Acquire; @@ -541,6 +543,12 @@ begin {$ENDIF} end; +procedure TResponseFilterBrowserFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TResponseFilterBrowserFrm.CheckResponseHeaders(const response : ICefResponse); var TempContentLength, TempContentEncoding : string; diff --git a/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.dfm b/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.dfm index bb803d4a..9aee6ad6 100644 --- a/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.dfm +++ b/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.dfm @@ -82,4 +82,9 @@ object SchemeRegistrationBrowserFrm: TSchemeRegistrationBrowserFrm Left = 16 Top = 96 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 16 + Top = 152 + end end diff --git a/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.pas b/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.pas index aa900997..f2b4206d 100644 --- a/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.pas +++ b/demos/Delphi_VCL/SchemeRegistrationBrowser/uSchemeRegistrationBrowser.pas @@ -51,7 +51,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Types, ComCtrls, ClipBrd, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFApplication, uCEFSchemeRegistrar, - uCEFTypes, uCEFConstants, uCEFWinControl; + uCEFTypes, uCEFConstants, uCEFWinControl, uCEFSentinel; const MINIBROWSER_CONTEXTMENU_REGSCHEME = MENU_ID_USER_FIRST + 1; @@ -65,6 +65,7 @@ type Chromium1: TChromium; AddressCbx: TComboBox; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); procedure Chromium1BeforeContextMenu(Sender: TObject; @@ -91,6 +92,7 @@ type var aAction : TCefCloseBrowserAction); procedure Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); + procedure CEFSentinel1Close(Sender: TObject); private { Private declarations } protected @@ -135,7 +137,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnRegCustomSchemes(const registrar: TCefSchemeRegistrarRef); begin @@ -151,6 +154,12 @@ begin // GlobalCEFApp.LogSeverity := LOGSEVERITY_VERBOSE; end; +procedure TSchemeRegistrationBrowserFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TSchemeRegistrationBrowserFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser); begin PostMessage(Handle, CEF_AFTERCREATED, 0, 0); @@ -159,8 +168,7 @@ end; procedure TSchemeRegistrationBrowserFrm.Chromium1BeforeClose( Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TSchemeRegistrationBrowserFrm.Chromium1BeforeContextMenu( diff --git a/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.dfm b/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.dfm index 84ca34e8..40463dfa 100644 --- a/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.dfm +++ b/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.dfm @@ -72,4 +72,9 @@ object Form1: TForm1 Left = 56 Top = 88 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 160 + end end diff --git a/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.pas b/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.pas index ab7c42ed..a128a95a 100644 --- a/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.pas +++ b/demos/Delphi_VCL/SimpleBrowser/uSimpleBrowser.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFChromiumWindow, uCEFTypes, uCEFInterfaces, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TForm1 = class(TForm) @@ -59,6 +59,7 @@ type AddressEdt: TEdit; GoBtn: TButton; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); @@ -70,6 +71,7 @@ type procedure ChromiumWindow1AfterCreated(Sender: TObject); procedure ChromiumWindow1Close(Sender: TObject); procedure ChromiumWindow1BeforeClose(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); private // You have to handle this two messages to call NotifyMoveOrResizeStarted or some page elements will be misaligned. @@ -116,7 +118,8 @@ uses // ================= // 1. The FormCloseQuery event sets CanClose to False and calls TChromiumWindow.CloseBrowser, which triggers the TChromiumWindow.OnClose event. // 2. The TChromiumWindow.OnClose event calls TChromiumWindow.DestroyChildWindow which triggers the TChromiumWindow.OnBeforeClose event. -// 3. TChromiumWindow.OnBeforeClose sets FCanClose to True and closes the form. +// 3. TChromiumWindow.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); @@ -151,20 +154,21 @@ begin if not(ChromiumWindow1.CreateBrowser) then Timer1.Enabled := True; end; -procedure TForm1.ChromiumWindow1BeforeClose(Sender: TObject); +procedure TForm1.CEFSentinel1Close(Sender: TObject); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); end; +procedure TForm1.ChromiumWindow1BeforeClose(Sender: TObject); +begin + CEFSentinel1.Start; +end; + procedure TForm1.ChromiumWindow1Close(Sender: TObject); begin // DestroyChildWindow will destroy the child window created by CEF at the top of the Z order. - if not(ChromiumWindow1.DestroyChildWindow) then - begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); - end; + if not(ChromiumWindow1.DestroyChildWindow) then CEFSentinel1.Start; end; procedure TForm1.Chromium_OnBeforePopup( Sender : TObject; diff --git a/demos/Delphi_VCL/SimpleBrowser2/uSimpleBrowser2.pas b/demos/Delphi_VCL/SimpleBrowser2/uSimpleBrowser2.pas index 59d8825c..695a88e0 100644 --- a/demos/Delphi_VCL/SimpleBrowser2/uSimpleBrowser2.pas +++ b/demos/Delphi_VCL/SimpleBrowser2/uSimpleBrowser2.pas @@ -132,7 +132,8 @@ uses // ================= // 1. FormCloseQuery sets CanClose to FALSE calls TChromium.CloseBrowser which triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread, which triggers the TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form. +// 3. TChromium.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin diff --git a/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.dfm b/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.dfm index 26f10886..8198c360 100644 --- a/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.dfm +++ b/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.dfm @@ -94,4 +94,9 @@ object SimpleExternalPumpBrowserFrm: TSimpleExternalPumpBrowserFrm Left = 56 Top = 88 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 56 + Top = 160 + end end diff --git a/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.pas b/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.pas index 194d296f..aa1882bf 100644 --- a/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.pas +++ b/demos/Delphi_VCL/SimpleExternalPumpBrowser/uSimpleExternalPumpBrowser.pas @@ -50,7 +50,8 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFTypes, uCEFConstants, uCEFInterfaces, uCEFWorkScheduler, - uCEFChromiumWindow, Vcl.ComCtrls, Vcl.AppEvnts, uCEFWinControl; + uCEFChromiumWindow, Vcl.ComCtrls, Vcl.AppEvnts, uCEFWinControl, + uCEFSentinel; type TSimpleExternalPumpBrowserFrm = class(TForm) @@ -59,10 +60,12 @@ type Timer1: TTimer; URLCbx: TComboBox; ChromiumWindow1: TChromiumWindow; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure Timer1Timer(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); @@ -101,7 +104,8 @@ uses // It was necessary to destroy the browser with the following destruction sequence : // 1. The FormCloseQuery event sets CanClose to False and calls TChromiumWindow.CloseBrowser, which triggers the TChromiumWindow.OnClose event. // 2. The TChromiumWindow.OnClose event calls TChromiumWindow.DestroyChildWindow which triggers the TChromiumWindow.OnBeforeClose event. -// 3. TChromiumWindow.OnBeforeClose sets FCanClose to True and closes the form. +// 3. TChromiumWindow.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure GlobalCEFApp_OnScheduleMessagePumpWork(const aDelayMS : int64); begin @@ -172,12 +176,17 @@ begin GoBtn.Click; end; -procedure TSimpleExternalPumpBrowserFrm.ChromiumWindow1BeforeClose(Sender: TObject); +procedure TSimpleExternalPumpBrowserFrm.CEFSentinel1Close(Sender: TObject); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); end; +procedure TSimpleExternalPumpBrowserFrm.ChromiumWindow1BeforeClose(Sender: TObject); +begin + CEFSentinel1.Start; +end; + procedure TSimpleExternalPumpBrowserFrm.ChromiumWindow1Close(Sender: TObject); begin // DestroyChildWindow will destroy the child window created by CEF at the top of the Z order. diff --git a/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.dfm b/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.dfm index da045e0a..e65f9d81 100644 --- a/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.dfm +++ b/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.dfm @@ -160,4 +160,9 @@ object Form1: TForm1 Left = 24 Top = 206 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 24 + Top = 350 + end end diff --git a/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.pas b/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.pas index 60c52618..95c9325a 100644 --- a/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.pas +++ b/demos/Delphi_VCL/SimpleOSRBrowser/uSimpleOSRBrowser.pas @@ -50,7 +50,8 @@ uses Windows, Messages, SysUtils, Variants, Classes, SyncObjs, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, AppEvnts, {$ENDIF} - uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel; + uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, + uCEFSentinel; const // Set this constant to True and load "file://transparency.html" to test a @@ -69,6 +70,7 @@ type SaveDialog1: TSaveDialog; Timer1: TTimer; Panel1: TBufferPanel; + CEFSentinel1: TCEFSentinel; procedure AppEventsMessage(var Msg: tagMSG; var Handled: Boolean); @@ -113,6 +115,7 @@ type procedure Timer1Timer(Sender: TObject); procedure ComboBox1Enter(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); protected FPopUpBitmap : TBitmap; @@ -174,7 +177,8 @@ uses // 2- chrmosr.CloseBrowser(True) will trigger chrmosr.OnClose and we have to // set "Result" to false and CEF3 will destroy the internal browser immediately. // 3- chrmosr.OnBeforeClose is triggered because the internal browser was destroyed. -// Now we set FCanClose to True and send WM_CLOSE to the form. +// Now we call TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4- TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure CreateGlobalCEFApp; begin @@ -326,8 +330,7 @@ end; procedure TForm1.chrmosrBeforeClose(Sender: TObject; const browser: ICefBrowser); begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); + CEFSentinel1.Start; end; procedure TForm1.chrmosrBeforePopup(Sender : TObject; @@ -894,6 +897,12 @@ begin (cardinal(aCurrentTime - FLastClickTime) > GetDoubleClickTime); end; +procedure TForm1.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TForm1.Panel1Enter(Sender: TObject); begin chrmosr.SendFocusEvent(True); diff --git a/demos/Delphi_VCL/SubProcess/uSimpleBrowser.dfm b/demos/Delphi_VCL/SubProcess/uSimpleBrowser.dfm index fc3d0e45..fc01a8d2 100644 --- a/demos/Delphi_VCL/SubProcess/uSimpleBrowser.dfm +++ b/demos/Delphi_VCL/SubProcess/uSimpleBrowser.dfm @@ -70,4 +70,9 @@ object Form1: TForm1 Left = 80 Top = 88 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 80 + Top = 160 + end end diff --git a/demos/Delphi_VCL/SubProcess/uSimpleBrowser.pas b/demos/Delphi_VCL/SubProcess/uSimpleBrowser.pas index 0bbda56a..113d61dd 100644 --- a/demos/Delphi_VCL/SubProcess/uSimpleBrowser.pas +++ b/demos/Delphi_VCL/SubProcess/uSimpleBrowser.pas @@ -50,7 +50,7 @@ uses Controls, Forms, Dialogs, StdCtrls, ExtCtrls, {$ENDIF} uCEFChromium, uCEFWindowParent, uCEFChromiumWindow, uCEFTypes, uCEFInterfaces, - uCEFWinControl; + uCEFWinControl, uCEFSentinel; type TForm1 = class(TForm) @@ -59,6 +59,7 @@ type AddressEdt: TEdit; GoBtn: TButton; Timer1: TTimer; + CEFSentinel1: TCEFSentinel; procedure GoBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure ChromiumWindow1AfterCreated(Sender: TObject); @@ -66,6 +67,7 @@ type procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure ChromiumWindow1Close(Sender: TObject); procedure ChromiumWindow1BeforeClose(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); private // You have to handle this two messages to call NotifyMoveOrResizeStarted or some page elements will be misaligned. procedure WMMove(var aMessage : TWMMove); message WM_MOVE; @@ -110,7 +112,8 @@ uses // ================= // 1. The FormCloseQuery event sets CanClose to False and calls TChromiumWindow.CloseBrowser, which triggers the TChromiumWindow.OnClose event. // 2. The TChromiumWindow.OnClose event calls TChromiumWindow.DestroyChildWindow which triggers the TChromiumWindow.OnBeforeClose event. -// 3. TChromiumWindow.OnBeforeClose sets FCanClose to True and closes the form. +// 3. TChromiumWindow.OnBeforeClose calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin @@ -147,14 +150,15 @@ end; procedure TForm1.ChromiumWindow1Close(Sender: TObject); begin // DestroyChildWindow will destroy the child window created by CEF at the top of the Z order. - if not(ChromiumWindow1.DestroyChildWindow) then - begin - FCanClose := True; - Close; - end; + if not(ChromiumWindow1.DestroyChildWindow) then CEFSentinel1.Start; end; procedure TForm1.ChromiumWindow1BeforeClose(Sender: TObject); +begin + CEFSentinel1.Start; +end; + +procedure TForm1.CEFSentinel1Close(Sender: TObject); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); diff --git a/demos/Delphi_VCL/TabbedBrowser/uMainForm.pas b/demos/Delphi_VCL/TabbedBrowser/uMainForm.pas index 63c6285f..c393d191 100644 --- a/demos/Delphi_VCL/TabbedBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/TabbedBrowser/uMainForm.pas @@ -147,7 +147,9 @@ implementation // This is the destruction sequence when the user closes the main form // 1. FormCloseQuery hides the form and calls CloseAllBrowsers which calls TChromium.CloseBrowser in all tabs and triggers the TChromium.OnClose event. // 2. TChromium.OnClose sends a CEFBROWSER_DESTROYWNDPARENT message to destroy TCEFWindowParent in the main thread which triggers a TChromium.OnBeforeClose event. -// 3. TChromium.OnBeforeClose sends a CEFBROWSER_CHECKTAGGEDTABS message to set the TAG property to 1 in the TabSheet containing the TChromium. Then sends WM_CLOSE in case all tabsheets have a TAG = 1. +// 3. TChromium.OnBeforeClose sends a CEFBROWSER_CHECKTAGGEDTABS message to set the TAG property to 1 in the TabSheet containing the TChromium. +// When all tabsheets have a TAG = 1 it calls TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4. TCEFSentinel.OnClose sends WM_CLOSE to the form. procedure GlobalCEFApp_OnContextInitialized; begin diff --git a/demos/Delphi_VCL/ToolBoxBrowser/uMainForm.pas b/demos/Delphi_VCL/ToolBoxBrowser/uMainForm.pas index 19bf295a..a9e7d0ca 100644 --- a/demos/Delphi_VCL/ToolBoxBrowser/uMainForm.pas +++ b/demos/Delphi_VCL/ToolBoxBrowser/uMainForm.pas @@ -103,7 +103,8 @@ uses // Destruction steps // ================= // 1. Destroy all child forms -// 2. Wait until all the child forms are closed before closing the main form and terminating the application. +// 2. Wait until all the child forms are closed before calling TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when all renderer processes are closed +// 3. TCEFSentinel.OnClose closes the main form. procedure GlobalCEFApp_OnContextInitialized; begin diff --git a/demos/Delphi_VCL/URLRequest/uURLRequest.dfm b/demos/Delphi_VCL/URLRequest/uURLRequest.dfm index c28f9029..f153c246 100644 --- a/demos/Delphi_VCL/URLRequest/uURLRequest.dfm +++ b/demos/Delphi_VCL/URLRequest/uURLRequest.dfm @@ -193,4 +193,9 @@ object URLRequestFrm: TURLRequestFrm Left = 304 Top = 104 end + object CEFSentinel1: TCEFSentinel + OnClose = CEFSentinel1Close + Left = 160 + Top = 112 + end end diff --git a/demos/Delphi_VCL/URLRequest/uURLRequest.pas b/demos/Delphi_VCL/URLRequest/uURLRequest.pas index 9330d3b7..022c19eb 100644 --- a/demos/Delphi_VCL/URLRequest/uURLRequest.pas +++ b/demos/Delphi_VCL/URLRequest/uURLRequest.pas @@ -47,7 +47,8 @@ uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, {$ENDIF} - uCEFInterfaces, uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest; + uCEFInterfaces, uCEFUrlRequestClientComponent, uCEFRequest, uCEFUrlRequest, + uCEFSentinel; const URLREQUEST_SUCCESS = WM_APP + $101; @@ -77,9 +78,12 @@ type Label6: TLabel; PostParam2NameEdt: TEdit; PostParam2ValueEdt: TEdit; + CEFSentinel1: TCEFSentinel; procedure DownloadBtnClick(Sender: TObject); procedure SendPostReqBtnClick(Sender: TObject); + procedure Button1Click(Sender: TObject); + procedure CEFSentinel1Close(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); @@ -90,8 +94,6 @@ type procedure CEFUrlRequestClientComponent1RequestComplete(Sender: TObject; const request: ICefUrlRequest); procedure CEFUrlRequestClientComponent1CreateURLRequest(Sender: TObject); - procedure Button1Click(Sender: TObject); - private FMemStream : TMemoryStream; FCanClose : boolean; @@ -134,7 +136,8 @@ implementation // 1- Set CanClose to FALSE in the TForm.OnCloseQuery event and set FClosing to TRUE. // 2- The next time TCEFUrlRequestClientComponent.OnDownloadProgress is executed we call request.Cancel, which triggers the // TCEFUrlRequestClientComponent.OnRequestComplete event. -// 3- in the TCEFUrlRequestClientComponent.OnRequestComplete event we set FCanClose to TRUE and send WM_CLOSE to the form. +// 3- in the TCEFUrlRequestClientComponent.OnRequestComplete event we call TCEFSentinel.Start, which will trigger TCEFSentinel.OnClose when the renderer processes are closed. +// 4- TCEFSentinel.OnClose sets FCanClose := True and sends WM_CLOSE to the form. uses ShellApi, @@ -222,6 +225,12 @@ begin ShellExecute(0, 'open', 'https://ptsv2.com/t/cef4delphi', nil, nil, SW_SHOWNORMAL); end; +procedure TURLRequestFrm.CEFSentinel1Close(Sender: TObject); +begin + FCanClose := True; + PostMessage(Handle, WM_CLOSE, 0, 0); +end; + procedure TURLRequestFrm.CEFUrlRequestClientComponent1CreateURLRequest(Sender: TObject); begin if FSendingGET then @@ -345,10 +354,7 @@ begin // Use request.response here to get a ICefResponse interface with all the response headers, status, error code, etc. if FClosing then - begin - FCanClose := True; - PostMessage(Handle, WM_CLOSE, 0, 0); - end + CEFSentinel1.Start else if (request <> nil) and (request.RequestStatus = UR_SUCCESS) then PostMessage(Handle, URLREQUEST_SUCCESS, 0, 0) diff --git a/demos/Lazarus/DOMVisitor/uDOMVisitor.pas b/demos/Lazarus/DOMVisitor/uDOMVisitor.pas index d27d268c..ab682af8 100644 --- a/demos/Lazarus/DOMVisitor/uDOMVisitor.pas +++ b/demos/Lazarus/DOMVisitor/uDOMVisitor.pas @@ -218,7 +218,7 @@ end; procedure DOMVisitor_OnDocAvailable(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument); var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; begin // This function is called from a different process. // document is only valid inside this function. @@ -239,21 +239,33 @@ begin // Sending back some custom results to the browser process // Notice that the DOMVISITOR_MSGNAME_PARTIAL message name needs to be recognized in // Chromium1ProcessMessageReceived - msg := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_PARTIAL); - msg.ArgumentList.SetString(0, 'document.Title : ' + document.Title); - frame.SendProcessMessage(PID_BROWSER, msg); + try + TempMessage := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_PARTIAL); + TempMessage.ArgumentList.SetString(0, 'document.Title : ' + document.Title); + + if (frame <> nil) and frame.IsValid then + frame.SendProcessMessage(PID_BROWSER, TempMessage); + finally + TempMessage := nil; + end; end; procedure DOMVisitor_OnDocAvailableFullMarkup(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument); var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; begin // Sending back some custom results to the browser process // Notice that the DOMVISITOR_MSGNAME_FULL message name needs to be recognized in // Chromium1ProcessMessageReceived - msg := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_FULL); - msg.ArgumentList.SetString(0, document.Body.AsMarkup); - frame.SendProcessMessage(PID_BROWSER, msg); + try + TempMessage := TCefProcessMessageRef.New(DOMVISITOR_MSGNAME_FULL); + TempMessage.ArgumentList.SetString(0, document.Body.AsMarkup); + + if (frame <> nil) and frame.IsValid then + frame.SendProcessMessage(PID_BROWSER, TempMessage); + finally + TempMessage := nil; + end; end; procedure GlobalCEFApp_OnProcessMessageReceived(const browser : ICefBrowser; @@ -262,7 +274,6 @@ procedure GlobalCEFApp_OnProcessMessageReceived(const browser : ICefBrowse const message : ICefProcessMessage; var aHandled : boolean); var - TempFrame : ICefFrame; TempVisitor : TCefFastDomVisitor2; begin aHandled := False; @@ -271,12 +282,10 @@ begin begin if (message.name = RETRIEVEDOM_MSGNAME_PARTIAL) then begin - TempFrame := browser.MainFrame; - - if (TempFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempVisitor := TCefFastDomVisitor2.Create(browser, frame, DOMVisitor_OnDocAvailable); - TempFrame.VisitDom(TempVisitor); + frame.VisitDom(TempVisitor); end; aHandled := True; @@ -284,12 +293,10 @@ begin else if (message.name = RETRIEVEDOM_MSGNAME_FULL) then begin - TempFrame := browser.MainFrame; - - if (TempFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempVisitor := TCefFastDomVisitor2.Create(browser, frame, DOMVisitor_OnDocAvailableFullMarkup); - TempFrame.VisitDom(TempVisitor); + frame.VisitDom(TempVisitor); end; aHandled := True; diff --git a/demos/Lazarus/EditorBrowser/uEditorBrowser.pas b/demos/Lazarus/EditorBrowser/uEditorBrowser.pas index 5c5d2c56..0359c653 100644 --- a/demos/Lazarus/EditorBrowser/uEditorBrowser.pas +++ b/demos/Lazarus/EditorBrowser/uEditorBrowser.pas @@ -1,4 +1,4 @@ -// ************************************************************************ +// ************************************************************************ // ***************************** CEF4Delphi ******************************* // ************************************************************************ // @@ -246,7 +246,7 @@ procedure TForm1.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer); begin - if (frame <> nil) and not(frame.isMain) then exit; + if (frame <> nil) and (not(frame.IsValid) or not(frame.isMain)) then exit; // Enable the "designMode" for all loaded files to edit them EnableDesignMode; diff --git a/demos/Lazarus/JavaScript/JSEval/uJSEval.pas b/demos/Lazarus/JavaScript/JSEval/uJSEval.pas index 4bd5182b..fb226d36 100644 --- a/demos/Lazarus/JavaScript/JSEval/uJSEval.pas +++ b/demos/Lazarus/JavaScript/JSEval/uJSEval.pas @@ -1,4 +1,4 @@ -// ************************************************************************ +// ************************************************************************ // ***************************** CEF4Delphi ******************************* // ************************************************************************ // @@ -432,7 +432,8 @@ begin end; end; - pFrame.SendProcessMessage(PID_BROWSER, pAnswer); + if (pFrame <> nil) and pFrame.IsValid then + pFrame.SendProcessMessage(PID_BROWSER, pAnswer); end; procedure ParseBinaryValue(const pBrowser : ICefBrowser; const pFrame: ICefFrame; const aBinaryValue : ICefBinaryValue); @@ -476,7 +477,7 @@ begin TempString := 'Image size : ' + inttostr(TempSize) + #13 + #10 + 'Encoded image : ' + TempEncodedStream.DataString; - if pAnswer.ArgumentList.SetString(0, TempString) then + if (pFrame <> nil) and pFrame.IsValid and pAnswer.ArgumentList.SetString(0, TempString) then pFrame.SendProcessMessage(PID_BROWSER, pAnswer); end; end; @@ -512,9 +513,9 @@ begin begin TempScript := pMessage.ArgumentList.GetString(0); - if (length(TempScript) > 0) then + if (length(TempScript) > 0) and (pFrame <> nil) and pFrame.IsValid then begin - pV8Context := pBrowser.MainFrame.GetV8Context; + pV8Context := pFrame.GetV8Context; if pV8Context.Enter then begin diff --git a/demos/Lazarus/JavaScript/JSExtension/uJSExtension.pas b/demos/Lazarus/JavaScript/JSExtension/uJSExtension.pas index ca62af96..dd4aa142 100644 --- a/demos/Lazarus/JavaScript/JSExtension/uJSExtension.pas +++ b/demos/Lazarus/JavaScript/JSExtension/uJSExtension.pas @@ -388,7 +388,7 @@ begin case commandId of MINIBROWSER_CONTEXTMENU_SETJSEVENT : - if (browser <> nil) and (browser.MainFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempJSCode := 'document.body.addEventListener("mouseover", function(evt){'+ 'function getpath(n){'+ @@ -399,16 +399,16 @@ begin 'myextension.mouseover(getpath(evt.target))}'+ ')'; - browser.MainFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); + frame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); end; MINIBROWSER_CONTEXTMENU_JSVISITDOM : - if (browser <> nil) and (browser.MainFrame <> nil) then + if (frame <> nil) and frame.IsValid then begin TempJSCode := 'var testhtml = document.body.innerHTML; ' + 'myextension.sendresulttobrowser(testhtml, ' + quotedstr(CUSTOMNAME_MESSAGE_NAME) + ');'; - browser.MainFrame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); + frame.ExecuteJavaScript(TempJSCode, 'about:blank', 0); end; MINIBROWSER_CONTEXTMENU_SHOWDEVTOOLS : diff --git a/demos/Lazarus/JavaScript/JSExtension/uTestExtensionHandler.pas b/demos/Lazarus/JavaScript/JSExtension/uTestExtensionHandler.pas index a171f7b4..8c2c0b22 100644 --- a/demos/Lazarus/JavaScript/JSExtension/uTestExtensionHandler.pas +++ b/demos/Lazarus/JavaScript/JSExtension/uTestExtensionHandler.pas @@ -1,4 +1,4 @@ -// ************************************************************************ +// ************************************************************************ // ***************************** CEF4Delphi ******************************* // ************************************************************************ // @@ -69,35 +69,46 @@ function TTestExtensionHandler.Execute(const name : ustring; var retval : ICefv8Value; var exception : ustring): Boolean; var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; + TempFrame : ICefFrame; begin - if (name = 'mouseover') then - begin - if (length(arguments) > 0) and arguments[0].IsString then - begin - msg := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME); - msg.ArgumentList.SetString(0, arguments[0].GetStringValue); + Result := False; - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); - end; - - Result := True; - end - else - if (name = 'sendresulttobrowser') then + try + if (name = 'mouseover') then begin - if (length(arguments) > 1) and arguments[0].IsString and arguments[1].IsString then + if (length(arguments) > 0) and arguments[0].IsString then begin - msg := TCefProcessMessageRef.New(arguments[1].GetStringValue); - msg.ArgumentList.SetString(0, arguments[0].GetStringValue); + TempMessage := TCefProcessMessageRef.New(MOUSEOVER_MESSAGE_NAME); + TempMessage.ArgumentList.SetString(0, arguments[0].GetStringValue); - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); end; Result := True; end else - Result := False; + if (name = 'sendresulttobrowser') then + begin + if (length(arguments) > 1) and arguments[0].IsString and arguments[1].IsString then + begin + TempMessage := TCefProcessMessageRef.New(arguments[1].GetStringValue); + TempMessage.ArgumentList.SetString(0, arguments[0].GetStringValue); + + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); + end; + + Result := True; + end; + finally + TempMessage := nil; + end; end; end. diff --git a/demos/Lazarus/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas b/demos/Lazarus/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas index 4ecd1a85..45e28bba 100644 --- a/demos/Lazarus/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas +++ b/demos/Lazarus/JavaScript/JSExtensionWithFunction/uMyV8Handler.pas @@ -1,4 +1,4 @@ -// ************************************************************************ +// ************************************************************************ // ***************************** CEF4Delphi ******************************* // ************************************************************************ // @@ -63,19 +63,28 @@ function TMyV8Handler.Execute(const name : ustring; var retval : ICefv8Value; var exception : ustring): Boolean; var - msg: ICefProcessMessage; + TempMessage : ICefProcessMessage; + TempFrame : ICefFrame; begin - if (name = 'myfunc') then - begin - msg := TCefProcessMessageRef.New(TEST_MESSAGE_NAME); - msg.ArgumentList.SetString(0, 'Message received!'); - TCefv8ContextRef.Current.Browser.MainFrame.SendProcessMessage(PID_BROWSER, msg); + Result := False; - retval := TCefv8ValueRef.NewString('My Value!'); - Result := True; - end - else - Result := False; + try + if (name = 'myfunc') then + begin + TempMessage := TCefProcessMessageRef.New(TEST_MESSAGE_NAME); + TempMessage.ArgumentList.SetString(0, 'Message received!'); + + TempFrame := TCefv8ContextRef.Current.Browser.MainFrame; + + if (TempFrame <> nil) and TempFrame.IsValid then + TempFrame.SendProcessMessage(PID_BROWSER, TempMessage); + + retval := TCefv8ValueRef.NewString('My Value!'); + Result := True; + end; + finally + TempMessage := nil; + end; end; diff --git a/demos/Lazarus/MiniBrowser/uMiniBrowser.pas b/demos/Lazarus/MiniBrowser/uMiniBrowser.pas index bc76ff94..da90365c 100644 --- a/demos/Lazarus/MiniBrowser/uMiniBrowser.pas +++ b/demos/Lazarus/MiniBrowser/uMiniBrowser.pas @@ -1,4 +1,4 @@ -// ************************************************************************ +// ************************************************************************ // ***************************** CEF4Delphi ******************************* // ************************************************************************ // @@ -496,6 +496,7 @@ begin if Chromium1.IsSameBrowser(browser) and (frame <> nil) and + frame.IsValid and frame.IsMain then InspectRequest(request); end; @@ -568,8 +569,8 @@ begin end; MINIBROWSER_CONTEXTMENU_JSWRITEDOC : - if (browser <> nil) and (browser.MainFrame <> nil) then - browser.MainFrame.ExecuteJavaScript( + if (frame <> nil) and frame.IsValid then + frame.ExecuteJavaScript( 'var css = ' + chr(39) + '@page {size: A4; margin: 0;} @media print {html, body {width: 210mm; height: 297mm;}}' + chr(39) + '; ' + 'var style = document.createElement(' + chr(39) + 'style' + chr(39) + '); ' + 'style.type = ' + chr(39) + 'text/css' + chr(39) + '; ' + @@ -578,8 +579,8 @@ begin 'about:blank', 0); MINIBROWSER_CONTEXTMENU_JSPRINTDOC : - if (browser <> nil) and (browser.MainFrame <> nil) then - browser.MainFrame.ExecuteJavaScript('window.print();', 'about:blank', 0); + if (frame <> nil) and frame.IsValid then + frame.ExecuteJavaScript('window.print();', 'about:blank', 0); MINIBROWSER_CONTEXTMENU_UNMUTEAUDIO : Chromium1.AudioMuted := False; @@ -720,6 +721,8 @@ procedure TMiniBrowserFrm.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer); begin + if (frame = nil) or not(frame.IsValid) then exit; + if frame.IsMain then StatusPnl.Caption := 'main frame loaded : ' + quotedstr(frame.name) else @@ -902,6 +905,7 @@ begin if Chromium1.IsSameBrowser(browser) and (frame <> nil) and + frame.IsValid and frame.IsMain then InspectResponse(response); end; diff --git a/demos/Lazarus/PopupBrowser2/PopupBrowser2.lps b/demos/Lazarus/PopupBrowser2/PopupBrowser2.lps index 2e287d70..27cb990e 100644 --- a/demos/Lazarus/PopupBrowser2/PopupBrowser2.lps +++ b/demos/Lazarus/PopupBrowser2/PopupBrowser2.lps @@ -10,7 +10,7 @@ - + @@ -22,9 +22,12 @@ - - - + + + + + + @@ -35,10 +38,10 @@ - + - + @@ -52,11 +55,10 @@ - - - + + + - @@ -83,120 +85,120 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - - + + - - + + - - + + - + - + - - + + - - + + - + - - + + - - + + - + - + - + - + - + - + - + diff --git a/demos/Lazarus/PopupBrowser2/uMainForm.lfm b/demos/Lazarus/PopupBrowser2/uMainForm.lfm index d9739c2a..5bd2846e 100644 --- a/demos/Lazarus/PopupBrowser2/uMainForm.lfm +++ b/demos/Lazarus/PopupBrowser2/uMainForm.lfm @@ -1,7 +1,7 @@ object MainForm: TMainForm - Left = 101 + Left = 679 Height = 624 - Top = 120 + Top = 160 Width = 1038 Caption = 'Initializing browser. Please wait...' ClientHeight = 624 @@ -71,7 +71,7 @@ object MainForm: TMainForm top = 152 end object ApplicationProperties1: TApplicationProperties - left = 59 - top = 235 + left = 56 + top = 216 end end diff --git a/demos/Lazarus/PopupBrowser2/uMainForm.pas b/demos/Lazarus/PopupBrowser2/uMainForm.pas index 37340ef3..eb32a160 100644 --- a/demos/Lazarus/PopupBrowser2/uMainForm.pas +++ b/demos/Lazarus/PopupBrowser2/uMainForm.pas @@ -45,7 +45,7 @@ uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, SyncObjs, uCEFChromium, uCEFWindowParent, uCEFInterfaces, uCEFConstants, uCEFTypes, uChildForm, - uCEFWinControl, uCEFChromiumEvents; + uCEFWinControl, uCEFChromiumEvents, uCEFSentinel; const CEF_CREATENEXTCHILD = WM_APP + $A50; @@ -325,8 +325,7 @@ begin Chromium1.LoadURL(AddressEdt.Text); end; -procedure TMainForm.Chromium1BeforeClose(Sender: TObject; - const browser: ICefBrowser); +procedure TMainForm.Chromium1BeforeClose(Sender: TObject; const browser: ICefBrowser); begin FCanClose := True; PostMessage(Handle, WM_CLOSE, 0, 0); diff --git a/demos/Lazarus/PostInspectorBrowser/uPostInspectorBrowser.pas b/demos/Lazarus/PostInspectorBrowser/uPostInspectorBrowser.pas index b968c03a..faed5a1d 100644 --- a/demos/Lazarus/PostInspectorBrowser/uPostInspectorBrowser.pas +++ b/demos/Lazarus/PostInspectorBrowser/uPostInspectorBrowser.pas @@ -366,7 +366,9 @@ procedure TForm1.Chromium1BeforeResourceLoad(Sender: TObject; begin // This event is called before a resource request is loaded. // The request object may be modified. - HandleRequest(request, frame.IsMain); + if (frame <> nil) and frame.IsValid then + HandleRequest(request, frame.IsMain); + Result := RV_CONTINUE; end; diff --git a/source/uCEFChromium.pas b/source/uCEFChromium.pas index 24b0434b..fcd64c92 100644 --- a/source/uCEFChromium.pas +++ b/source/uCEFChromium.pas @@ -241,7 +241,7 @@ type // ICefRequestContextHandler FOnRequestContextInitialized : TOnRequestContextInitialized; FOnBeforePluginLoad : TOnBeforePluginLoad; - + // Custom FOnTextResultAvailable : TOnTextResultAvailableEvent; FOnPdfPrintFinished : TOnPdfPrintFinishedEvent; @@ -445,17 +445,17 @@ type procedure doOnRenderProcessTerminated(const browser: ICefBrowser; status: TCefTerminationStatus); virtual; // ICefResourceRequestHandler - function doOnBeforeResourceLoad(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const callback: ICefRequestCallback): TCefReturnValue; virtual; - procedure doOnGetResourceHandler(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; var aResourceHandler : ICefResourceHandler); virtual; - procedure doOnResourceRedirect(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; var newUrl: ustring); virtual; - function doOnResourceResponse(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse): Boolean; virtual; - procedure doOnGetResourceResponseFilter(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; var aResponseFilter: ICefResponseFilter); virtual; - procedure doOnResourceLoadComplete(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; status: TCefUrlRequestStatus; receivedContentLength: Int64); virtual; - procedure doOnProtocolExecution(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; var allowOsExecution: Boolean); virtual; - - // ICefCookieAccessFilter - function doCanSendCookie(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const cookie: PCefCookie): boolean; virtual; - function doCanSaveCookie(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; const cookie: PCefCookie): boolean; virtual; + function doOnBeforeResourceLoad(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const callback: ICefRequestCallback): TCefReturnValue; virtual; + procedure doOnGetResourceHandler(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; var aResourceHandler : ICefResourceHandler); virtual; + procedure doOnResourceRedirect(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; var newUrl: ustring); virtual; + function doOnResourceResponse(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse): Boolean; virtual; + procedure doOnGetResourceResponseFilter(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; var aResponseFilter: ICefResponseFilter); virtual; + procedure doOnResourceLoadComplete(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; status: TCefUrlRequestStatus; receivedContentLength: Int64); virtual; + procedure doOnProtocolExecution(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; var allowOsExecution: Boolean); virtual; + + // ICefCookieAccessFilter + function doCanSendCookie(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const cookie: PCefCookie): boolean; virtual; + function doCanSaveCookie(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; const response: ICefResponse; const cookie: PCefCookie): boolean; virtual; // ICefDialogHandler function doOnFileDialog(const browser: ICefBrowser; mode: TCefFileDialogMode; const title, defaultFilePath: ustring; const acceptFilters: TStrings; selectedAcceptFilter: Integer; const callback: ICefFileDialogCallback): Boolean; virtual; @@ -486,11 +486,11 @@ type procedure doOnFindResult(const browser: ICefBrowser; identifier, count: Integer; const selectionRect: PCefRect; activeMatchOrdinal: Integer; finalUpdate: Boolean); virtual; // ICefRequestContextHandler - procedure doOnRequestContextInitialized(const request_context: ICefRequestContext); virtual; - function doOnBeforePluginLoad(const mimeType, pluginUrl:ustring; isMainFrame : boolean; const topOriginUrl: ustring; const pluginInfo: ICefWebPluginInfo; var pluginPolicy: TCefPluginPolicy): Boolean; virtual; - procedure doGetResourceRequestHandler(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; is_navigation, is_download: boolean; const request_initiator: ustring; var disable_default_handling: boolean; var aResourceRequestHandler : ICefResourceRequestHandler); virtual; + procedure doOnRequestContextInitialized(const request_context: ICefRequestContext); virtual; + function doOnBeforePluginLoad(const mimeType, pluginUrl:ustring; isMainFrame : boolean; const topOriginUrl: ustring; const pluginInfo: ICefWebPluginInfo; var pluginPolicy: TCefPluginPolicy): Boolean; virtual; + procedure doGetResourceRequestHandler(const browser: ICefBrowser; const frame: ICefFrame; const request: ICefRequest; is_navigation, is_download: boolean; const request_initiator: ustring; var disable_default_handling: boolean; var aResourceRequestHandler : ICefResourceRequestHandler); virtual; - // Custom + // Custom procedure doCookiesDeleted(numDeleted : integer); virtual; procedure doPdfPrintFinished(aResultOK : boolean); virtual; procedure doTextResultAvailable(const aText : ustring); virtual; @@ -502,7 +502,7 @@ type procedure doDownloadImageFinished(const imageUrl: ustring; httpStatusCode: Integer; const image: ICefImage); virtual; procedure doOnCookiesStoreFlushed; virtual; procedure doCertificateExceptionsCleared; virtual; - procedure doHttpAuthCredentialsCleared; virtual; + procedure doHttpAuthCredentialsCleared; virtual; procedure doAllConnectionsClosed; virtual; function MustCreateLoadHandler : boolean; virtual; function MustCreateFocusHandler : boolean; virtual; @@ -554,7 +554,7 @@ type function DeleteCookies(const url : ustring = ''; const cookieName : ustring = '') : boolean; function FlushCookieStore(aFlushImmediately : boolean = True) : boolean; function ClearCertificateExceptions(aClearImmediately : boolean = True) : boolean; - function ClearHttpAuthCredentials(aClearImmediately : boolean = True) : boolean; + function ClearHttpAuthCredentials(aClearImmediately : boolean = True) : boolean; function CloseAllConnections(aCloseImmediately : boolean = True) : boolean; procedure RetrieveHTML(const aFrameName : ustring = ''); overload; procedure RetrieveHTML(const aFrame : ICefFrame); overload; @@ -636,8 +636,8 @@ type procedure DragSourceSystemDragEnded; procedure IMESetComposition(const text: ustring; const underlines : TCefCompositionUnderlineDynArray; const replacement_range, selection_range : PCefRange); - procedure IMECommitText(const text: ustring; const replacement_range : PCefRange; relative_cursor_pos : integer); - procedure IMEFinishComposingText(keep_selection : boolean); + procedure IMECommitText(const text: ustring; const replacement_range : PCefRange; relative_cursor_pos : integer); + procedure IMEFinishComposingText(keep_selection : boolean); procedure IMECancelComposition; @@ -1553,7 +1553,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Copy; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Copy; end; end; @@ -1566,7 +1566,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Paste; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Paste; end; end; @@ -1579,7 +1579,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Cut; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Cut; end; end; @@ -1592,7 +1592,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Undo; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Undo; end; end; @@ -1605,7 +1605,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Redo; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Redo; end; end; @@ -1618,7 +1618,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Del; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Del; end; end; @@ -1631,7 +1631,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.SelectAll; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.SelectAll; end; end; @@ -1743,13 +1743,13 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadUrl(aURL); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadUrl(aURL); end; end; procedure TChromium.LoadURL(const aURL : ustring; const aFrame : ICefFrame); begin - if Initialized and (aFrame <> nil) then aFrame.LoadUrl(aURL); + if Initialized and (aFrame <> nil) and aFrame.IsValid then aFrame.LoadUrl(aURL); end; procedure TChromium.LoadURL(const aURL : ustring; const aFrameIdentifier : int64); @@ -1763,7 +1763,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadUrl(aURL); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadUrl(aURL); end; end; @@ -1774,7 +1774,7 @@ begin if Initialized then begin TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadString(aString, aURL); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadString(aString, aURL); end; end; @@ -1785,7 +1785,7 @@ begin if Initialized then begin TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadRequest(aRequest); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadRequest(aRequest); end; end; @@ -1975,7 +1975,7 @@ begin if Initialized then begin TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then Result := TempFrame.URL; + if (TempFrame <> nil) and TempFrame.IsValid then Result := TempFrame.URL; end; end; @@ -2382,9 +2382,9 @@ begin end; // If aClearImmediately is false then OnHttpAuthCredentialsCleared is triggered when the credeintials are cleared -function TChromium.ClearHttpAuthCredentials(aClearImmediately : boolean) : boolean; -var - TempCallback : ICefCompletionCallback; +function TChromium.ClearHttpAuthCredentials(aClearImmediately : boolean) : boolean; +var + TempCallback : ICefCompletionCallback; begin Result := False; @@ -2400,9 +2400,9 @@ begin finally TempCallback := nil; end; -end; - -// If aCloseImmediately is false then OnAllConnectionsClosed is triggered when the connections are closed +end; + +// If aCloseImmediately is false then OnAllConnectionsClosed is triggered when the connections are closed function TChromium.CloseAllConnections(aCloseImmediately : boolean) : boolean; var TempCallback : ICefCompletionCallback; @@ -2436,7 +2436,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetSource(TempVisitor); @@ -2450,7 +2450,7 @@ procedure TChromium.RetrieveHTML(const aFrame : ICefFrame); var TempVisitor : ICefStringVisitor; begin - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); aFrame.GetSource(TempVisitor); @@ -2471,7 +2471,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetSource(TempVisitor); @@ -2494,7 +2494,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetText(TempVisitor); @@ -2508,7 +2508,7 @@ procedure TChromium.RetrieveText(const aFrame : ICefFrame); var TempVisitor : ICefStringVisitor; begin - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); aFrame.GetText(TempVisitor); @@ -2529,7 +2529,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetText(TempVisitor); @@ -3277,11 +3277,11 @@ begin if assigned(FOnCertificateExceptionsCleared) then FOnCertificateExceptionsCleared(self); end; -procedure TChromium.doHttpAuthCredentialsCleared; -begin +procedure TChromium.doHttpAuthCredentialsCleared; +begin if assigned(FOnHttpAuthCredentialsCleared) then FOnHttpAuthCredentialsCleared(self); -end; - +end; + procedure TChromium.doAllConnectionsClosed; begin if assigned(FOnAllConnectionsClosed) then FOnAllConnectionsClosed(self); @@ -3375,7 +3375,7 @@ begin end; function TChromium.MustCreateResourceRequestHandler : boolean; -begin +begin Result := assigned(FOnBeforeResourceLoad) or assigned(FOnGetResourceHandler) or assigned(FOnResourceRedirect) or @@ -3385,7 +3385,7 @@ begin assigned(FOnProtocolExecution) or MustCreateCookieAccessFilter; end; - + function TChromium.MustCreateCookieAccessFilter : boolean; begin Result := assigned(FOnCanSendCookie) or @@ -3427,7 +3427,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.ExecuteJavaScript(aCode, aScriptURL, aStartLine); end; except @@ -3439,7 +3439,7 @@ end; procedure TChromium.ExecuteJavaScript(const aCode, aScriptURL : ustring; const aFrame : ICefFrame; aStartLine : integer); begin try - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then aFrame.ExecuteJavaScript(aCode, aScriptURL, aStartLine); except on e : exception do @@ -3459,7 +3459,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.ExecuteJavaScript(aCode, aScriptURL, aStartLine); end; except @@ -3628,11 +3628,11 @@ begin // TempAction values // ----------------- - // cbaCancel : stop closing the browser - // cbaClose : continue closing the browser - // cbaDelay : stop closing the browser momentarily. Used when the application - // needs to execute some custom processes before closing the - // browser. This is usually needed to destroy a TCEFWindowParent + // cbaCancel : stop closing the browser + // cbaClose : continue closing the browser + // cbaDelay : stop closing the browser momentarily. Used when the application + // needs to execute some custom processes before closing the + // browser. This is usually needed to destroy a TCEFWindowParent // in the main thread before closing the browser. if Assigned(FOnClose) then FOnClose(Self, browser, TempAction); @@ -3902,31 +3902,31 @@ begin if assigned(FOnRequestContextInitialized) then FOnRequestContextInitialized(self, request_context); end; -function TChromium.doOnBeforePluginLoad(const mimeType : ustring; - const pluginUrl : ustring; - isMainFrame : boolean; - const topOriginUrl : ustring; - const pluginInfo : ICefWebPluginInfo; - var pluginPolicy : TCefPluginPolicy): Boolean; -begin +function TChromium.doOnBeforePluginLoad(const mimeType : ustring; + const pluginUrl : ustring; + isMainFrame : boolean; + const topOriginUrl : ustring; + const pluginInfo : ICefWebPluginInfo; + var pluginPolicy : TCefPluginPolicy): Boolean; +begin Result := False; if assigned(FOnBeforePluginLoad) then FOnBeforePluginLoad(self, mimeType, pluginUrl, isMainFrame, topOriginUrl, pluginInfo, pluginPolicy, Result); -end; - -procedure TChromium.doGetResourceRequestHandler(const browser : ICefBrowser; - const frame : ICefFrame; - const request : ICefRequest; - is_navigation : boolean; - is_download : boolean; - const request_initiator : ustring; - var disable_default_handling : boolean; - var aResourceRequestHandler : ICefResourceRequestHandler); -begin +end; + +procedure TChromium.doGetResourceRequestHandler(const browser : ICefBrowser; + const frame : ICefFrame; + const request : ICefRequest; + is_navigation : boolean; + is_download : boolean; + const request_initiator : ustring; + var disable_default_handling : boolean; + var aResourceRequestHandler : ICefResourceRequestHandler); +begin disable_default_handling := False; aResourceRequestHandler := nil; -end; +end; procedure TChromium.doOnFullScreenModeChange(const browser: ICefBrowser; fullscreen: Boolean); begin @@ -3967,11 +3967,11 @@ begin if assigned(FOnCanSendCookie) then FOnCanSendCookie(self, browser, frame, request, cookie, Result); end; -function TChromium.doCanSaveCookie(const browser : ICefBrowser; - const frame : ICefFrame; - const request : ICefRequest; - const response : ICefResponse; - const cookie : PCefCookie): boolean; +function TChromium.doCanSaveCookie(const browser : ICefBrowser; + const frame : ICefFrame; + const request : ICefRequest; + const response : ICefResponse; + const cookie : PCefCookie): boolean; begin Result := True; @@ -4095,10 +4095,10 @@ begin end; procedure TChromium.doOnGetResourceRequestHandler(const browser : ICefBrowser; - const frame : ICefFrame; - const request : ICefRequest; - is_navigation : boolean; - is_download : boolean; + const frame : ICefFrame; + const request : ICefRequest; + is_navigation : boolean; + is_download : boolean; const request_initiator : ustring; var disable_default_handling : boolean; var aResourceRequestHandler : ICefResourceRequestHandler; @@ -4602,7 +4602,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.SendProcessMessage(targetProcess, ProcMessage); end; except @@ -4614,7 +4614,7 @@ end; procedure TChromium.SendProcessMessage(targetProcess: TCefProcessId; const ProcMessage: ICefProcessMessage; const aFrame : ICefFrame); begin try - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then aFrame.SendProcessMessage(targetProcess, ProcMessage); except on e : exception do @@ -4634,7 +4634,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.SendProcessMessage(targetProcess, ProcMessage); end; except @@ -4657,7 +4657,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then Result := TempFrame.CreateUrlRequest(request, client); end; except @@ -4671,7 +4671,7 @@ begin Result := nil; try - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then Result := aFrame.CreateUrlRequest(request, client); except on e : exception do @@ -4693,7 +4693,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then Result := TempFrame.CreateUrlRequest(request, client); end; except @@ -4741,19 +4741,19 @@ begin FBrowser.Host.IMESetComposition(text, underlines, replacement_range, selection_range); end; -procedure TChromium.IMECommitText(const text : ustring; - const replacement_range : PCefRange; - relative_cursor_pos : integer); -begin +procedure TChromium.IMECommitText(const text : ustring; + const replacement_range : PCefRange; + relative_cursor_pos : integer); +begin if Initialized then FBrowser.Host.IMECommitText(text, replacement_range, relative_cursor_pos); -end; - -procedure TChromium.IMEFinishComposingText(keep_selection : boolean); -begin +end; + +procedure TChromium.IMEFinishComposingText(keep_selection : boolean); +begin if Initialized then FBrowser.Host.IMEFinishComposingText(keep_selection); -end; - +end; + procedure TChromium.IMECancelComposition; begin if Initialized then FBrowser.Host.IMECancelComposition; diff --git a/source/uCEFFMXChromium.pas b/source/uCEFFMXChromium.pas index f07bba7f..b249b1c8 100644 --- a/source/uCEFFMXChromium.pas +++ b/source/uCEFFMXChromium.pas @@ -1352,7 +1352,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Copy; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Copy; end; end; @@ -1365,7 +1365,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Paste; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Paste; end; end; @@ -1378,7 +1378,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Cut; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Cut; end; end; @@ -1391,7 +1391,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Undo; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Undo; end; end; @@ -1404,7 +1404,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Redo; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Redo; end; end; @@ -1417,7 +1417,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.Del; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.Del; end; end; @@ -1430,7 +1430,7 @@ begin TempFrame := FBrowser.FocusedFrame; if (TempFrame = nil) then TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.SelectAll; + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.SelectAll; end; end; @@ -1542,13 +1542,13 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadUrl(aURL); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadUrl(aURL); end; end; procedure TFMXChromium.LoadURL(const aURL : ustring; const aFrame : ICefFrame); begin - if Initialized and (aFrame <> nil) then aFrame.LoadUrl(aURL); + if Initialized and (aFrame <> nil) and aFrame.IsValid then aFrame.LoadUrl(aURL); end; procedure TFMXChromium.LoadURL(const aURL : ustring; const aFrameIdentifier : int64); @@ -1562,7 +1562,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadUrl(aURL); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadUrl(aURL); end; end; @@ -1573,7 +1573,7 @@ begin if Initialized then begin TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadString(aString, aURL); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadString(aString, aURL); end; end; @@ -1584,7 +1584,7 @@ begin if Initialized then begin TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then TempFrame.LoadRequest(aRequest); + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.LoadRequest(aRequest); end; end; @@ -1774,7 +1774,7 @@ begin if Initialized then begin TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then Result := TempFrame.URL; + if (TempFrame <> nil) and TempFrame.IsValid then Result := TempFrame.URL; end; end; @@ -2235,7 +2235,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetSource(TempVisitor); @@ -2249,7 +2249,7 @@ procedure TFMXChromium.RetrieveHTML(const aFrame : ICefFrame); var TempVisitor : ICefStringVisitor; begin - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); aFrame.GetSource(TempVisitor); @@ -2270,7 +2270,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetSource(TempVisitor); @@ -2293,7 +2293,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetText(TempVisitor); @@ -2307,7 +2307,7 @@ procedure TFMXChromium.RetrieveText(const aFrame : ICefFrame); var TempVisitor : ICefStringVisitor; begin - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); aFrame.GetText(TempVisitor); @@ -2328,7 +2328,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then try TempVisitor := TCustomCefStringVisitor.Create(self); TempFrame.GetText(TempVisitor); @@ -3157,7 +3157,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.ExecuteJavaScript(aCode, aScriptURL, aStartLine); end; except @@ -3169,7 +3169,7 @@ end; procedure TFMXChromium.ExecuteJavaScript(const aCode, aScriptURL : ustring; const aFrame : ICefFrame; aStartLine : integer); begin try - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then aFrame.ExecuteJavaScript(aCode, aScriptURL, aStartLine); except on e : exception do @@ -3189,7 +3189,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.ExecuteJavaScript(aCode, aScriptURL, aStartLine); end; except @@ -4305,7 +4305,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.SendProcessMessage(targetProcess, ProcMessage); end; except @@ -4317,7 +4317,7 @@ end; procedure TFMXChromium.SendProcessMessage(targetProcess: TCefProcessId; const ProcMessage: ICefProcessMessage; const aFrame : ICefFrame); begin try - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then aFrame.SendProcessMessage(targetProcess, ProcMessage); except on e : exception do @@ -4337,7 +4337,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then TempFrame.SendProcessMessage(targetProcess, ProcMessage); end; except @@ -4360,7 +4360,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then Result := TempFrame.CreateUrlRequest(request, client); end; except @@ -4374,7 +4374,7 @@ begin Result := nil; try - if Initialized and (aFrame <> nil) then + if Initialized and (aFrame <> nil) and aFrame.IsValid then Result := aFrame.CreateUrlRequest(request, client); except on e : exception do @@ -4396,7 +4396,7 @@ begin else TempFrame := FBrowser.MainFrame; - if (TempFrame <> nil) then + if (TempFrame <> nil) and TempFrame.IsValid then Result := TempFrame.CreateUrlRequest(request, client); end; except diff --git a/source/uCEFMiscFunctions.pas b/source/uCEFMiscFunctions.pas index a4187272..8bffb48e 100644 --- a/source/uCEFMiscFunctions.pas +++ b/source/uCEFMiscFunctions.pas @@ -241,6 +241,9 @@ function DeleteDirContents(const aDirectory : string; const aExcludeFiles : TStr function DeleteFileList(const aFileList : TStringList) : boolean; function MoveFileList(const aFileList : TStringList; const aSrcDirectory, aDstDirectory : string) : boolean; +function CefGetDataURI(const aString, aMimeType : ustring) : ustring; overload; +function CefGetDataURI(aData : pointer; aSize : integer; const aMimeType : ustring; const aCharset : ustring = '') : ustring; overload; + implementation uses @@ -2132,4 +2135,25 @@ begin end; end; +function CefGetDataURI(const aString, aMimeType : ustring) : ustring; +var + TempUTF : AnsiString; +begin + TempUTF := UTF8Encode(aString); + + if (length(TempUTF) > 0) then + Result := CefGetDataURI(@TempUTF[1], length(TempUTF), aMimeType, 'utf-8') + else + Result := ''; +end; + +function CefGetDataURI(aData : pointer; aSize : integer; const aMimeType, aCharset : ustring) : ustring; +begin + Result := 'data:' + aMimeType; + + if (length(aCharset) > 0) then Result := Result + ';charset=' + aCharset; + + Result := Result + ';base64,' + CefURIEncode(CefBase64Encode(aData, aSize), false); +end; + end. diff --git a/source/uCEFRequestHandler.pas b/source/uCEFRequestHandler.pas index 0df7a1f5..d5f9667b 100644 --- a/source/uCEFRequestHandler.pas +++ b/source/uCEFRequestHandler.pas @@ -163,8 +163,8 @@ begin Result := nil; TempResourceRequestHandler := nil; TempObject := CefGetObject(self); - TempDisableDefHandling := disable_default_handling^ <> 0; - + TempDisableDefHandling := disable_default_handling^ <> 0; + if (TempObject <> nil) and (TempObject is TCefRequestHandlerOwn) then try TCefRequestHandlerOwn(TempObject).GetResourceRequestHandler(TCefBrowserRef.UnWrap(browser), @@ -485,8 +485,8 @@ end; procedure TCustomRequestHandler.InitializeVars; begin - FResourceRequestHandler := nil; - FEvents := nil; + FResourceRequestHandler := nil; + FEvents := nil; end; function TCustomRequestHandler.GetAuthCredentials(const browser : ICefBrowser; @@ -552,32 +552,32 @@ var TempUseInternalHandler : boolean; begin if (FEvents <> nil) then - begin - TempUseInternalHandler := True; - - IChromiumEvents(FEvents).doOnGetResourceRequestHandler(browser, frame, request, - is_navigation, is_download, - request_initiator, - disable_default_handling, - aResourceRequestHandler, - TempUseInternalHandler); - - if TempUseInternalHandler then - begin - if (FResourceRequestHandler <> nil) then - aResourceRequestHandler := FResourceRequestHandler - else - aResourceRequestHandler := nil; - end; - end - else + begin + TempUseInternalHandler := True; + + IChromiumEvents(FEvents).doOnGetResourceRequestHandler(browser, frame, request, + is_navigation, is_download, + request_initiator, + disable_default_handling, + aResourceRequestHandler, + TempUseInternalHandler); + + if TempUseInternalHandler then + begin + if (FResourceRequestHandler <> nil) then + aResourceRequestHandler := FResourceRequestHandler + else + aResourceRequestHandler := nil; + end; + end + else inherited GetResourceRequestHandler(browser, frame, request, is_navigation, is_download, request_initiator, disable_default_handling, aResourceRequestHandler); end; - + function TCustomRequestHandler.OnSelectClientCertificate(const browser : ICefBrowser; isProxy : boolean; const host : ustring; diff --git a/update_CEF4Delphi.json b/update_CEF4Delphi.json index 21efc087..80e36aae 100644 --- a/update_CEF4Delphi.json +++ b/update_CEF4Delphi.json @@ -1,8 +1,8 @@ { "UpdateLazPackages" : [ { - "ForceNotify" : false, - "InternalVersion" : 42, + "ForceNotify" : true, + "InternalVersion" : 43, "Name" : "cef4delphi_lazarus.lpk", "Version" : "77.1.13.0" }