diff options
author | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-30 20:09:46 +0000 |
---|---|---|
committer | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-30 20:09:46 +0000 |
commit | 6d98bcf2015ef0bd8ce67f79afe9d48225e59ed7 (patch) | |
tree | 5b6a3505ac52b3cab763b4045bd1fa036d86e5de | |
parent | 1a9ae172dde1aed6720c7f00110d720eb1d0088f (diff) | |
download | chromium_src-6d98bcf2015ef0bd8ce67f79afe9d48225e59ed7.zip chromium_src-6d98bcf2015ef0bd8ce67f79afe9d48225e59ed7.tar.gz chromium_src-6d98bcf2015ef0bd8ce67f79afe9d48225e59ed7.tar.bz2 |
Ensure that NPN_PluginThreadAsyncCall callbacks are not invoked after NPP_Destroy.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/338050
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30628 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/test/data/npapi/plugin_thread_async_call.html | 42 | ||||
-rw-r--r-- | chrome/test/ui/npapi_uitest.cc | 7 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_instance.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_client.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_thread_async_call_test.cc | 92 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_thread_async_call_test.h | 31 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.gyp | 2 |
7 files changed, 181 insertions, 1 deletions
diff --git a/chrome/test/data/npapi/plugin_thread_async_call.html b/chrome/test/data/npapi/plugin_thread_async_call.html new file mode 100644 index 0000000..156c844 --- /dev/null +++ b/chrome/test/data/npapi/plugin_thread_async_call.html @@ -0,0 +1,42 @@ +<html> + +<head> +<script src="npapi.js"></script> +<script> + function deleteShortLivedInstance() { + var shortLivedDiv = document.getElementById("short_lived_div"); + shortLivedDiv.innerHTML = "Instance deleted"; + } +</script> +</head> + + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +NPAPI NPN_PluginThreadAsyncCall test<p> +Tests that a plugin can schedule async callbacks.<P> + +<embed type="application/vnd.npapi-test" + src="foo" + name="plugin_thread_async_call" + id="1" + short_lived="false" + mode="np_embed" +> + +<div id="short_lived_div"> + <embed type="application/vnd.npapi-test" + src="foo" + name="plugin_thread_async_call" + id="2" + short_lived="true" + mode="np_embed" + > +</div> + +</body> +</html> diff --git a/chrome/test/ui/npapi_uitest.cc b/chrome/test/ui/npapi_uitest.cc index 206fdd2..e68bf7f 100644 --- a/chrome/test/ui/npapi_uitest.cc +++ b/chrome/test/ui/npapi_uitest.cc @@ -300,6 +300,13 @@ TEST_F(NPAPITester, ScheduleTimer) { kTestCompleteSuccess, kShortWaitTimeout); } +TEST_F(NPAPITester, PluginThreadAsyncCall) { + GURL url = GetTestUrl(L"npapi", L"plugin_thread_async_call.html"); + NavigateToURL(url); + WaitForFinish("plugin_thread_async_call", "1", url, kTestCompleteCookie, + kTestCompleteSuccess, kShortWaitTimeout); +} + // Test checking the privacy mode is on. TEST_F(NPAPIIncognitoTester, PrivateEnabled) { if (UITest::in_process_renderer()) diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc index 8ae1aeb..458d287 100644 --- a/webkit/glue/plugins/plugin_instance.cc +++ b/webkit/glue/plugins/plugin_instance.cc @@ -365,7 +365,9 @@ void PluginInstance::PluginThreadAsyncCall(void (*func)(void *), void PluginInstance::OnPluginThreadAsyncCall(void (*func)(void *), void *user_data) { - func(user_data); + // Do not invoke the callback if NPP_Destroy has already been invoked. + if (webplugin_) + func(user_data); } uint32 PluginInstance::ScheduleTimer(uint32 interval, diff --git a/webkit/glue/plugins/test/plugin_client.cc b/webkit/glue/plugins/test/plugin_client.cc index 3bde2c1..7d9a468 100644 --- a/webkit/glue/plugins/test/plugin_client.cc +++ b/webkit/glue/plugins/test/plugin_client.cc @@ -17,6 +17,7 @@ #include "webkit/glue/plugins/test/plugin_new_fails_test.h" #include "webkit/glue/plugins/test/plugin_private_test.h" #include "webkit/glue/plugins/test/plugin_schedule_timer_test.h" +#include "webkit/glue/plugins/test/plugin_thread_async_call_test.h" #include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h" #include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h" #include "webkit/glue/plugins/test/plugin_window_size_test.h" @@ -169,6 +170,9 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, } else if (test_name == "plugin_popup_with_plugin_target") { new_test = new NPAPIClient::ExecuteJavascriptPopupWindowTargetPluginTest( instance, NPAPIClient::PluginClient::HostFunctions()); + } else if (test_name == "plugin_thread_async_call") { + new_test = new NPAPIClient::PluginThreadAsyncCallTest( + instance, NPAPIClient::PluginClient::HostFunctions()); } else if (test_name == "private") { new_test = new NPAPIClient::PrivateTest(instance, NPAPIClient::PluginClient::HostFunctions()); diff --git a/webkit/glue/plugins/test/plugin_thread_async_call_test.cc b/webkit/glue/plugins/test/plugin_thread_async_call_test.cc new file mode 100644 index 0000000..11d514d --- /dev/null +++ b/webkit/glue/plugins/test/plugin_thread_async_call_test.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2006-2008 The Chromium 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 "webkit/glue/plugins/test/plugin_thread_async_call_test.h" +#include "webkit/glue/plugins/test/plugin_client.h" + +namespace NPAPIClient { + +namespace { + +// There are two plugin instances in this test. The long lived instance is used +// for reporting errors and signalling test completion. The short lived one is +// used to verify that async callbacks are not invoked after NPP_Destroy. +PluginThreadAsyncCallTest* g_short_lived_instance; +PluginThreadAsyncCallTest* g_long_lived_instance; + +void OnCallSucceededHelper(void* data) { + static_cast<PluginThreadAsyncCallTest*>(data)->OnCallSucceeded(); +} + +void OnCallFailed(void* data) { + g_long_lived_instance->SetError("Async callback invoked after NPP_Destroy"); +} + +void OnCallCompletedHelper(void* data) { + static_cast<PluginThreadAsyncCallTest*>(data)->OnCallCompleted(); +} +} + +PluginThreadAsyncCallTest::PluginThreadAsyncCallTest( + NPP id, NPNetscapeFuncs *host_functions) + : PluginTest(id, host_functions) { +} + +NPError PluginThreadAsyncCallTest::New( + uint16 mode, int16 argc, const char* argn[], const char* argv[], + NPSavedData* saved) { + NPError error = PluginTest::New(mode, argc, argn, argv, saved); + if (error != NPERR_NO_ERROR) + return error; + + // Determine whether this is the short lived instance. + for (int i = 0; i < argc; ++i) { + if (base::strcasecmp(argn[i], "short_lived") == 0) { + if (base::strcasecmp(argv[i], "true") == 0) { + g_short_lived_instance = this; + } else { + g_long_lived_instance = this; + } + } + } + + // Schedule an async call that will succeed. + if (this == g_short_lived_instance) { + HostFunctions()->pluginthreadasynccall(id(), OnCallSucceededHelper, this); + } + + return NPERR_NO_ERROR; +} + +void PluginThreadAsyncCallTest::OnCallSucceeded() { + // Delete the short lived instance. + NPIdentifier delete_id = HostFunctions()->getstringidentifier( + "deleteShortLivedInstance"); + + NPObject *window_obj = NULL; + HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj); + + NPVariant result; + HostFunctions()->invoke(id(), window_obj, delete_id, NULL, 0, &result); +} + +NPError PluginThreadAsyncCallTest::Destroy() { + if (this == g_short_lived_instance) { + // Schedule an async call that should not be called. + HostFunctions()->pluginthreadasynccall(id(), OnCallFailed, NULL); + + // Schedule an async call to end the test using the long lived instance. + HostFunctions()->pluginthreadasynccall(g_long_lived_instance->id(), + OnCallCompletedHelper, + g_long_lived_instance); + } + + return NPERR_NO_ERROR; +} + +void PluginThreadAsyncCallTest::OnCallCompleted() { + SignalTestCompleted(); +} + +} // namespace NPAPIClient diff --git a/webkit/glue/plugins/test/plugin_thread_async_call_test.h b/webkit/glue/plugins/test/plugin_thread_async_call_test.h new file mode 100644 index 0000000..ff39ed8 --- /dev/null +++ b/webkit/glue/plugins/test/plugin_thread_async_call_test.h @@ -0,0 +1,31 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H +#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H + +#include <vector> + +#include "webkit/glue/plugins/test/plugin_test.h" + +namespace NPAPIClient { + +// This class tests scheduling and unscheduling of async callbacks using +// NPN_PluginThreadAsyncCall. +class PluginThreadAsyncCallTest : public PluginTest { + public: + PluginThreadAsyncCallTest(NPP id, NPNetscapeFuncs *host_functions); + + virtual NPError New(uint16 mode, int16 argc, const char* argn[], + const char* argv[], NPSavedData* saved); + + virtual NPError Destroy(); + + void OnCallSucceeded(); + void OnCallCompleted(); +}; + +} // namespace NPAPIClient + +#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_THREAD_ASYNC_CALL_TEST_H diff --git a/webkit/tools/test_shell/test_shell.gyp b/webkit/tools/test_shell/test_shell.gyp index f0fe364..d7a18d2 100644 --- a/webkit/tools/test_shell/test_shell.gyp +++ b/webkit/tools/test_shell/test_shell.gyp @@ -578,6 +578,8 @@ '../../glue/plugins/test/plugin_npobject_proxy_test.h', '../../glue/plugins/test/plugin_schedule_timer_test.cc', '../../glue/plugins/test/plugin_schedule_timer_test.h', + '../../glue/plugins/test/plugin_thread_async_call_test.cc', + '../../glue/plugins/test/plugin_thread_async_call_test.h', '../../glue/plugins/test/plugin_windowed_test.cc', '../../glue/plugins/test/plugin_windowed_test.h', '../../glue/plugins/test/plugin_private_test.cc', |