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
16namespace NPAPIClient {
17
18namespace {
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.
23PluginThreadAsyncCallTest* g_short_lived_instance;
24PluginThreadAsyncCallTest* g_long_lived_instance;
25
26void OnCallSucceededHelper(void* data) {
27  static_cast<PluginThreadAsyncCallTest*>(data)->OnCallSucceeded();
28}
29
30void OnCallFailed(void* data) {
31  g_long_lived_instance->SetError("Async callback invoked after NPP_Destroy");
32}
33
34void OnCallCompletedHelper(void* data) {
35  static_cast<PluginThreadAsyncCallTest*>(data)->OnCallCompleted();
36}
37}
38
39PluginThreadAsyncCallTest::PluginThreadAsyncCallTest(
40    NPP id, NPNetscapeFuncs *host_functions)
41    : PluginTest(id, host_functions), at_exit_manager_(NULL) {
42}
43
44PluginThreadAsyncCallTest::~PluginThreadAsyncCallTest() {
45  delete at_exit_manager_;
46}
47
48NPError 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
83void PluginThreadAsyncCallTest::AsyncCall() {
84  HostFunctions()->pluginthreadasynccall(id(), OnCallSucceededHelper, this);
85}
86
87void 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
99NPError 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
113void PluginThreadAsyncCallTest::OnCallCompleted() {
114  SignalTestCompleted();
115}
116
117}  // namespace NPAPIClient
118