// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. #include "tests/ceftests/message_router_unittest_utils.h" namespace { const char kSingleQueryRequest[] = "request_context"; const char kSingleQueryResponse[] = "success_response"; const int kSingleQueryErrorCode = 5; const char kSingleQueryErrorMessage[] = "error_message"; // Test a single query in a single page load. class SingleQueryTestHandler : public SingleLoadTestHandler { public: enum TestType { SUCCESS, FAILURE, CANCEL, }; SingleQueryTestHandler(TestType type, bool sync_callback) : test_type_(type), sync_callback_(sync_callback), query_id_(0) {} std::string GetMainHTML() override { std::string html; std::stringstream ss; ss << kSingleQueryErrorCode; const std::string& errorCodeStr = ss.str(); html = ""; return html; } void OnNotify(CefRefPtr browser, CefRefPtr frame, const std::string& message) override { AssertMainBrowser(browser); AssertMainFrame(frame); // OnNotify only be called once. EXPECT_FALSE(got_notify_); got_notify_.yes(); if (test_type_ == SUCCESS) { EXPECT_STREQ("success", message.c_str()); } else if (test_type_ == FAILURE) { EXPECT_STREQ("failure", message.c_str()); } else if (test_type_ == CANCEL) { EXPECT_STREQ("cancel", message.c_str()); } DestroyTestIfDone(); } void ExecuteCallback() { EXPECT_TRUE(callback_.get()); if (test_type_ == SUCCESS) { callback_->Success(kSingleQueryResponse); } else if (test_type_ == FAILURE) { callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage); } else { ADD_FAILURE(); // Not reached. } callback_ = nullptr; } bool OnQuery(CefRefPtr browser, CefRefPtr frame, int64 query_id, const CefString& request, bool persistent, CefRefPtr callback) override { AssertMainBrowser(browser); AssertMainFrame(frame); EXPECT_NE(0, query_id); EXPECT_FALSE(persistent); EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str()); got_on_query_.yes(); query_id_ = query_id; callback_ = callback; if (test_type_ == SUCCESS || test_type_ == FAILURE) { if (sync_callback_) { ExecuteCallback(); } else { CefPostTask( TID_UI, base::BindOnce(&SingleQueryTestHandler::ExecuteCallback, this)); } } return true; } void OnQueryCanceled(CefRefPtr browser, CefRefPtr frame, int64 query_id) override { AssertMainBrowser(browser); AssertMainFrame(frame); EXPECT_EQ(test_type_, CANCEL); EXPECT_EQ(query_id_, query_id); EXPECT_TRUE(got_on_query_); EXPECT_TRUE(callback_.get()); got_on_query_canceled_.yes(); callback_ = nullptr; DestroyTestIfDone(); } void DestroyTestIfDone() { bool destroy_test = false; if (test_type_ == CANCEL) destroy_test = got_notify_ && got_on_query_canceled_; else destroy_test = got_notify_; if (destroy_test) DestroyTest(); } void DestroyTest() override { EXPECT_TRUE(got_notify_); EXPECT_TRUE(got_on_query_); EXPECT_FALSE(callback_.get()); if (test_type_ == CANCEL) EXPECT_TRUE(got_on_query_canceled_); else EXPECT_FALSE(got_on_query_canceled_); TestHandler::DestroyTest(); } private: const TestType test_type_; const bool sync_callback_; int64 query_id_; CefRefPtr callback_; TrackCallback got_on_query_; TrackCallback got_on_query_canceled_; TrackCallback got_notify_; }; } // namespace // Test that a single query with successful result delivered synchronously. TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) { CefRefPtr handler = new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with successful result delivered asynchronously. TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) { CefRefPtr handler = new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with failure result delivered synchronously. TEST(MessageRouterTest, SingleQueryFailureSyncCallback) { CefRefPtr handler = new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with failure result delivered asynchronously. TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) { CefRefPtr handler = new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with cancellation. TEST(MessageRouterTest, SingleQueryCancel) { CefRefPtr handler = new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } namespace { const int kSinglePersistentQueryResponseCount = 10; // Test a single persistent query in a single page load. class SinglePersistentQueryTestHandler : public SingleLoadTestHandler { public: enum TestType { SUCCESS, FAILURE, }; SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback) : test_type_(test_type), sync_callback_(sync_callback), query_id_(0) {} std::string GetMainHTML() override { std::string html; std::stringstream ss; ss << kSinglePersistentQueryResponseCount; const std::string& responseCountStr = ss.str(); ss.str(""); ss << kSingleQueryErrorCode; const std::string& errorCodeStr = ss.str(); html = ""; return html; } void OnNotify(CefRefPtr browser, CefRefPtr frame, const std::string& message) override { AssertMainBrowser(browser); AssertMainFrame(frame); if (test_type_ == SUCCESS) { EXPECT_STREQ("success", message.c_str()); } else if (test_type_ == FAILURE) { EXPECT_STREQ("failure", message.c_str()); } got_notify_.yes(); DestroyTestIfDone(); } void ExecuteCallback() { EXPECT_TRUE(callback_.get()); if (test_type_ == SUCCESS) { callback_->Success(kSingleQueryResponse); } else { callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage); callback_ = nullptr; } } bool OnQuery(CefRefPtr browser, CefRefPtr frame, int64 query_id, const CefString& request, bool persistent, CefRefPtr callback) override { AssertMainBrowser(browser); AssertMainFrame(frame); EXPECT_NE(0, query_id); EXPECT_TRUE(persistent); EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str()); got_on_query_.yes(); query_id_ = query_id; callback_ = callback; int repeat = (test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1); for (int i = 0; i < repeat; ++i) { if (sync_callback_) { ExecuteCallback(); } else { CefPostTask( TID_UI, base::BindOnce(&SinglePersistentQueryTestHandler::ExecuteCallback, this)); } } return true; } void OnQueryCanceled(CefRefPtr browser, CefRefPtr frame, int64 query_id) override { AssertMainBrowser(browser); AssertMainFrame(frame); EXPECT_EQ(query_id_, query_id); EXPECT_TRUE(got_on_query_); EXPECT_TRUE(callback_.get()); got_on_query_canceled_.yes(); callback_ = nullptr; DestroyTestIfDone(); } void DestroyTestIfDone() { bool destroy_test = false; if (test_type_ == SUCCESS) { if (got_on_query_ && got_on_query_canceled_ && got_notify_) destroy_test = true; } else if (got_on_query_ && got_notify_) { destroy_test = true; } if (destroy_test) DestroyTest(); } void DestroyTest() override { EXPECT_TRUE(got_notify_); EXPECT_TRUE(got_on_query_); EXPECT_FALSE(callback_.get()); if (test_type_ == SUCCESS) EXPECT_TRUE(got_on_query_canceled_); else EXPECT_FALSE(got_on_query_canceled_); TestHandler::DestroyTest(); } private: const TestType test_type_; const bool sync_callback_; int64 query_id_; CefRefPtr callback_; TrackCallback got_on_query_; TrackCallback got_on_query_canceled_; TrackCallback got_notify_; }; } // namespace // Test that a single query with successful result delivered synchronously. TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) { CefRefPtr handler = new SinglePersistentQueryTestHandler( SinglePersistentQueryTestHandler::SUCCESS, true); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with successful result delivered asynchronously. TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) { CefRefPtr handler = new SinglePersistentQueryTestHandler( SinglePersistentQueryTestHandler::SUCCESS, false); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with failure result delivered synchronously. TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) { CefRefPtr handler = new SinglePersistentQueryTestHandler( SinglePersistentQueryTestHandler::FAILURE, true); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } // Test that a single query with failure result delivered asynchronously. TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) { CefRefPtr handler = new SinglePersistentQueryTestHandler( SinglePersistentQueryTestHandler::FAILURE, false); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); } namespace { // Test a single unhandled query in a single page load. class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler { public: SingleUnhandledQueryTestHandler() {} std::string GetMainHTML() override { std::string html; html = ""; return html; } void OnNotify(CefRefPtr browser, CefRefPtr frame, const std::string& message) override { AssertMainBrowser(browser); AssertMainFrame(frame); EXPECT_STREQ("failure", message.c_str()); got_notify_.yes(); DestroyTest(); } bool OnQuery(CefRefPtr browser, CefRefPtr frame, int64 query_id, const CefString& request, bool persistent, CefRefPtr callback) override { AssertMainBrowser(browser); AssertMainFrame(frame); EXPECT_NE(0, query_id); EXPECT_FALSE(persistent); EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str()); got_on_query_.yes(); return false; } void OnQueryCanceled(CefRefPtr browser, CefRefPtr frame, int64 query_id) override { EXPECT_FALSE(true); // Not reached. } void DestroyTest() override { EXPECT_TRUE(got_on_query_); EXPECT_TRUE(got_notify_); TestHandler::DestroyTest(); } private: TrackCallback got_on_query_; TrackCallback got_notify_; }; } // namespace // Test that a single unhandled query results in a call to onFailure. TEST(MessageRouterTest, SingleUnhandledQuery) { CefRefPtr handler = new SingleUnhandledQueryTestHandler(); handler->ExecuteTest(); ReleaseAndWaitForDestructor(handler); }