From 7f870db945db29c447555724d200fed281791f6e Mon Sep 17 00:00:00 2001 From: Alex Maitland Date: Fri, 10 Sep 2021 14:24:42 +1000 Subject: [PATCH] Core - FrameHandler track frame lifecycle - FrameHandler now tracks frame creation and removal and reuses the IFrame reference - CefFrameWrapper no longer throws exception if accessing Identifier for invalid frame, this appears to be a valid use case now which makes sense otherwise we'd never be able to identify the frame. Resolves #3588 --- .../Internals/CefFrameWrapper.cpp | 1 - .../BrowserTabUserControl.cs | 1 + CefSharp/Handler/FrameHandler.cs | 36 ++++++++++++++++--- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CefSharp.Core.Runtime/Internals/CefFrameWrapper.cpp b/CefSharp.Core.Runtime/Internals/CefFrameWrapper.cpp index 987123dcce..0d10be063d 100644 --- a/CefSharp.Core.Runtime/Internals/CefFrameWrapper.cpp +++ b/CefSharp.Core.Runtime/Internals/CefFrameWrapper.cpp @@ -311,7 +311,6 @@ String^ CefFrameWrapper::Name::get() Int64 CefFrameWrapper::Identifier::get() { ThrowIfDisposed(); - ThrowIfFrameInvalid(); return _frame->GetIdentifier(); } diff --git a/CefSharp.WinForms.Example/BrowserTabUserControl.cs b/CefSharp.WinForms.Example/BrowserTabUserControl.cs index da21f8ae1c..c1557f75ed 100644 --- a/CefSharp.WinForms.Example/BrowserTabUserControl.cs +++ b/CefSharp.WinForms.Example/BrowserTabUserControl.cs @@ -42,6 +42,7 @@ public BrowserTabUserControl(Action openNewTab, string url, bool m browser.JsDialogHandler = new JsDialogHandler(); browser.DownloadHandler = new DownloadHandler(); browser.AudioHandler = new CefSharp.Handler.AudioHandler(); + browser.FrameHandler = new CefSharp.Handler.FrameHandler(); if (multiThreadedMessageLoopEnabled) { diff --git a/CefSharp/Handler/FrameHandler.cs b/CefSharp/Handler/FrameHandler.cs index e4ad69b947..59cc26183f 100644 --- a/CefSharp/Handler/FrameHandler.cs +++ b/CefSharp/Handler/FrameHandler.cs @@ -2,6 +2,8 @@ // // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. +using System.Collections.Generic; + namespace CefSharp.Handler { /// @@ -10,10 +12,16 @@ namespace CefSharp.Handler /// public class FrameHandler : IFrameHandler { + private Dictionary frames = new Dictionary(); + /// void IFrameHandler.OnFrameAttached(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame) { - OnFrameAttached(chromiumWebBrowser, browser, frame); + //If we have a reference to the frame then we'll reuse that for memory management purposes + //The frame param massed on here is stack allocated so will be disposed when out of scope. + var storedFrame = GetFrameById(frame.Identifier); + + OnFrameAttached(chromiumWebBrowser, browser, storedFrame ?? frame); } /// @@ -25,12 +33,14 @@ void IFrameHandler.OnFrameAttached(IWebBrowser chromiumWebBrowser, IBrowser brow /// the frame object protected virtual void OnFrameAttached(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame) { - + } /// void IFrameHandler.OnFrameCreated(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame) { + frames.Add(frame.Identifier, frame); + OnFrameCreated(chromiumWebBrowser, browser, frame); } @@ -45,12 +55,14 @@ void IFrameHandler.OnFrameCreated(IWebBrowser chromiumWebBrowser, IBrowser brows /// the frame object protected virtual void OnFrameCreated(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame) { - + } /// void IFrameHandler.OnFrameDetached(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame) { + frames.Remove(frame.Identifier); + OnFrameDetached(chromiumWebBrowser, browser, frame); } @@ -66,13 +78,17 @@ void IFrameHandler.OnFrameDetached(IWebBrowser chromiumWebBrowser, IBrowser brow /// the frame object protected virtual void OnFrameDetached(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame) { - + } /// void IFrameHandler.OnMainFrameChanged(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame oldFrame, IFrame newFrame) { - OnMainFrameChanged(chromiumWebBrowser, browser, oldFrame, newFrame); + //If we have a reference to the frame then we'll reuse that for memory management purposes + //The frame param massed on here is stack allocated so will be disposed when out of scope. + var storedFrame = newFrame == null ? null : GetFrameById(newFrame.Identifier); + + OnMainFrameChanged(chromiumWebBrowser, browser, oldFrame, storedFrame ?? newFrame); } /// @@ -101,5 +117,15 @@ protected virtual void OnMainFrameChanged(IWebBrowser chromiumWebBrowser, IBrows { } + + private IFrame GetFrameById(long frameId) + { + if(frames.TryGetValue(frameId, out var frame)) + { + return frame; + } + + return null; + } } }