/// <summary>
        /// Called when the browser is done loading a frame. The |frame| value
        /// will never be empty -- call the IsMain() method to check if this
        /// frame is the main frame. Multiple frames may be loading at the same
        /// time. Sub-frames may start or continue loading after the main frame
        /// load has ended. This method will always be called for all frames
        /// irrespective of whether the request completes successfully.
        /// </summary>
        private void on_load_end(cef_load_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, int httpStatusCode)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            this.OnLoadEnd(m_browser, m_frame, httpStatusCode);
        }
        /// <summary>
        /// Called when a frame's address has changed.
        /// </summary>
        private void on_address_change(cef_display_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, /*const*/ cef_string_t* url)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_url = cef_string_t.ToString(url);

            this.OnAddressChange(m_browser, m_frame, m_url);
        }
        /// <summary>
        /// Called immediately before the V8 context for a frame is released. No
        /// references to the context should be kept after this function is
        /// called.
        /// </summary>
        private void on_context_released(cef_v8context_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_v8context_t* context)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_context = CefV8Context.From(context);

            this.OnContextReleased(m_browser, m_frame, m_context);
        }
        /// <summary>
        /// Called on the UI thread before a script extension is loaded.
        /// Return false to let the extension load normally.
        /// </summary>
        private int on_before_script_extension_load(cef_permission_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, /*const*/ cef_string_t* extensionName)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_extensionName = cef_string_t.ToString(extensionName);

            var handled = this.OnBeforeScriptExtensionLoad(m_browser, m_frame, m_extensionName);

            return handled ? 1 : 0;
        }
        /// <summary>
        /// Called  to run a JavaScript alert message. Return false to display
        /// the default alert or true if you displayed a custom alert.
        /// </summary>
        private int on_jsalert(cef_jsdialog_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, /*const*/ cef_string_t* message)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_message = cef_string_t.ToString(message);

            var handled = this.OnJSAlert(m_browser, m_frame, m_message);

            return handled ? 1 : 0;
        }
        /// <summary>
        /// Called for global uncaught exceptions. Execution of this callback is
        /// disabled by default. To enable set
        /// CefSettings.uncaught_exception_stack_size &gt; 0.
        /// </summary>
        private void on_uncaught_exception(cef_v8context_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_v8context_t* context, cef_v8exception_t* exception, cef_v8stack_trace_t* stackTrace)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_context = CefV8Context.From(context);
            var m_exception = CefV8Exception.From(exception);
            var m_stackTrace = CefV8StackTrace.From(stackTrace);

            this.OnUncaughtException(m_browser, m_frame, m_context, m_exception, m_stackTrace);
        }
        /// <summary>
        /// Called when a new node in the the browser gets focus. The |node|
        /// value may be empty if no specific node has gained focus. The node
        /// object passed to this method represents a snapshot of the DOM at the
        /// time this method is executed. DOM objects are only valid for the
        /// scope of this method. Do not keep references to or attempt to access
        /// any DOM objects outside the scope of this method.
        /// </summary>
        private void on_focused_node_changed(cef_focus_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_domnode_t* node)
        {
            ThrowIfObjectDisposed();

            var mBrowser = CefBrowser.From(browser);
            var mFrame = CefFrame.From(frame);
            var mNode = CefDomNode.FromOrDefault(node);

            // TODO: DOM nodes context
            this.OnFocusedNodeChanged(mBrowser, mFrame, mNode);

            if (mNode != null) mNode.Dispose();
        }
        /// <summary>
        /// Called when the browser fails to load a resource. |errorCode| is the
        /// error code number and |failedUrl| is the URL that failed to load. To
        /// provide custom error text assign the text to |errorText| and return
        /// true. Otherwise, return false for the default error text. See
        /// net\base\net_error_list.h for complete descriptions of the error
        /// codes.
        /// </summary>
        private int on_load_error(cef_load_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_handler_errorcode_t errorCode, /*const*/ cef_string_t* failedUrl, cef_string_t* errorText)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_failedUrl = cef_string_t.ToString(failedUrl);
            var m_errorText = cef_string_t.ToString(errorText);
            var c_errorText = m_errorText;
            var result = this.OnLoadError(m_browser, m_frame, (CefHandlerErrorCode)errorCode, m_failedUrl, ref m_errorText) ? 1 : 0;
            if ((object)c_errorText != (object)m_errorText)
            {
                cef_string_t.Copy(m_errorText, errorText);
            }
            return result;
        }
        /// <summary>
        /// Called to run a JavaScript confirm request. Return false to display
        /// the default alert or true if you displayed a custom alert. If you
        /// handled the alert set |retval| to true if the user accepted the
        /// confirmation.
        /// </summary>
        private int on_jsconfirm(cef_jsdialog_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, /*const*/ cef_string_t* message, int* retval)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_message = cef_string_t.ToString(message);
            bool m_retval;

            var handled = this.OnJSConfirm(m_browser, m_frame, m_message, out m_retval);

            if (handled)
            {
                *retval = m_retval ? 1 : 0;
            }

            return handled ? 1 : 0;
        }
        /// <summary>
        /// Called to format print headers and footers. |printInfo| contains
        /// platform- specific information about the printer context. |url| is
        /// the URL if the currently printing page, |title| is the title of the
        /// currently printing page, |currentPage| is the current page number and
        /// |maxPages| is the total number of pages. Six default header locations
        /// are provided by the implementation: top left, top center, top right,
        /// bottom left, bottom center and bottom right. To use one of these
        /// default locations just assign a string to the appropriate variable.
        /// To draw the header and footer yourself return true. Otherwise,
        /// populate the approprate variables and return false.
        /// </summary>
        private int get_print_header_footer(cef_print_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, /*const*/ cef_print_info_t* printInfo, /*const*/ cef_string_t* url, /*const*/ cef_string_t* title, int currentPage, int maxPages, cef_string_t* topLeft, cef_string_t* topCenter, cef_string_t* topRight, cef_string_t* bottomLeft, cef_string_t* bottomCenter, cef_string_t* bottomRight)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_printInfo = CefPrintInfo.From(printInfo);
            var m_url = cef_string_t.ToString(url);
            var m_title = cef_string_t.ToString(title);

            var m_topLeft = cef_string_t.ToString(topLeft);
            var m_topCenter = cef_string_t.ToString(topCenter);
            var m_topRight = cef_string_t.ToString(topRight);
            var m_bottomLeft = cef_string_t.ToString(bottomLeft);
            var m_bottomCenter = cef_string_t.ToString(bottomCenter);
            var m_bottomRight = cef_string_t.ToString(bottomRight);

            var o_topLeft = m_topLeft;
            var o_topCenter = m_topCenter;
            var o_topRight = m_topRight;
            var o_bottomLeft = m_bottomLeft;
            var o_bottomCenter = m_bottomCenter;
            var o_bottomRight = m_bottomRight;

            var handled = this.GetPrintHeaderFooter(m_browser, m_frame,
                m_printInfo, m_url, m_title, currentPage, maxPages,
                ref m_topLeft, ref m_topCenter, ref m_topRight,
                ref m_bottomLeft, ref m_bottomCenter, ref m_bottomRight);

            m_printInfo.Dispose();

            if (!handled)
            {
                if ((object)m_topLeft != (object)o_topLeft) cef_string_t.Copy(m_topLeft, topLeft);
                if ((object)m_topCenter != (object)o_topCenter) cef_string_t.Copy(m_topCenter, topCenter);
                if ((object)m_topRight != (object)o_topRight) cef_string_t.Copy(m_topRight, topRight);
                if ((object)m_bottomLeft != (object)o_bottomLeft) cef_string_t.Copy(m_bottomLeft, bottomLeft);
                if ((object)m_bottomCenter != (object)o_bottomCenter) cef_string_t.Copy(m_bottomCenter, bottomCenter);
                if ((object)m_bottomRight != (object)o_bottomRight) cef_string_t.Copy(m_bottomRight, bottomRight);
            }

            return handled ? 1 : 0;
        }
        /// <summary>
        /// Called when the size of the content area has changed.
        /// </summary>
        private void on_contents_size_change(cef_display_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, int width, int height)
        {
            ThrowIfObjectDisposed();

            var mBrowser = CefBrowser.From(browser);
            var mFrame = CefFrame.From(frame);

            this.OnContentsSizeChange(mBrowser, mFrame, width, height);
        }
        /// <summary>
        /// Called to run a JavaScript prompt request. Return false to display
        /// the default prompt or true if you displayed a custom prompt. If you
        /// handled the prompt set |retval| to true if the user accepted the
        /// prompt and request and |result| to the resulting value.
        /// </summary>
        private int on_jsprompt(cef_jsdialog_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, /*const*/ cef_string_t* message, /*const*/ cef_string_t* defaultValue, int* retval, cef_string_t* result)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_message = cef_string_t.ToString(message);
            var m_defaultValue = cef_string_t.ToString(defaultValue);
            bool m_retval;
            string m_result;

            var handled = this.OnJSPrompt(m_browser, m_frame, m_message, m_defaultValue, out m_retval, out m_result);

            if (handled)
            {
                *retval = m_retval ? 1 : 0;
                cef_string_t.Copy(m_result, result);
            }

            return handled ? 1 : 0;
        }
        /// <summary>
        /// Called when the browser begins loading a frame. The |frame| value
        /// will never be empty -- call the IsMain() method to check if this
        /// frame is the main frame. Multiple frames may be loading at the same
        /// time. Sub-frames may start or continue loading after the main frame
        /// load has ended. This method may not be called for a particular frame
        /// if the load request for that frame fails.
        /// </summary>
        private void on_load_start(cef_load_handler_t* self, cef_browser_t* browser, cef_frame_t* frame)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            this.OnLoadStart(m_browser, m_frame);
        }
        /// <summary>
        /// Called on the UI thread before browser navigation. Return true to
        /// cancel the navigation or false to allow the navigation to proceed.
        /// </summary>
        private int on_before_browse(cef_request_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, cef_request_t* request, cef_handler_navtype_t navType, int isRedirect)
        {
            ThrowIfObjectDisposed();

            var m_browser = CefBrowser.From(browser);
            var m_frame = CefFrame.From(frame);
            var m_request = CefRequest.From(request);
            var m_navType = (CefHandlerNavType)navType;
            var m_isRedirect = isRedirect != 0;

            var handled = this.OnBeforeBrowse(m_browser, m_frame, m_request, m_navType, m_isRedirect);

            return handled ? 1 : 0;
        }