1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
// Copyright (c) 2011 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 "content/test/plugin/plugin_delete_plugin_in_deallocate_test.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
namespace {
NPAPIClient::DeletePluginInDeallocateTest* g_signalling_instance_ = NULL;
class DeletePluginInDeallocateTestNPObject : public NPObject {
public:
DeletePluginInDeallocateTestNPObject()
: NPObject(), id_(NULL), host_functions_(NULL), deallocate_count_(0) {}
static NPObject* Allocate(NPP npp, NPClass* npclass) {
return new DeletePluginInDeallocateTestNPObject();
}
static void Deallocate(NPObject* npobject) {
DeletePluginInDeallocateTestNPObject* object =
reinterpret_cast<DeletePluginInDeallocateTestNPObject*>(npobject);
++object->deallocate_count_;
// Call window.deletePlugin to tear-down our plugin from inside deallocate.
if (object->deallocate_count_ == 1) {
NPIdentifier delete_id =
object->host_functions_->getstringidentifier("deletePlugin");
NPObject* window_obj = NULL;
object->host_functions_->getvalue(object->id_, NPNVWindowNPObject,
&window_obj);
NPVariant rv;
object->host_functions_->invoke(object->id_, window_obj, delete_id, NULL,
0, &rv);
}
}
NPP id_;
NPNetscapeFuncs* host_functions_;
int deallocate_count_;
};
NPClass* GetDeletePluginInDeallocateTestClass() {
static NPClass plugin_class = {
NP_CLASS_STRUCT_VERSION,
DeletePluginInDeallocateTestNPObject::Allocate,
DeletePluginInDeallocateTestNPObject::Deallocate,
NULL, // Invalidate
NULL, // HasMethod
NULL, // Invoke
NULL, // InvokeDefault
NULL, // HasProperty
NULL, // GetProperty
NULL, // SetProperty
NULL, // RemoveProperty
};
return &plugin_class;
}
} // namespace
namespace NPAPIClient {
DeletePluginInDeallocateTest::DeletePluginInDeallocateTest(
NPP id, NPNetscapeFuncs* host_functions)
: PluginTest(id, host_functions), npobject_(NULL), test_started_(false) {
}
NPError DeletePluginInDeallocateTest::SetWindow(NPWindow* pNPWindow) {
#if !defined(OS_MACOSX)
if (pNPWindow->window == NULL)
return NPERR_NO_ERROR;
#endif
// Ensure that we run the test once, even if SetWindow is called again.
if (test_started_)
return NPERR_NO_ERROR;
test_started_ = true;
// Because of http://crbug.com/94829, we have to have a second plugin
// instance that we can use to signal completion.
if (test_id() == "signaller") {
g_signalling_instance_ = this;
return NPERR_NO_ERROR;
}
// Create a custom NPObject and give our Id and the Netscape function table.
npobject_ = HostFunctions()->createobject(
id(), GetDeletePluginInDeallocateTestClass());
DeletePluginInDeallocateTestNPObject* test_object =
reinterpret_cast<DeletePluginInDeallocateTestNPObject*>(npobject_);
test_object->id_ = id();
test_object->host_functions_ = HostFunctions();
// Fetch the window script object for our page.
NPObject* window = NULL;
HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window);
// Pass it to the window.setTestObject function, which will later release it.
NPIdentifier set_test_object_id =
HostFunctions()->getstringidentifier("setTestObject");
NPVariant func_var;
NULL_TO_NPVARIANT(func_var);
HostFunctions()->getproperty(id(), window, set_test_object_id, &func_var);
NPObject* func = NPVARIANT_TO_OBJECT(func_var);
NPVariant func_arg;
OBJECT_TO_NPVARIANT(npobject_, func_arg);
NPVariant func_result;
HostFunctions()->invokeDefault(id(), func, &func_arg, 1,
&func_result);
// Release the object - the page's reference should keep it alive.
HostFunctions()->releaseobject(npobject_);
return NPERR_NO_ERROR;
}
NPError DeletePluginInDeallocateTest::Destroy() {
// Because of http://crbug.com/94829, we can't signal completion from within
// the NPP_Destroy of the plugin that is being destroyed. We work-around
// that by testing using a second instance, and signalling though the main
// test instance.
// There should always be a signalling instance by the time we reach here.
if (!g_signalling_instance_)
return NPERR_NO_ERROR;
// If we're the signalling instance, do nothing.
if (g_signalling_instance_ == this)
return NPERR_NO_ERROR;
if (!npobject_) {
g_signalling_instance_->SetError("SetWindow was not invoked.");
} else {
// Verify that our object was deallocated exactly once.
DeletePluginInDeallocateTestNPObject* test_object =
reinterpret_cast<DeletePluginInDeallocateTestNPObject*>(npobject_);
if (test_object->deallocate_count_ != 1)
g_signalling_instance_->SetError(
"Object was not deallocated exactly once.");
delete test_object;
}
g_signalling_instance_->SignalTestCompleted();
return NPERR_NO_ERROR;
}
} // namespace NPAPIClient
|