Fix handler insertion in CefMessageRouterBrowserSideImpl (fixes #3586)

This commit is contained in:
Nik Pavlov 2024-08-13 18:30:35 +00:00 committed by Marshall Greenblatt
parent b98eac265a
commit 2cd405baac
2 changed files with 70 additions and 33 deletions

View File

@ -198,9 +198,9 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
bool AddHandler(Handler* handler, bool first) override { bool AddHandler(Handler* handler, bool first) override {
CEF_REQUIRE_UI_THREAD(); CEF_REQUIRE_UI_THREAD();
if (handler_set_.find(handler) == handler_set_.end()) { if (std::find(handlers_.begin(), handlers_.end(), handler) ==
handler_set_.insert(first ? handler_set_.begin() : handler_set_.end(), handlers_.end()) {
handler); handlers_.insert(first ? handlers_.begin() : handlers_.end(), handler);
return true; return true;
} }
return false; return false;
@ -208,7 +208,9 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
bool RemoveHandler(Handler* handler) override { bool RemoveHandler(Handler* handler) override {
CEF_REQUIRE_UI_THREAD(); CEF_REQUIRE_UI_THREAD();
if (handler_set_.erase(handler) > 0) { auto it = std::find(handlers_.begin(), handlers_.end(), handler);
if (it != handlers_.end()) {
handlers_.erase(it);
CancelPendingFor(nullptr, handler, true); CancelPendingFor(nullptr, handler, true);
return true; return true;
} }
@ -297,7 +299,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
const int request_id = content.request_id; const int request_id = content.request_id;
const bool persistent = content.is_persistent; const bool persistent = content.is_persistent;
if (handler_set_.empty()) { if (handlers_.empty()) {
// No handlers so cancel the query. // No handlers so cancel the query.
CancelUnhandledQuery(browser, frame, context_id, request_id); CancelUnhandledQuery(browser, frame, context_id, request_id);
return true; return true;
@ -312,7 +314,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
// Make a copy of the handler list in case the user adds or removes a // Make a copy of the handler list in case the user adds or removes a
// handler while we're iterating. // handler while we're iterating.
const HandlerSet handlers = handler_set_; const HandlerSet handlers = handlers_;
Handler* handler = std::visit( Handler* handler = std::visit(
[&](const auto& arg) -> CefMessageRouterBrowserSide::Handler* { [&](const auto& arg) -> CefMessageRouterBrowserSide::Handler* {
@ -615,8 +617,8 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
// Set of currently registered handlers. An entry is added when a handler is // Set of currently registered handlers. An entry is added when a handler is
// registered and removed when a handler is unregistered. // registered and removed when a handler is unregistered.
using HandlerSet = std::set<Handler*>; using HandlerSet = std::vector<Handler*>;
HandlerSet handler_set_; HandlerSet handlers_;
// Map of query ID to QueryInfo instance. An entry is added when a Handler // Map of query ID to QueryInfo instance. An entry is added when a Handler
// indicates that it will handle the query and removed when either the query // indicates that it will handle the query and removed when either the query

View File

@ -1164,35 +1164,65 @@ class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
const CefString& request, const CefString& request,
bool persistent, bool persistent,
CefRefPtr<Callback> callback) override { CefRefPtr<Callback> callback) override {
// Each handler only handles a single request. // We expect handlers to be called in order 0, 1, 2.
std::stringstream ss;
ss << kMultiQueryRequest << ":" << index_; // The handler0 is called 3 times:
const std::string& handled_request = ss.str(); // - 1st request = "MultiQueryRequest:0", returns true, preventing calls
if (request != handled_request) { // to the other handlers.
return false; // - 2nd request = "MultiQueryRequest:1", returns false
// - 3rd request = "MultiQueryRequest:2", returns false
if (index_ == 0) {
if (request == HandledRequest(0)) {
EXPECT_FALSE(test_handler_->got_query0_);
EXPECT_FALSE(test_handler_->got_query1_);
EXPECT_FALSE(test_handler_->got_query2_);
test_handler_->got_query0_.yes();
} else if (request == HandledRequest(1)) {
EXPECT_TRUE(test_handler_->got_query0_);
EXPECT_FALSE(test_handler_->got_query1_);
EXPECT_FALSE(test_handler_->got_query2_);
} else {
EXPECT_EQ(request, HandledRequest(2));
EXPECT_TRUE(test_handler_->got_query0_);
EXPECT_TRUE(test_handler_->got_query1_);
EXPECT_FALSE(test_handler_->got_query2_);
}
} }
// Verify that handlers are called in the correct order. // The handler1 is called 2 times:
if (index_ == 0) { // - 1st request = "MultiQueryRequest:1", returns true, preventing calls
EXPECT_FALSE(test_handler_->got_query0_); // to the handler2.
EXPECT_FALSE(test_handler_->got_query1_); // - 2nd request = "MultiQueryRequest:2", returns false
EXPECT_FALSE(test_handler_->got_query2_); if (index_ == 1) {
if (request == HandledRequest(1)) {
EXPECT_TRUE(test_handler_->got_query0_);
EXPECT_FALSE(test_handler_->got_query1_);
EXPECT_FALSE(test_handler_->got_query2_);
test_handler_->got_query0_.yes(); test_handler_->got_query1_.yes();
} else if (index_ == 1) { } else {
EXPECT_TRUE(test_handler_->got_query0_); EXPECT_EQ(request, HandledRequest(2));
EXPECT_FALSE(test_handler_->got_query1_); EXPECT_TRUE(test_handler_->got_query0_);
EXPECT_FALSE(test_handler_->got_query2_); EXPECT_TRUE(test_handler_->got_query1_);
EXPECT_FALSE(test_handler_->got_query2_);
}
}
test_handler_->got_query1_.yes(); // The handler2 is called 1 time with request = "MultiQueryRequest:2".
} else if (index_ == 2) { if (index_ == 2) {
EXPECT_EQ(request, HandledRequest(2));
EXPECT_TRUE(test_handler_->got_query0_); EXPECT_TRUE(test_handler_->got_query0_);
EXPECT_TRUE(test_handler_->got_query1_); EXPECT_TRUE(test_handler_->got_query1_);
EXPECT_FALSE(test_handler_->got_query2_); EXPECT_FALSE(test_handler_->got_query2_);
test_handler_->got_query2_.yes(); test_handler_->got_query2_.yes();
} }
// Each handler only handles a single request.
if (request != HandledRequest(index_)) {
return false;
}
query_id_ = query_id; query_id_ = query_id;
return test_handler_->OnQuery(browser, frame, query_id, request, return test_handler_->OnQuery(browser, frame, query_id, request,
persistent, callback); persistent, callback);
@ -1219,6 +1249,12 @@ class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
} }
private: private:
static std::string HandledRequest(int index) {
std::stringstream ss;
ss << kMultiQueryRequest << ":" << index;
return ss.str();
}
MultiQueryMultiHandlerTestHandler* test_handler_; MultiQueryMultiHandlerTestHandler* test_handler_;
const int index_; const int index_;
int64_t query_id_ = 0; int64_t query_id_ = 0;
@ -1227,9 +1263,9 @@ class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
MultiQueryMultiHandlerTestHandler(bool synchronous, MultiQueryMultiHandlerTestHandler(bool synchronous,
bool cancel_by_removing_handler) bool cancel_by_removing_handler)
: manager_(std::string(), synchronous, 0), : manager_(std::string(), synchronous, 0),
handler0_(this, 0),
handler1_(this, 1),
handler2_(this, 2), handler2_(this, 2),
handler1_(this, 1),
handler0_(this, 0),
cancel_by_removing_handler_(cancel_by_removing_handler) { cancel_by_removing_handler_(cancel_by_removing_handler) {
manager_.AddObserver(this); manager_.AddObserver(this);
@ -1347,8 +1383,7 @@ class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
protected: protected:
void AddHandlers( void AddHandlers(
CefRefPtr<CefMessageRouterBrowserSide> message_router) override { CefRefPtr<CefMessageRouterBrowserSide> message_router) override {
// OnQuery call order will verify that the first/last ordering works as // OnQuery call order will verify that the ordering works as expected.
// expected.
EXPECT_TRUE(message_router->AddHandler(&handler1_, true)); EXPECT_TRUE(message_router->AddHandler(&handler1_, true));
EXPECT_TRUE(message_router->AddHandler(&handler0_, true)); EXPECT_TRUE(message_router->AddHandler(&handler0_, true));
EXPECT_TRUE(message_router->AddHandler(&handler2_, false)); EXPECT_TRUE(message_router->AddHandler(&handler2_, false));
@ -1359,9 +1394,9 @@ class MultiQueryMultiHandlerTestHandler : public SingleLoadTestHandler,
private: private:
MultiQueryManager manager_; MultiQueryManager manager_;
Handler handler0_;
Handler handler1_;
Handler handler2_; Handler handler2_;
Handler handler1_;
Handler handler0_;
const bool cancel_by_removing_handler_; const bool cancel_by_removing_handler_;