1 // Copyright (c) 2012 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 #include "content/test/plugin/plugin_client.h" 6 7 #include "base/strings/string_util.h" 8 #include "content/test/plugin/plugin_execute_stream_javascript.h" 9 #include "content/test/plugin/plugin_test.h" 10 #include "content/test/plugin/plugin_test_factory.h" 11 12 namespace NPAPIClient { 13 14 NPNetscapeFuncs* PluginClient::host_functions_; 15 16 NPError PluginClient::GetEntryPoints(NPPluginFuncs* pFuncs) { 17 if (pFuncs == NULL) 18 return NPERR_INVALID_FUNCTABLE_ERROR; 19 20 if (pFuncs->size < sizeof(NPPluginFuncs)) 21 return NPERR_INVALID_FUNCTABLE_ERROR; 22 23 pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; 24 pFuncs->newp = NPP_New; 25 pFuncs->destroy = NPP_Destroy; 26 pFuncs->setwindow = NPP_SetWindow; 27 pFuncs->newstream = NPP_NewStream; 28 pFuncs->destroystream = NPP_DestroyStream; 29 pFuncs->asfile = NPP_StreamAsFile; 30 pFuncs->writeready = NPP_WriteReady; 31 pFuncs->write = NPP_Write; 32 pFuncs->print = NPP_Print; 33 pFuncs->event = NPP_HandleEvent; 34 pFuncs->urlnotify = NPP_URLNotify; 35 pFuncs->getvalue = NPP_GetValue; 36 pFuncs->setvalue = NPP_SetValue; 37 pFuncs->javaClass = NULL; 38 pFuncs->urlredirectnotify = NPP_URLRedirectNotify; 39 pFuncs->clearsitedata = NPP_ClearSiteData; 40 41 return NPERR_NO_ERROR; 42 } 43 44 NPError PluginClient::Initialize(NPNetscapeFuncs* pFuncs) { 45 if (pFuncs == NULL) { 46 return NPERR_INVALID_FUNCTABLE_ERROR; 47 } 48 49 if (static_cast<unsigned char>((pFuncs->version >> 8) & 0xff) > 50 NP_VERSION_MAJOR) { 51 return NPERR_INCOMPATIBLE_VERSION_ERROR; 52 } 53 54 #if defined(OS_WIN) 55 // Check if we should crash. 56 HANDLE crash_event = CreateEvent(NULL, TRUE, FALSE, L"TestPluginCrashOnInit"); 57 if (WaitForSingleObject(crash_event, 0) == WAIT_OBJECT_0) { 58 int *zero = NULL; 59 *zero = 0; 60 } 61 CloseHandle(crash_event); 62 #endif 63 64 host_functions_ = pFuncs; 65 66 return NPERR_NO_ERROR; 67 } 68 69 NPError PluginClient::Shutdown() { 70 return NPERR_NO_ERROR; 71 } 72 73 } // namespace NPAPIClient 74 75 extern "C" { 76 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, 77 int16 argc, char* argn[], char* argv[], NPSavedData* saved) { 78 if (instance == NULL) 79 return NPERR_INVALID_INSTANCE_ERROR; 80 81 NPAPIClient::PluginTest* new_test = NULL; 82 if (mode == NP_FULL) { 83 new_test = new::NPAPIClient::ExecuteStreamJavaScript( 84 instance, NPAPIClient::PluginClient::HostFunctions()); 85 } else { 86 // We look at the test name requested via the plugin arguments. We match 87 // that against a given test and try to instantiate it. 88 89 // lookup the name parameter 90 std::string test_name; 91 for (int name_index = 0; name_index < argc; name_index++) { 92 if (base::strcasecmp(argn[name_index], "name") == 0) { 93 test_name = argv[name_index]; 94 break; 95 } 96 } 97 if (test_name.empty()) 98 return NPERR_GENERIC_ERROR; // no name found 99 100 new_test = NPAPIClient::CreatePluginTest(test_name, 101 instance, NPAPIClient::PluginClient::HostFunctions()); 102 if (new_test == NULL) { 103 // If we don't have a test case for this, create a 104 // generic one which basically never fails. 105 LOG(WARNING) << "Unknown test name '" << test_name 106 << "'; using default test."; 107 new_test = new NPAPIClient::PluginTest(instance, 108 NPAPIClient::PluginClient::HostFunctions()); 109 } 110 } 111 112 #if defined(OS_MACOSX) 113 // Set modern drawing and event models. 114 NPError drawing_ret = NPAPIClient::PluginClient::HostFunctions()->setvalue( 115 instance, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics); 116 NPError event_ret = NPAPIClient::PluginClient::HostFunctions()->setvalue( 117 instance, NPPVpluginEventModel, (void*)NPEventModelCocoa); 118 if (drawing_ret != NPERR_NO_ERROR || event_ret != NPERR_NO_ERROR) 119 return NPERR_INCOMPATIBLE_VERSION_ERROR; 120 #endif 121 122 NPError ret = new_test->New(mode, argc, (const char**)argn, 123 (const char**)argv, saved); 124 if ((ret == NPERR_NO_ERROR) && new_test->IsWindowless()) { 125 NPAPIClient::PluginClient::HostFunctions()->setvalue( 126 instance, NPPVpluginWindowBool, NULL); 127 } 128 129 return ret; 130 } 131 132 NPError NPP_Destroy(NPP instance, NPSavedData** save) { 133 if (instance == NULL) 134 return NPERR_INVALID_INSTANCE_ERROR; 135 136 NPAPIClient::PluginTest* plugin = 137 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 138 139 NPError rv = plugin->Destroy(); 140 delete plugin; 141 return rv; 142 } 143 144 NPError NPP_SetWindow(NPP instance, NPWindow* pNPWindow) { 145 if (instance == NULL) 146 return NPERR_INVALID_INSTANCE_ERROR; 147 148 NPAPIClient::PluginTest* plugin = 149 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 150 151 return plugin->SetWindow(pNPWindow); 152 } 153 154 NPError NPP_NewStream(NPP instance, NPMIMEType type, 155 NPStream* stream, NPBool seekable, uint16* stype) { 156 if (instance == NULL) 157 return NPERR_INVALID_INSTANCE_ERROR; 158 159 NPAPIClient::PluginTest* plugin = 160 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 161 162 return plugin->NewStream(type, stream, seekable, stype); 163 } 164 165 int32 NPP_WriteReady(NPP instance, NPStream *stream) { 166 if (instance == NULL) 167 return NPERR_INVALID_INSTANCE_ERROR; 168 169 NPAPIClient::PluginTest* plugin = 170 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 171 172 return plugin->WriteReady(stream); 173 } 174 175 int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, 176 int32 len, void *buffer) { 177 if (instance == NULL) 178 return NPERR_INVALID_INSTANCE_ERROR; 179 180 NPAPIClient::PluginTest* plugin = 181 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 182 183 return plugin->Write(stream, offset, len, buffer); 184 } 185 186 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) { 187 if (instance == NULL) 188 return NPERR_INVALID_INSTANCE_ERROR; 189 190 NPAPIClient::PluginTest* plugin = 191 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 192 193 return plugin->DestroyStream(stream, reason); 194 } 195 196 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) { 197 if (instance == NULL) 198 return; 199 200 NPAPIClient::PluginTest* plugin = 201 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 202 203 return plugin->StreamAsFile(stream, fname); 204 } 205 206 void NPP_Print(NPP instance, NPPrint* printInfo) { 207 if (instance == NULL) 208 return; 209 210 // XXXMB - do work here. 211 } 212 213 void NPP_URLNotify(NPP instance, const char* url, NPReason reason, 214 void* notifyData) { 215 if (instance == NULL) 216 return; 217 218 NPAPIClient::PluginTest* plugin = 219 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 220 221 return plugin->URLNotify(url, reason, notifyData); 222 } 223 224 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) { 225 if (instance == NULL) 226 return NPERR_INVALID_INSTANCE_ERROR; 227 228 if (variable == NPPVpluginNeedsXEmbed) { 229 *static_cast<NPBool*>(value) = 1; 230 return NPERR_NO_ERROR; 231 } 232 233 // XXXMB - do work here. 234 return NPERR_GENERIC_ERROR; 235 } 236 237 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) { 238 if (instance == NULL) 239 return NPERR_INVALID_INSTANCE_ERROR; 240 241 // XXXMB - do work here. 242 return NPERR_GENERIC_ERROR; 243 } 244 245 int16 NPP_HandleEvent(NPP instance, void* event) { 246 if (instance == NULL) 247 return 0; 248 249 NPAPIClient::PluginTest* plugin = 250 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 251 252 return plugin->HandleEvent(event); 253 } 254 255 void NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, 256 void* notify_data) { 257 if (instance) { 258 NPAPIClient::PluginTest* plugin = 259 reinterpret_cast<NPAPIClient::PluginTest*>(instance->pdata); 260 plugin->URLRedirectNotify(url, status, notify_data); 261 } 262 } 263 264 NPError NPP_ClearSiteData(const char* site, 265 uint64 flags, 266 uint64 max_age) { 267 VLOG(0) << "NPP_ClearSiteData called"; 268 return NPERR_NO_ERROR; 269 } 270 } // extern "C" 271