1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #define UNIT_TEST // To get the ShadowingAtExitManager.
6 #include "base/at_exit.h"
8 #include "content/test/plugin/plugin_thread_async_call_test.h"
10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/string_util.h"
13 #include "base/threading/thread.h"
14 #include "content/test/plugin/plugin_client.h"
16 namespace NPAPIClient
{
20 // There are two plugin instances in this test. The long lived instance is used
21 // for reporting errors and signalling test completion. The short lived one is
22 // used to verify that async callbacks are not invoked after NPP_Destroy.
23 PluginThreadAsyncCallTest
* g_short_lived_instance
;
24 PluginThreadAsyncCallTest
* g_long_lived_instance
;
26 void OnCallSucceededHelper(void* data
) {
27 static_cast<PluginThreadAsyncCallTest
*>(data
)->OnCallSucceeded();
30 void OnCallFailed(void* data
) {
31 g_long_lived_instance
->SetError("Async callback invoked after NPP_Destroy");
34 void OnCallCompletedHelper(void* data
) {
35 static_cast<PluginThreadAsyncCallTest
*>(data
)->OnCallCompleted();
39 PluginThreadAsyncCallTest::PluginThreadAsyncCallTest(
40 NPP id
, NPNetscapeFuncs
*host_functions
)
41 : PluginTest(id
, host_functions
), at_exit_manager_(NULL
) {
44 PluginThreadAsyncCallTest::~PluginThreadAsyncCallTest() {
45 delete at_exit_manager_
;
48 NPError
PluginThreadAsyncCallTest::New(
49 uint16 mode
, int16 argc
, const char* argn
[], const char* argv
[],
51 NPError error
= PluginTest::New(mode
, argc
, argn
, argv
, saved
);
52 if (error
!= NPERR_NO_ERROR
)
55 // Determine whether this is the short lived instance.
56 for (int i
= 0; i
< argc
; ++i
) {
57 if (base::strcasecmp(argn
[i
], "short_lived") == 0) {
58 if (base::strcasecmp(argv
[i
], "true") == 0) {
59 g_short_lived_instance
= this;
61 g_long_lived_instance
= this;
66 // Schedule an async call that will succeed. Make sure to call that API from
67 // a different thread to fully test it.
68 if (this == g_short_lived_instance
) {
69 // This is slightly complicated thanks to the Linux shared library build,
70 // which shares more compilation units between the NPAPI plugin and
72 at_exit_manager_
= new base::ShadowingAtExitManager();
73 base::Thread
random_thread("random_thread");
74 random_thread
.Start();
75 random_thread
.message_loop()->PostTask(
76 FROM_HERE
, base::Bind(&PluginThreadAsyncCallTest::AsyncCall
,
77 base::Unretained(this)));
80 return NPERR_NO_ERROR
;
83 void PluginThreadAsyncCallTest::AsyncCall() {
84 HostFunctions()->pluginthreadasynccall(id(), OnCallSucceededHelper
, this);
87 void PluginThreadAsyncCallTest::OnCallSucceeded() {
88 // Delete the short lived instance.
89 NPIdentifier delete_id
= HostFunctions()->getstringidentifier(
90 "deleteShortLivedInstance");
92 NPObject
*window_obj
= NULL
;
93 HostFunctions()->getvalue(id(), NPNVWindowNPObject
, &window_obj
);
96 HostFunctions()->invoke(id(), window_obj
, delete_id
, NULL
, 0, &result
);
99 NPError
PluginThreadAsyncCallTest::Destroy() {
100 if (this == g_short_lived_instance
) {
101 // Schedule an async call that should not be called.
102 HostFunctions()->pluginthreadasynccall(id(), OnCallFailed
, NULL
);
104 // Schedule an async call to end the test using the long lived instance.
105 HostFunctions()->pluginthreadasynccall(g_long_lived_instance
->id(),
106 OnCallCompletedHelper
,
107 g_long_lived_instance
);
110 return NPERR_NO_ERROR
;
113 void PluginThreadAsyncCallTest::OnCallCompleted() {
114 SignalTestCompleted();
117 } // namespace NPAPIClient