mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-16 20:20:51 +01:00
Add unit test for crash due to by delayed execution of JS functions on destroyed windows (issue #2038)
This commit is contained in:
parent
cca0bcc8e0
commit
3b499d3d11
@ -5,6 +5,7 @@
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/cef_command_line.h"
|
||||
#include "include/cef_stream.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
@ -283,6 +284,11 @@ CefRefPtr<CefResourceHandler> TestHandler::GetResourceHandler(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TestHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
||||
TerminationStatus status) {
|
||||
LOG(WARNING) << "OnRenderProcessTerminated: status = " << status << ".";
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> TestHandler::GetBrowser() {
|
||||
return first_browser_;
|
||||
}
|
||||
|
@ -182,6 +182,9 @@ class TestHandler : public CefClient,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override;
|
||||
|
||||
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
||||
TerminationStatus status) override;
|
||||
|
||||
// These methods should only be used if at most one non-popup browser exists.
|
||||
CefRefPtr<CefBrowser> GetBrowser();
|
||||
int GetBrowserId();
|
||||
|
@ -37,6 +37,10 @@ const char kV8ContextEvalCspBypassSandbox[] =
|
||||
"http://tests/V8Test.ContextEvalCspBypassSandbox";
|
||||
const char kV8OnUncaughtExceptionTestUrl[] =
|
||||
"http://tests/V8Test.OnUncaughtException";
|
||||
const char kV8HandlerCallOnReleasedContextUrl[] =
|
||||
"http://tests/V8Test.HandlerCallOnReleasedContext/main.html";
|
||||
const char kV8HandlerCallOnReleasedContextChildUrl[] =
|
||||
"http://tests/V8Test.HandlerCallOnReleasedContext/child.html";
|
||||
const char kV8TestMsg[] = "V8Test.Test";
|
||||
const char kV8TestCmdArg[] = "v8-test";
|
||||
const char kV8RunTestMsg[] = "V8Test.RunTest";
|
||||
@ -88,6 +92,7 @@ enum V8TestMode {
|
||||
V8TEST_ON_UNCAUGHT_EXCEPTION,
|
||||
V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS,
|
||||
V8TEST_EXTENSION,
|
||||
V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT,
|
||||
};
|
||||
|
||||
// Set to the current test being run in the browser process. Will always be
|
||||
@ -254,6 +259,8 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
|
||||
case V8TEST_ON_UNCAUGHT_EXCEPTION:
|
||||
RunOnUncaughtExceptionTest();
|
||||
break;
|
||||
case V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT:
|
||||
break;
|
||||
default:
|
||||
// Was a startup test.
|
||||
EXPECT_TRUE(startup_test_success_);
|
||||
@ -2482,6 +2489,79 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
|
||||
EXPECT_TRUE(object.get());
|
||||
EXPECT_TRUE(object->SetValue("v8_binding_test", CefV8Value::CreateInt(12),
|
||||
V8_PROPERTY_ATTRIBUTE_NONE));
|
||||
} else if (url == kV8HandlerCallOnReleasedContextUrl) {
|
||||
// For V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT
|
||||
class Handler : public CefV8Handler {
|
||||
public:
|
||||
Handler(CefRefPtr<V8RendererTest> renderer_test)
|
||||
: renderer_test_(renderer_test) {}
|
||||
|
||||
bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) override {
|
||||
if (name == "notify_test_done") {
|
||||
CefPostDelayedTask(
|
||||
TID_RENDERER,
|
||||
base::Bind(&V8RendererTest::DestroyTest, renderer_test_.get()),
|
||||
1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
CefRefPtr<V8RendererTest> renderer_test_;
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
|
||||
Handler* handler = new Handler(this);
|
||||
CefRefPtr<CefV8Handler> handlerPtr(handler);
|
||||
|
||||
// Function that will be called from the parent frame context.
|
||||
CefRefPtr<CefV8Value> func =
|
||||
CefV8Value::CreateFunction("notify_test_done", handler);
|
||||
EXPECT_TRUE(func.get());
|
||||
|
||||
CefRefPtr<CefV8Value> object = context->GetGlobal();
|
||||
EXPECT_TRUE(object.get());
|
||||
EXPECT_TRUE(object->SetValue("notify_test_done", func,
|
||||
V8_PROPERTY_ATTRIBUTE_NONE));
|
||||
} else if (url == kV8HandlerCallOnReleasedContextChildUrl) {
|
||||
// For V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT
|
||||
class Handler : public CefV8Handler {
|
||||
public:
|
||||
Handler() {}
|
||||
bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) override {
|
||||
if (name == "v8_context_is_alive") {
|
||||
retval = CefV8Value::CreateBool(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
|
||||
Handler* handler = new Handler;
|
||||
CefRefPtr<CefV8Handler> handlerPtr(handler);
|
||||
|
||||
// Function that will be called from the parent frame context.
|
||||
CefRefPtr<CefV8Value> func =
|
||||
CefV8Value::CreateFunction("v8_context_is_alive", handler);
|
||||
EXPECT_TRUE(func.get());
|
||||
|
||||
CefRefPtr<CefV8Value> object = context->GetGlobal();
|
||||
EXPECT_TRUE(object.get());
|
||||
EXPECT_TRUE(object->SetValue("v8_context_is_alive", func,
|
||||
V8_PROPERTY_ATTRIBUTE_NONE));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2714,6 +2794,58 @@ class V8TestHandler : public TestHandler {
|
||||
"</body></html>\n",
|
||||
"text/html");
|
||||
CreateBrowser(kV8OnUncaughtExceptionTestUrl);
|
||||
} else if (test_mode_ == V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT) {
|
||||
AddResource(kV8HandlerCallOnReleasedContextUrl,
|
||||
"<html><body onload='createFrame()'>"
|
||||
"(main)"
|
||||
"<script>"
|
||||
"function createFrame() {"
|
||||
" var el = document.createElement('iframe');"
|
||||
" el.id = 'child';"
|
||||
" el.src = '" +
|
||||
std::string(kV8HandlerCallOnReleasedContextChildUrl) +
|
||||
"';"
|
||||
" el.onload = function() {"
|
||||
" setTimeout(function() {"
|
||||
" try {"
|
||||
" el.contentWindow.removeMe();"
|
||||
" window.notify_test_done();"
|
||||
" } catch (e) { alert('Unit test error.\\n' + e); }"
|
||||
" }, 1000);"
|
||||
" };"
|
||||
" document.body.appendChild(el);"
|
||||
"}"
|
||||
""
|
||||
"function removeFrame(id) {"
|
||||
" var el = document.getElementById(id);"
|
||||
" if (el) { el.parentElement.removeChild(el); }"
|
||||
" else { alert('Error in test. No element \"' + id + "
|
||||
"'\" found.'); }"
|
||||
"}"
|
||||
"</script>"
|
||||
"</body></html>",
|
||||
"text/html");
|
||||
AddResource(kV8HandlerCallOnReleasedContextChildUrl,
|
||||
"<html><body>"
|
||||
"(child)"
|
||||
"<script>"
|
||||
"try {"
|
||||
" if (!window.v8_context_is_alive()) {"
|
||||
" throw 'v8_context_is_alive returns non-true value.';"
|
||||
" }"
|
||||
"} catch (e) {"
|
||||
" alert('Unit test error.\\n' + e);"
|
||||
"}"
|
||||
""
|
||||
"function removeMe() {"
|
||||
" var w = window;"
|
||||
" w.parent.removeFrame('child');"
|
||||
" return w.v8_context_is_alive();"
|
||||
"}"
|
||||
"</script>"
|
||||
"</body></html>",
|
||||
"text/html");
|
||||
CreateBrowser(kV8HandlerCallOnReleasedContextUrl);
|
||||
} else {
|
||||
EXPECT_TRUE(test_url_ != NULL);
|
||||
AddResource(test_url_,
|
||||
@ -2879,3 +3011,6 @@ V8_TEST(StackTrace, V8TEST_STACK_TRACE);
|
||||
V8_TEST(OnUncaughtException, V8TEST_ON_UNCAUGHT_EXCEPTION);
|
||||
V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS);
|
||||
V8_TEST(Extension, V8TEST_EXTENSION);
|
||||
V8_TEST_EX(HandlerCallOnReleasedContext,
|
||||
V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT,
|
||||
kV8HandlerCallOnReleasedContextUrl)
|
||||
|
Loading…
x
Reference in New Issue
Block a user