summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-30 20:09:46 +0000
committerapatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-30 20:09:46 +0000
commit6d98bcf2015ef0bd8ce67f79afe9d48225e59ed7 (patch)
tree5b6a3505ac52b3cab763b4045bd1fa036d86e5de
parent1a9ae172dde1aed6720c7f00110d720eb1d0088f (diff)
downloadchromium_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.html42
-rw-r--r--chrome/test/ui/npapi_uitest.cc7
-rw-r--r--webkit/glue/plugins/plugin_instance.cc4
-rw-r--r--webkit/glue/plugins/test/plugin_client.cc4
-rw-r--r--webkit/glue/plugins/test/plugin_thread_async_call_test.cc92
-rw-r--r--webkit/glue/plugins/test/plugin_thread_async_call_test.h31
-rw-r--r--webkit/tools/test_shell/test_shell.gyp2
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',