• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #define UNIT_TEST  // To get the ShadowingAtExitManager.
6 #include "base/at_exit.h"
7 
8 #include "content/test/plugin/plugin_thread_async_call_test.h"
9 
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"
15 
16 namespace NPAPIClient {
17 
18 namespace {
19 
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;
25 
OnCallSucceededHelper(void * data)26 void OnCallSucceededHelper(void* data) {
27   static_cast<PluginThreadAsyncCallTest*>(data)->OnCallSucceeded();
28 }
29 
OnCallFailed(void * data)30 void OnCallFailed(void* data) {
31   g_long_lived_instance->SetError("Async callback invoked after NPP_Destroy");
32 }
33 
OnCallCompletedHelper(void * data)34 void OnCallCompletedHelper(void* data) {
35   static_cast<PluginThreadAsyncCallTest*>(data)->OnCallCompleted();
36 }
37 }
38 
PluginThreadAsyncCallTest(NPP id,NPNetscapeFuncs * host_functions)39 PluginThreadAsyncCallTest::PluginThreadAsyncCallTest(
40     NPP id, NPNetscapeFuncs *host_functions)
41     : PluginTest(id, host_functions), at_exit_manager_(NULL) {
42 }
43 
~PluginThreadAsyncCallTest()44 PluginThreadAsyncCallTest::~PluginThreadAsyncCallTest() {
45   delete at_exit_manager_;
46 }
47 
New(uint16 mode,int16 argc,const char * argn[],const char * argv[],NPSavedData * saved)48 NPError PluginThreadAsyncCallTest::New(
49     uint16 mode, int16 argc, const char* argn[], const char* argv[],
50     NPSavedData* saved) {
51   NPError error = PluginTest::New(mode, argc, argn, argv, saved);
52   if (error != NPERR_NO_ERROR)
53     return error;
54 
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;
60       } else {
61         g_long_lived_instance = this;
62       }
63     }
64   }
65 
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 plug-in and
71     // the base code.
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)));
78   }
79 
80   return NPERR_NO_ERROR;
81 }
82 
AsyncCall()83 void PluginThreadAsyncCallTest::AsyncCall() {
84   HostFunctions()->pluginthreadasynccall(id(), OnCallSucceededHelper, this);
85 }
86 
OnCallSucceeded()87 void PluginThreadAsyncCallTest::OnCallSucceeded() {
88   // Delete the short lived instance.
89   NPIdentifier delete_id = HostFunctions()->getstringidentifier(
90       "deleteShortLivedInstance");
91 
92   NPObject *window_obj = NULL;
93   HostFunctions()->getvalue(id(), NPNVWindowNPObject, &window_obj);
94 
95   NPVariant result;
96   HostFunctions()->invoke(id(), window_obj, delete_id, NULL, 0, &result);
97 }
98 
Destroy()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);
103 
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);
108   }
109 
110   return NPERR_NO_ERROR;
111 }
112 
OnCallCompleted()113 void PluginThreadAsyncCallTest::OnCallCompleted() {
114   SignalTestCompleted();
115 }
116 
117 }  // namespace NPAPIClient
118