init lserp cs 5.0
This commit is contained in:
@@ -0,0 +1,629 @@
|
||||
namespace Cef3.Wrapper
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using BrowserInfoMap = CefBrowserInfoMap<long, Cef3.Wrapper.CefMessageRouterBrowserSide.QueryInfo>;
|
||||
|
||||
/// <summary>
|
||||
/// Implements the browser side of query routing. The methods of this class may
|
||||
/// be called on any browser process thread unless otherwise indicated.
|
||||
/// </summary>
|
||||
public sealed class CefMessageRouterBrowserSide
|
||||
{
|
||||
#region Callback
|
||||
|
||||
/// <summary>
|
||||
/// Callback associated with a single pending asynchronous query. Execute the
|
||||
/// Success or Failure method to send an asynchronous response to the
|
||||
/// associated JavaScript handler. It is a runtime error to destroy a Callback
|
||||
/// object associated with an uncanceled query without first executing one of
|
||||
/// the callback methods. The methods of this class may be called on any
|
||||
/// browser process thread.
|
||||
/// </summary>
|
||||
public sealed class Callback
|
||||
{
|
||||
private CefMessageRouterBrowserSide _router;
|
||||
private readonly int _browserId;
|
||||
private readonly long _queryId;
|
||||
private readonly bool _persistent;
|
||||
|
||||
internal Callback(CefMessageRouterBrowserSide router, int browserId, long queryId, bool persistent)
|
||||
{
|
||||
_router = router;
|
||||
_browserId = browserId;
|
||||
_queryId = queryId;
|
||||
_persistent = persistent;
|
||||
}
|
||||
|
||||
~Callback()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
internal void Dispose()
|
||||
{
|
||||
// Hitting this DCHECK means that you didn't call Success or Failure
|
||||
// on the Callback after returning true from Handler::OnQuery. You must
|
||||
// call Failure to terminate persistent queries.
|
||||
Debug.Assert(_router == null);
|
||||
// if (_router != null) throw new InvalidOperationException("You didn't call Success or Failure on the Callback after returning true from Handler::OnQuery.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify the associated JavaScript onSuccess callback that the query has
|
||||
/// completed successfully with the specified |response|.
|
||||
/// </summary>
|
||||
public void Success(string response)
|
||||
{
|
||||
if (!CefRuntime.CurrentlyOn(CefThreadId.UI))
|
||||
{
|
||||
Helpers.PostTask(CefThreadId.UI,
|
||||
Helpers.Apply(this.Success, response)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_router != null)
|
||||
{
|
||||
Helpers.PostTaskUncertainty(CefThreadId.UI,
|
||||
Helpers.Apply(_router.OnCallbackSuccess, _browserId, _queryId, response)
|
||||
);
|
||||
|
||||
if (!_persistent)
|
||||
{
|
||||
// Non-persistent callbacks are only good for a single use.
|
||||
_router = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify the associated JavaScript onFailure callback that the query has
|
||||
/// failed with the specified |error_code| and |error_message|.
|
||||
/// </summary>
|
||||
public void Failure(int errorCode, string errorMessage)
|
||||
{
|
||||
if (!CefRuntime.CurrentlyOn(CefThreadId.UI))
|
||||
{
|
||||
// Must execute on the UI thread to access member variables.
|
||||
Helpers.PostTask(CefThreadId.UI,
|
||||
Helpers.Apply(this.Failure, errorCode, errorMessage)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_router != null)
|
||||
{
|
||||
Helpers.PostTaskUncertainty(CefThreadId.UI,
|
||||
Helpers.Apply(_router.OnCallbackFailure, _browserId, _queryId, errorCode, errorMessage)
|
||||
);
|
||||
|
||||
// Failure always invalidates the callback.
|
||||
_router = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Detach()
|
||||
{
|
||||
Helpers.RequireUIThread();
|
||||
_router = null;
|
||||
}
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handler
|
||||
|
||||
/// <summary>
|
||||
/// Implement this interface to handle queries. All methods will be executed on
|
||||
/// the browser process UI thread.
|
||||
/// </summary>
|
||||
public class Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Executed when a new query is received. |query_id| uniquely identifies the
|
||||
/// query for the life span of the router. Return true to handle the query
|
||||
/// or false to propagate the query to other registered handlers, if any. If
|
||||
/// no handlers return true from this method then the query will be
|
||||
/// automatically canceled with an error code of -1 delivered to the
|
||||
/// JavaScript onFailure callback. If this method returns true then a
|
||||
/// Callback method must be executed either in this method or asynchronously
|
||||
/// to complete the query.
|
||||
/// </summary>
|
||||
public virtual bool OnQuery(CefBrowser browser, CefFrame frame, long queryId, string request, bool persistent, Callback callback)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executed when a query has been canceled either explicitly using the
|
||||
/// JavaScript cancel function or implicitly due to browser destruction,
|
||||
/// navigation or renderer process termination. It will only be called for
|
||||
/// the single handler that returned true from OnQuery for the same
|
||||
/// |query_id|. No references to the associated Callback object should be
|
||||
/// kept after this method is called, nor should any Callback methods be
|
||||
/// executed.
|
||||
/// </summary>
|
||||
public virtual void OnQueryCanceled(CefBrowser browser, CefFrame frame, long queryId)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly CefMessageRouterConfig _config;
|
||||
private readonly string _queryMessageName;
|
||||
private readonly string _cancelMessageName;
|
||||
|
||||
private readonly List<Handler> _handlerSet = new List<Handler>(4); // TODO: use a HashSet, for .NET 3.5+
|
||||
|
||||
private readonly BrowserInfoMap _browserQueryInfoMap = new BrowserInfoMap();
|
||||
|
||||
private readonly CefMessageRouter.IdGeneratorInt64 _queryIdGenerator = new CefMessageRouter.IdGeneratorInt64();
|
||||
|
||||
/// <summary>
|
||||
/// Create a new router with the specified configuration.
|
||||
/// </summary>
|
||||
public CefMessageRouterBrowserSide(CefMessageRouterConfig config)
|
||||
{
|
||||
if (!config.Validate()) throw new ArgumentException("Invalid configuration.");
|
||||
|
||||
_config = config;
|
||||
_queryMessageName = config.JSQueryFunction + CefMessageRouter.MessageSuffix;
|
||||
_cancelMessageName = config.JSCancelFunction + CefMessageRouter.MessageSuffix;
|
||||
}
|
||||
|
||||
~CefMessageRouterBrowserSide()
|
||||
{
|
||||
// There should be no pending queries when the router is deleted.
|
||||
Debug.Assert(_browserQueryInfoMap.IsEmpty);
|
||||
}
|
||||
|
||||
// TODO: Dispose method ?
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new router with the specified configuration.
|
||||
/// </summary>
|
||||
public static CefMessageRouterBrowserSide Create(CefMessageRouterConfig config)
|
||||
{
|
||||
return new CefMessageRouterBrowserSide(config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new query handler. If |first| is true it will be added as the first
|
||||
/// handler, otherwise it will be added as the last handler. Returns true if
|
||||
/// the handler is added successfully or false if the handler has already been
|
||||
/// added. Must be called on the browser process UI thread. The Handler object
|
||||
/// must either outlive the router or be removed before deletion.
|
||||
/// </summary>
|
||||
public bool AddHandler(Handler handler, bool first = false)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException("handler");
|
||||
|
||||
Helpers.RequireUIThread();
|
||||
|
||||
if (_handlerSet.Contains(handler)) return false;
|
||||
|
||||
if (first) { _handlerSet.Insert(0, handler); }
|
||||
else { _handlerSet.Add(handler); }
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an existing query handler. Any pending queries associated with the
|
||||
/// handler will be canceled. Handler::OnQueryCanceled will be called and the
|
||||
/// associated JavaScript onFailure callback will be executed with an error
|
||||
/// code of -1. Returns true if the handler is removed successfully or false
|
||||
/// if the handler is not found. Must be called on the browser process UI
|
||||
/// thread.
|
||||
/// </summary>
|
||||
public bool RemoveHandler(Handler handler)
|
||||
{
|
||||
if (handler == null) throw new ArgumentNullException("handler");
|
||||
|
||||
Helpers.RequireUIThread();
|
||||
|
||||
if (_handlerSet.Remove(handler))
|
||||
{
|
||||
CancelPendingFor(null, handler, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancel all pending queries associated with either |browser| or |handler|.
|
||||
/// If both |browser| and |handler| are NULL all pending queries will be
|
||||
/// canceled. Handler::OnQueryCanceled will be called and the associated
|
||||
/// JavaScript onFailure callback will be executed in all cases with an error
|
||||
/// code of -1.
|
||||
/// </summary>
|
||||
public void CancelPending(CefBrowser browser = null, Handler handler = null)
|
||||
{
|
||||
CancelPendingFor(browser, handler, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of queries currently pending for the specified |browser|
|
||||
/// and/or |handler|. Either or both values may be empty. Must be called on the
|
||||
/// browser process UI thread.
|
||||
/// </summary>
|
||||
public int GetPendingCount(CefBrowser browser = null, Handler handler = null)
|
||||
{
|
||||
Helpers.RequireUIThread();
|
||||
|
||||
if (_browserQueryInfoMap.IsEmpty) return 0;
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
int count = 0;
|
||||
BrowserInfoMap.Visitor visitor = (int browserId, long key, QueryInfo value, ref bool remove) =>
|
||||
{
|
||||
if (value.Handler == handler) count++;
|
||||
return true;
|
||||
};
|
||||
|
||||
if (browser != null)
|
||||
{
|
||||
// Count queries associated with the specified browser.
|
||||
_browserQueryInfoMap.FindAll(browser.Identifier, visitor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count all queries for all browsers.
|
||||
_browserQueryInfoMap.FindAll(visitor);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
else if (browser != null)
|
||||
{
|
||||
return _browserQueryInfoMap.Count(browser.Identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _browserQueryInfoMap.Count();
|
||||
}
|
||||
}
|
||||
|
||||
#region The below methods should be called from other CEF handlers. They must be called exactly as documented for the router to function correctly.
|
||||
|
||||
/// <summary>
|
||||
/// Call from CefLifeSpanHandler::OnBeforeClose. Any pending queries associated
|
||||
/// with |browser| will be canceled and Handler::OnQueryCanceled will be called.
|
||||
/// No JavaScript callbacks will be executed since this indicates destruction
|
||||
/// of the browser.
|
||||
/// </summary>
|
||||
public void OnBeforeClose(CefBrowser browser)
|
||||
{
|
||||
CancelPendingFor(browser, null, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call from CefRequestHandler::OnRenderProcessTerminated. Any pending queries
|
||||
/// associated with |browser| will be canceled and Handler::OnQueryCanceled
|
||||
/// will be called. No JavaScript callbacks will be executed since this
|
||||
/// indicates destruction of the context.
|
||||
/// </summary>
|
||||
public void OnRenderProcessTerminated(CefBrowser browser)
|
||||
{
|
||||
CancelPendingFor(browser, null, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call from CefRequestHandler::OnBeforeBrowse only if the navigation is
|
||||
/// allowed to proceed. If |frame| is the main frame then any pending queries
|
||||
/// associated with |browser| will be canceled and Handler::OnQueryCanceled
|
||||
/// will be called. No JavaScript callbacks will be executed since this
|
||||
/// indicates destruction of the context.
|
||||
/// </summary>
|
||||
public void OnBeforeBrowse(CefBrowser browser, CefFrame frame)
|
||||
{
|
||||
if (frame.IsMain) CancelPendingFor(browser, null, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call from CefClient::OnProcessMessageReceived. Returns true if the message
|
||||
/// is handled by this router or false otherwise.
|
||||
/// </summary>
|
||||
public bool OnProcessMessageReceived(CefBrowser browser, CefProcessId sourceProcess, CefProcessMessage message)
|
||||
{
|
||||
Helpers.RequireUIThread();
|
||||
|
||||
var messageName = message.Name;
|
||||
if (messageName == _queryMessageName)
|
||||
{
|
||||
var args = message.Arguments;
|
||||
Debug.Assert(args.Count == 6);
|
||||
|
||||
var frameId = Helpers.Int64Set(args.GetInt(0), args.GetInt(1));
|
||||
var contextId = args.GetInt(2);
|
||||
var requestId = args.GetInt(3);
|
||||
var request = args.GetString(4);
|
||||
var persistent = args.GetBool(5);
|
||||
|
||||
if (_handlerSet.Count == 0)
|
||||
{
|
||||
// No handlers so cancel the query.
|
||||
CancelUnhandledQuery(browser, contextId, requestId);
|
||||
return true;
|
||||
}
|
||||
|
||||
var browserId = browser.Identifier;
|
||||
var queryId = _queryIdGenerator.GetNextId();
|
||||
|
||||
var frame = browser.GetFrame(frameId);
|
||||
var callback = new Callback(this, browserId, queryId, persistent);
|
||||
|
||||
// Make a copy of the handler list in case the user adds or removes a
|
||||
// handler while we're iterating.
|
||||
var handlers = _handlerSet.ToArray();
|
||||
|
||||
var handled = false;
|
||||
Handler handler = null;
|
||||
foreach (var x in handlers)
|
||||
{
|
||||
handled = x.OnQuery(browser, frame, queryId, request, persistent, callback);
|
||||
if (handled)
|
||||
{
|
||||
handler = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the query isn't handled nothing should be keeping a reference to
|
||||
// the callback.
|
||||
// DCHECK(handled || callback->GetRefCt() == 1);
|
||||
// Debug.Assert(handled && handler != null);
|
||||
// We don't need this assertion, in GC environment.
|
||||
// There is client responsibility to do not reference callback, if request is not handled.
|
||||
|
||||
if (handled)
|
||||
{
|
||||
// Persist the query information until the callback executes.
|
||||
// It's safe to do this here because the callback will execute
|
||||
// asynchronously.
|
||||
var info = new QueryInfo
|
||||
{
|
||||
Browser = browser,
|
||||
FrameId = frameId,
|
||||
ContextId = contextId,
|
||||
RequestId = requestId,
|
||||
Persistent = persistent,
|
||||
Callback = callback,
|
||||
Handler = handler,
|
||||
};
|
||||
_browserQueryInfoMap.Add(browserId, queryId, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalidate the callback.
|
||||
callback.Detach();
|
||||
|
||||
// No one chose to handle the query so cancel it.
|
||||
CancelUnhandledQuery(browser, contextId, requestId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (messageName == _cancelMessageName)
|
||||
{
|
||||
var args = message.Arguments;
|
||||
Debug.Assert(args.Count == 2);
|
||||
|
||||
var browserId = browser.Identifier;
|
||||
var contextId = args.GetInt(0);
|
||||
var requestId = args.GetInt(1);
|
||||
|
||||
CancelPendingRequest(browserId, contextId, requestId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal sealed class QueryInfo
|
||||
{
|
||||
// Browser and frame originated the query.
|
||||
public CefBrowser Browser;
|
||||
public long FrameId;
|
||||
|
||||
// IDs that uniquely identify the query in the renderer process. These
|
||||
// values are opaque to the browser process but must be returned with the
|
||||
// response.
|
||||
public int ContextId;
|
||||
public int RequestId;
|
||||
|
||||
// True if the query is persistent.
|
||||
public bool Persistent;
|
||||
|
||||
// Callback associated with the query that must be detached when the query
|
||||
// is canceled.
|
||||
public Callback Callback;
|
||||
|
||||
// Handler that should be notified if the query is automatically canceled.
|
||||
public Handler Handler;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Browser = null;
|
||||
//if (Browser != null)
|
||||
//{
|
||||
// Browser.Dispose();
|
||||
// Browser = null;
|
||||
//}
|
||||
}
|
||||
};
|
||||
|
||||
// Retrieve a QueryInfo object from the map based on the browser-side query
|
||||
// ID. If |always_remove| is true then the QueryInfo object will always be
|
||||
// removed from the map. Othewise, the QueryInfo object will only be removed
|
||||
// if the query is non-persistent. If |removed| is true the caller is
|
||||
// responsible for deleting the returned QueryInfo object.
|
||||
private QueryInfo GetQueryInfo(int browserId, long queryId, bool alwaysRemove, ref bool removed)
|
||||
{
|
||||
bool removedTemp = false;
|
||||
BrowserInfoMap.Visitor visitor = (int browserId_, long key, QueryInfo value, ref bool remove) =>
|
||||
{
|
||||
remove = removedTemp = alwaysRemove || !value.Persistent;
|
||||
return true;
|
||||
};
|
||||
var info = _browserQueryInfoMap.Find(browserId, queryId, visitor);
|
||||
if (info != null) removed = removedTemp;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Called by CallbackImpl on success.
|
||||
private void OnCallbackSuccess(int browserId, long queryId, string response)
|
||||
{
|
||||
Helpers.RequireUIThread();
|
||||
|
||||
bool removed = false;
|
||||
var info = GetQueryInfo(browserId, queryId, false, ref removed);
|
||||
if (info != null)
|
||||
{
|
||||
SendQuerySuccess(info, response);
|
||||
if (removed) info.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Called by CallbackImpl on failure.
|
||||
private void OnCallbackFailure(int browserId, long queryId, int errorCode, string errorMessage)
|
||||
{
|
||||
Helpers.RequireUIThread();
|
||||
|
||||
bool removed = false;
|
||||
var info = GetQueryInfo(browserId, queryId, true, ref removed);
|
||||
if (info != null)
|
||||
{
|
||||
SendQueryFailure(info, errorCode, errorMessage);
|
||||
Debug.Assert(removed);
|
||||
info.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void SendQuerySuccess(QueryInfo info, string response)
|
||||
{
|
||||
SendQuerySuccess(info.Browser, info.ContextId, info.RequestId, response);
|
||||
}
|
||||
|
||||
private void SendQuerySuccess(CefBrowser browser, int contextId, int requestId, string response)
|
||||
{
|
||||
var message = CefProcessMessage.Create(_queryMessageName);
|
||||
var args = message.Arguments;
|
||||
args.SetInt(0, contextId);
|
||||
args.SetInt(1, requestId);
|
||||
args.SetBool(2, true); // Indicates a success result.
|
||||
args.SetString(3, response);
|
||||
browser.SendProcessMessage(CefProcessId.Renderer, message);
|
||||
args.Dispose();
|
||||
message.Dispose();
|
||||
}
|
||||
|
||||
private void SendQueryFailure(QueryInfo info, int errorCode, string errorMessage)
|
||||
{
|
||||
SendQueryFailure(info.Browser, info.ContextId, info.RequestId, errorCode, errorMessage);
|
||||
}
|
||||
|
||||
private void SendQueryFailure(CefBrowser browser, int contextId, int requestId, int errorCode, string errorMessage)
|
||||
{
|
||||
var message = CefProcessMessage.Create(_queryMessageName);
|
||||
var args = message.Arguments;
|
||||
args.SetInt(0, contextId);
|
||||
args.SetInt(1, requestId);
|
||||
args.SetBool(2, false); // Indicates a failure result.
|
||||
args.SetInt(3, errorCode);
|
||||
args.SetString(4, errorMessage);
|
||||
browser.SendProcessMessage(CefProcessId.Renderer, message);
|
||||
args.Dispose();
|
||||
message.Dispose();
|
||||
}
|
||||
|
||||
// Cancel a query that has not been sent to a handler.
|
||||
private void CancelUnhandledQuery(CefBrowser browser, int contextId, int requestId)
|
||||
{
|
||||
SendQueryFailure(browser, contextId, requestId, CefMessageRouter.CanceledErrorCode, CefMessageRouter.CanceledErrorMessage);
|
||||
}
|
||||
|
||||
// Cancel a query that has already been sent to a handler.
|
||||
private void CancelQuery(long queryId, QueryInfo info, bool notifyRenderer)
|
||||
{
|
||||
if (notifyRenderer)
|
||||
SendQueryFailure(info, CefMessageRouter.CanceledErrorCode, CefMessageRouter.CanceledErrorMessage);
|
||||
|
||||
var frame = info.Browser.GetFrame(info.FrameId);
|
||||
info.Handler.OnQueryCanceled(info.Browser, frame, queryId);
|
||||
|
||||
// Invalidate the callback.
|
||||
info.Callback.Detach();
|
||||
}
|
||||
|
||||
// Cancel all pending queries associated with either |browser| or |handler|.
|
||||
// If both |browser| and |handler| are NULL all pending queries will be
|
||||
// canceled. Set |notify_renderer| to true if the renderer should be notified.
|
||||
private void CancelPendingFor(CefBrowser browser, Handler handler, bool notifyRenderer)
|
||||
{
|
||||
if (!CefRuntime.CurrentlyOn(CefThreadId.UI))
|
||||
{
|
||||
// Must execute on the UI thread.
|
||||
Helpers.PostTask(CefThreadId.UI,
|
||||
Helpers.Apply(this.CancelPendingFor, browser, handler, notifyRenderer)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_browserQueryInfoMap.IsEmpty) return;
|
||||
|
||||
BrowserInfoMap.Visitor visitor = (int browserId, long queryId, QueryInfo info, ref bool remove) =>
|
||||
{
|
||||
if (handler == null || info.Handler == handler)
|
||||
{
|
||||
remove = true;
|
||||
CancelQuery(queryId, info, notifyRenderer);
|
||||
info.Dispose();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (browser != null)
|
||||
{
|
||||
// Cancel all queries associated with the specified browser.
|
||||
_browserQueryInfoMap.FindAll(browser.Identifier, visitor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel all queries for all browsers.
|
||||
_browserQueryInfoMap.FindAll(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel a query based on the renderer-side IDs. If |request_id| is
|
||||
// kReservedId all requests associated with |context_id| will be canceled.
|
||||
private void CancelPendingRequest(int browserId, int contextId, int requestId)
|
||||
{
|
||||
BrowserInfoMap.Visitor visitor = (int vBrowserId, long queryId, QueryInfo info, ref bool remove) =>
|
||||
{
|
||||
if (info.ContextId == contextId
|
||||
&& (requestId == CefMessageRouter.ReservedId || info.RequestId == requestId))
|
||||
{
|
||||
remove = true;
|
||||
CancelQuery(queryId, info, false);
|
||||
info.Dispose();
|
||||
|
||||
// Stop iterating if only canceling a single request.
|
||||
return requestId == CefMessageRouter.ReservedId;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
_browserQueryInfoMap.FindAll(browserId, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user