// Copyright © 2021 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
namespace CefSharp.Handler
{
///
/// Default implementation of . This class provides default implementations of the methods from
/// , therefore providing a convenience base class for a custom implementation.
/// You need only override the methods you require.
/// IMPORTANT: behaviour of this implementation differs
/// from the default, the WM_CLOSE message is only sent by default for popups (return false), for the main browser
/// we return true to cancel this behaviour.
///
///
public class LifeSpanHandler : ILifeSpanHandler
{
///
bool ILifeSpanHandler.DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
return DoClose(chromiumWebBrowser, browser);
}
///
/// Called when a browser has recieved a request to close. This may result
/// directly from a call to CefBrowserHost::CloseBrowser() or indirectly if the
/// browser is a top-level OS window created by CEF and the user attempts to
/// close the window. This method will be called after the JavaScript
/// 'onunload' event has been fired. It will not be called for browsers after
/// the associated OS window has been destroyed (for those browsers it is no
/// longer possible to cancel the close).
///
/// If CEF created an OS window for the browser returning false will send an OS
/// close notification to the browser window's top-level owner (e.g. WM_CLOSE
/// on Windows). If no OS window exists (window rendering disabled) returning false
/// will cause the browser object to be destroyed immediately. Return true if
/// the browser is parented to another window and that other window needs to
/// receive close notification via some non-standard technique.
///
/// !!IMPORTANT!!: Behaviour of this implementation differs from the default,
/// the WM_CLOSE message is only sent by default for popups (return false),
/// for the main browser we return true to cancel this behaviour.
///
/// If an application provides its own top-level window it should handle OS
/// close notifications by calling CefBrowserHost::CloseBrowser(false) instead
/// of immediately closing (see the example below). This gives CEF an
/// opportunity to process the 'onbeforeunload' event and optionally cancel the
/// close before DoClose() is called.
///
/// The CefLifeSpanHandler::OnBeforeClose() method will be called immediately
/// before the browser object is destroyed. The application should only exit
/// after OnBeforeClose() has been called for all existing browsers.
///
/// If the browser represents a modal window and a custom modal loop
/// implementation was provided in CefLifeSpanHandler::RunModal() this callback
/// should be used to restore the opener window to a usable state.
///
/// By way of example consider what should happen during window close when the
/// browser is parented to an application-provided top-level OS window.
/// 1. User clicks the window close button which sends an OS close
/// notification (e.g. WM_CLOSE on Windows, performClose: on OS-X and
/// "delete_event" on Linux).
/// 2. Application's top-level window receives the close notification and:
/// A. Calls CefBrowserHost::CloseBrowser(false).
/// B. Cancels the window close.
/// 3. JavaScript 'onbeforeunload' handler executes and shows the close
/// confirmation dialog (which can be overridden via
/// CefJSDialogHandler::OnBeforeUnloadDialog()).
/// 4. User approves the close.
/// 5. JavaScript 'onunload' handler executes.
/// 6. Application's DoClose() handler is called. Application will:
/// A. Set a flag to indicate that the next close attempt will be allowed.
/// B. Return false.
/// 7. CEF sends an OS close notification.
/// 8. Application's top-level window receives the OS close notification and
/// allows the window to close based on the flag from #6B.
/// 9. Browser OS window is destroyed.
/// 10. Application's CefLifeSpanHandler::OnBeforeClose() handler is called and
/// the browser object is destroyed.
/// 11. Application exits by calling CefQuitMessageLoop() if no other browsers
/// exist.
///
/// the ChromiumWebBrowser control
/// The browser instance - check if IsDisposed as it's possible when the browser is disposing
/// For default behaviour return false
protected virtual bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
//For popups by default are created by CEF and need to be closed via the default behaviour
//(Sending a WM_CLOSE message)
if (browser.IsPopup)
{
return false;
}
//For the main browser NO WM_CLOSE message will be sent.
return true;
}
///
void ILifeSpanHandler.OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
OnAfterCreated(chromiumWebBrowser, browser);
}
///
/// Called after a new browser is created.
///
/// the ChromiumWebBrowser control
/// The browser instance
protected virtual void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
}
///
void ILifeSpanHandler.OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
OnBeforeClose(chromiumWebBrowser, browser);
}
///
/// Called before a CefBrowser window (either the main browser for ,
/// or one of its children)
///
/// the ChromiumWebBrowser control
/// The browser instance
protected virtual void OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
}
///
bool ILifeSpanHandler.OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
{
return OnBeforePopup(chromiumWebBrowser, browser, frame, targetUrl, targetFrameName, targetDisposition, userGesture, popupFeatures, windowInfo, browserSettings, ref noJavascriptAccess, out newBrowser);
}
///
/// Called before a popup window is created. By default the popup (browser) is created in a new native window.
///
/// the ChromiumWebBrowser control
/// The browser instance that launched this popup.
/// The HTML frame that launched this popup.
/// The URL of the popup content. (This may be empty/null)
/// The name of the popup. (This may be empty/null)
/// The value indicates where the user intended to
/// open the popup (e.g. current tab, new tab, etc)
/// The value will be true if the popup was opened via explicit user gesture
/// (e.g. clicking a link) or false if the popup opened automatically (e.g. via the DomContentLoaded event).
/// structure contains additional information about the requested popup window
/// window information
/// browser settings, defaults to source browsers
/// value indicates whether the new browser window should be scriptable
/// and in the same process as the source browser.
///
/// EXPERIMENTAL - Low level this allows for assigning the CefClient instance associated with the new ChromiumWebBrowser instance to the CefClient param of the CefLifeSpanHandler::OnBeforeBrowser method.
/// This allows for all the handlers, LifeSpanHandler, DisplayHandler, etc to be associated with the CefClient of the new ChromiumWebBrowser instance to be associated with the popup (browser).
/// WPF/WinForms specific code is still required to host the popup (browser) in the new ChromiumWebBrowser instance.
/// Set to null for default behaviour. If you return true (cancel popup creation) then his property **MUST** be null, an exception will be thrown otherwise.
///
///
/// By default the popup (browser) is opened in a new native window. If you return true then creation of the popup (browser) is cancelled, no further action will occur.
/// Otherwise return false to allow creation of the popup (browser).
///
///
/// If you return true and set to not null then an exception will be thrown as creation of the popup (browser) was cancelled.
/// WinForms - To host the popup (browser) in a TAB/Custom Window see https://github.com/cefsharp/CefSharp/wiki/General-Usage#winforms---hosting-popup-using-tab-control for an easy method.
/// WPF - For an example of hosting the popup (browser) in a custom window see https://github.com/cefsharp/CefSharp/wiki/General-Usage#wpf---hosting-popup-in-new-window-experimental
/// Same can be applied for hosting the popup in a TAB.
/// This method is still EXPERIMENTAL and will likely require upstream bug fixes in CEF (https://bitbucket.org/chromiumembedded/cef).
///
protected virtual bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
{
newBrowser = null;
return false;
}
}
}