// Copyright (c) 2012 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 "include/base/cef_callback.h" #include "include/test/cef_test_helpers.h" #include "include/wrapper/cef_closure_task.h" #include "tests/ceftests/test_handler.h" #include "tests/gtest/include/gtest/gtest.h" namespace { const char* kStartUrl = "http://tests/JSDialogTestHandler.Start"; const char* kEndUrl = "http://tests/JSDialogTestHandler.End?r="; class JSDialogTestHandler : public TestHandler { public: enum TestType { TYPE_ALERT, TYPE_CONFIRM, TYPE_PROMPT, TYPE_ONBEFOREUNLOAD, }; enum TestMode { MODE_SUPPRESS, MODE_RUN_IMMEDIATE, MODE_RUN_DELAYED, }; JSDialogTestHandler(TestType type, TestMode mode, bool success, const std::string& user_input, const std::string& result) : type_(type), mode_(mode), success_(success), user_input_(user_input), result_(result) {} void RunTest() override { std::string content = "START"; AddResource(kStartUrl, content, "text/html"); AddResource(kEndUrl, "END", "text/html"); // Create the browser CreateBrowser(kStartUrl); // Time out the test after a reasonable period of time. SetTestTimeout(); } void OnLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) override { if (!frame->IsMain()) { return; } std::string url = frame->GetURL(); if (url.find(kEndUrl) == 0) { got_onloadend_.yes(); std::string result = url.substr(strlen(kEndUrl)); EXPECT_STREQ(result_.c_str(), result.c_str()); DestroyTest(); } else if (type_ == TYPE_ONBEFOREUNLOAD) { // Send the page a user gesture to enable firing of the onbefureunload // handler. See https://crbug.com/707007. CefExecuteJavaScriptWithUserGestureForTests(frame, CefString()); // Trigger the onunload handler. frame->LoadURL(kEndUrl); } } void Continue(CefRefPtr callback) { callback->Continue(success_, user_input_); } bool OnJSDialog(CefRefPtr browser, const CefString& origin_url, JSDialogType dialog_type, const CefString& message_text, const CefString& default_prompt_text, CefRefPtr callback, bool& suppress_message) override { got_onjsdialog_.yes(); EXPECT_STREQ(kStartUrl, origin_url.ToString().c_str()); if (type_ == TYPE_ALERT) { EXPECT_EQ(JSDIALOGTYPE_ALERT, dialog_type); EXPECT_STREQ("My alert message", message_text.ToString().c_str()); EXPECT_TRUE(default_prompt_text.empty()); } else if (type_ == TYPE_CONFIRM) { EXPECT_EQ(JSDIALOGTYPE_CONFIRM, dialog_type); EXPECT_STREQ("My confirm message", message_text.ToString().c_str()); EXPECT_TRUE(default_prompt_text.empty()); } else if (type_ == TYPE_PROMPT) { EXPECT_EQ(JSDIALOGTYPE_PROMPT, dialog_type); EXPECT_STREQ("My prompt message", message_text.ToString().c_str()); EXPECT_STREQ("my default", default_prompt_text.ToString().c_str()); } EXPECT_FALSE(suppress_message); if (mode_ == MODE_SUPPRESS) { // Suppress the dialog. suppress_message = true; return false; } else if (mode_ == MODE_RUN_IMMEDIATE) { // Continue immediately. callback->Continue(success_, user_input_); } else if (mode_ == MODE_RUN_DELAYED) { // Continue asynchronously. CefPostTask(TID_UI, base::BindOnce(&JSDialogTestHandler::Continue, this, callback)); } return true; } bool OnBeforeUnloadDialog(CefRefPtr browser, const CefString& message_text, bool is_reload, CefRefPtr callback) override { got_onbeforeunloaddialog_.yes(); if (type_ == TYPE_ONBEFOREUNLOAD) { // The message is no longer configurable via JavaScript. // See http://crbug.com/587940. EXPECT_STREQ("Is it OK to leave/reload this page?", message_text.ToString().c_str()); EXPECT_FALSE(is_reload); } if (mode_ == MODE_RUN_IMMEDIATE) { // Continue immediately. callback->Continue(success_, user_input_); } else if (mode_ == MODE_RUN_DELAYED) { // Continue asynchronously. CefPostTask(TID_UI, base::BindOnce(&JSDialogTestHandler::Continue, this, callback)); } return true; } void OnResetDialogState(CefRefPtr browser) override { got_onresetdialogstate_.yes(); } TestType type_; TestMode mode_; bool success_; std::string user_input_; std::string result_; TrackCallback got_onjsdialog_; TrackCallback got_onbeforeunloaddialog_; TrackCallback got_onresetdialogstate_; TrackCallback got_onloadend_; IMPLEMENT_REFCOUNTING(JSDialogTestHandler); }; } // namespace // Alert dialog with suppression. TEST(JSDialogTest, AlertSuppress) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_ALERT, JSDialogTestHandler::MODE_SUPPRESS, true, // success "", // user_input ""); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Alert dialog with immediate callback. TEST(JSDialogTest, AlertRunImmediate) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_ALERT, JSDialogTestHandler::MODE_RUN_IMMEDIATE, true, // success "", // user_input ""); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Alert dialog with delayed callback. TEST(JSDialogTest, AlertRunDelayed) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_ALERT, JSDialogTestHandler::MODE_RUN_DELAYED, true, // success "", // user_input ""); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Confirm dialog with suppression. TEST(JSDialogTest, ConfirmSuppress) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_SUPPRESS, true, // success "", // user_input "cancel"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Confirm dialog run immediately return OK. TEST(JSDialogTest, ConfirmRunImmediateOk) { CefRefPtr handler = new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_RUN_IMMEDIATE, true, // success "", // user_input "ok"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Confirm dialog run immediately return Cancel. TEST(JSDialogTest, ConfirmRunImmediateCancel) { CefRefPtr handler = new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_RUN_IMMEDIATE, false, // success "", // user_input "cancel"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Confirm dialog run delayed return OK. TEST(JSDialogTest, ConfirmRunDelayedOk) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_RUN_DELAYED, true, // success "", // user_input "ok"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Confirm dialog run delayed return Cancel. TEST(JSDialogTest, ConfirmRunDelayedCancel) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_CONFIRM, JSDialogTestHandler::MODE_RUN_DELAYED, false, // success "", // user_input "cancel"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Prompt dialog with suppression. TEST(JSDialogTest, PromptSuppress) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_SUPPRESS, true, // success "some_value", // user_input "null"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Prompt dialog run immediately return OK. TEST(JSDialogTest, PromptRunImmediateOk) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_IMMEDIATE, true, // success "some_value", // user_input "some_value"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Prompt dialog run immediately return Cancel. TEST(JSDialogTest, PromptRunImmediateCancel) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_IMMEDIATE, false, // success "some_value", // user_input "null"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Prompt dialog run delayed return OK. TEST(JSDialogTest, PromptRunDelayedOk) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_DELAYED, true, // success "some_value", // user_input "some_value"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // Prompt dialog run delayed return Cancel. TEST(JSDialogTest, PromptRunDelayedCancel) { CefRefPtr handler = new JSDialogTestHandler( JSDialogTestHandler::TYPE_PROMPT, JSDialogTestHandler::MODE_RUN_DELAYED, false, // success "some_value", // user_input "null"); // result handler->ExecuteTest(); EXPECT_TRUE(handler->got_onjsdialog_); EXPECT_FALSE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // OnBeforeUnload dialog with immediate callback. TEST(JSDialogTest, OnBeforeUnloadRunImmediate) { CefRefPtr handler = new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD, JSDialogTestHandler::MODE_RUN_IMMEDIATE, true, // success "", // user_input ""); // result handler->ExecuteTest(); EXPECT_FALSE(handler->got_onjsdialog_); EXPECT_TRUE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); } // OnBeforeUnload dialog with delayed callback. TEST(JSDialogTest, OnBeforeUnloadRunDelayed) { CefRefPtr handler = new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD, JSDialogTestHandler::MODE_RUN_DELAYED, true, // success "", // user_input ""); // result handler->ExecuteTest(); EXPECT_FALSE(handler->got_onjsdialog_); EXPECT_TRUE(handler->got_onbeforeunloaddialog_); EXPECT_TRUE(handler->got_onresetdialogstate_); EXPECT_TRUE(handler->got_onloadend_); ReleaseAndWaitForDestructor(handler); }