1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* ***** BEGIN LICENSE BLOCK ***** 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * http://www.mozilla.org/MPL/ 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 13 * License. 14 * 15 * The Original Code is mozilla.org code. 16 * 17 * The Initial Developer of the Original Code is 18 * Netscape Communications Corporation. 19 * Portions created by the Initial Developer are Copyright (C) 1998 20 * the Initial Developer. All Rights Reserved. 21 * 22 * Contributor(s): 23 * 24 * Alternatively, the contents of this file may be used under the terms of 25 * either the GNU General Public License Version 2 or later (the "GPL"), or 26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 * in which case the provisions of the GPL or the LGPL are applicable instead 28 * of those above. If you wish to allow use of your version of this file only 29 * under the terms of either the GPL or the LGPL, and not to allow others to 30 * use your version of this file under the terms of the MPL, indicate your 31 * decision by deleting the provisions above and replace them with the notice 32 * and other provisions required by the GPL or the LGPL. If you do not delete 33 * the provisions above, a recipient may use your version of this file under 34 * the terms of any one of the MPL, the GPL or the LGPL. 35 * 36 * ***** END LICENSE BLOCK ***** */ 37 38 #include "xp.h" 39 40 #include "epmanager.h" 41 #include "logger.h" 42 43 extern Logger * logger; 44 45 InstanceList::InstanceList(NPP _instance) : 46 next(NULL), 47 instance(_instance) 48 { 49 } 50 51 InstanceList::~InstanceList() 52 { 53 } 54 55 PluginEntryPointList::PluginEntryPointList() : 56 next(NULL), 57 instances(NULL) 58 { 59 mimetype[0] = '\0'; 60 memset((void *)&realNPPFuncs, 0, sizeof(realNPPFuncs)); 61 realShutdown = NULL; 62 hLib = NULL; 63 } 64 65 PluginEntryPointList::~PluginEntryPointList() 66 { 67 } 68 69 NPPEntryPointManager::NPPEntryPointManager() : 70 mEntryPoints(NULL) 71 { 72 } 73 74 NPPEntryPointManager::~NPPEntryPointManager() 75 { 76 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL;) 77 { 78 for(InstanceList * instances = eps->instances; instances != NULL;) 79 { 80 InstanceList * next = instances->next; 81 delete instances; 82 instances = next; 83 } 84 85 PluginEntryPointList * next = eps->next; 86 delete eps; 87 eps = next; 88 } 89 } 90 91 void NPPEntryPointManager::createEntryPointsForPlugin(char * mimetype, NPPluginFuncs * funcs, NP_SHUTDOWN shutdownproc, XP_HLIB hLib) 92 { 93 PluginEntryPointList * eps = new PluginEntryPointList(); 94 95 if(eps == NULL) 96 return; 97 98 strcpy(eps->mimetype, mimetype); 99 100 if(funcs) 101 { 102 eps->realNPPFuncs.size = funcs->size; 103 eps->realNPPFuncs.version = funcs->version; 104 eps->realNPPFuncs.newp = funcs->newp; 105 eps->realNPPFuncs.destroy = funcs->destroy; 106 eps->realNPPFuncs.setwindow = funcs->setwindow; 107 eps->realNPPFuncs.newstream = funcs->newstream; 108 eps->realNPPFuncs.destroystream = funcs->destroystream; 109 eps->realNPPFuncs.asfile = funcs->asfile; 110 eps->realNPPFuncs.writeready = funcs->writeready; 111 eps->realNPPFuncs.write = funcs->write; 112 eps->realNPPFuncs.print = funcs->print; 113 eps->realNPPFuncs.event = funcs->event; 114 eps->realNPPFuncs.urlnotify = funcs->urlnotify; 115 eps->realNPPFuncs.javaClass = funcs->javaClass; 116 eps->realNPPFuncs.getvalue = funcs->getvalue; 117 118 } 119 120 eps->realShutdown = shutdownproc; 121 eps->hLib = hLib; 122 123 eps->next = mEntryPoints; 124 mEntryPoints = eps; 125 } 126 127 void NPPEntryPointManager::removeEntryPointsForPlugin(NPP instance, XP_HLIB * lib) 128 { 129 NPPluginFuncs * eptoremove = findEntryPointsForInstance(instance); 130 131 PluginEntryPointList * prev = NULL; 132 133 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 134 { 135 if(&eps->realNPPFuncs == eptoremove) 136 { 137 if(prev) 138 prev->next = eps->next; 139 else 140 mEntryPoints = eps->next; 141 142 *lib = eps->hLib; 143 delete eps; 144 return; 145 } 146 147 prev = eps; 148 } 149 } 150 151 NPPluginFuncs * NPPEntryPointManager::findEntryPointsForPlugin(char * mimetype) 152 { 153 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 154 { 155 if(0 == _stricmp(eps->mimetype, mimetype)) 156 return &eps->realNPPFuncs; 157 } 158 159 return NULL; 160 } 161 162 NPPluginFuncs * NPPEntryPointManager::findEntryPointsForInstance(NPP instance) 163 { 164 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 165 { 166 for(InstanceList * instances = eps->instances; instances != NULL; instances = instances->next) 167 { 168 if(instances->instance == instance) 169 return &eps->realNPPFuncs; 170 } 171 } 172 173 return NULL; 174 } 175 176 void NPPEntryPointManager::callNP_ShutdownAll() 177 { 178 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 179 { 180 if(eps->realShutdown) 181 { 182 logger->logSPY_NP_Shutdown(eps->mimetype); 183 eps->realShutdown(); 184 eps->realShutdown = NULL; // don't want to call it more than once 185 } 186 } 187 } 188 189 void NPPEntryPointManager::callNP_Shutdown(NPP instance) 190 { 191 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 192 { 193 for(InstanceList * instances = eps->instances; instances != NULL; instances = instances->next) 194 { 195 if(instances->instance == instance) 196 { 197 if(eps->realShutdown) 198 { 199 logger->logSPY_NP_Shutdown(eps->mimetype); 200 eps->realShutdown(); 201 eps->realShutdown = NULL; // don't want to call it more than once 202 } 203 } 204 } 205 } 206 } 207 208 NPError NPPEntryPointManager::callNPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) 209 { 210 NPPluginFuncs * nppfuncs = NULL; 211 212 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 213 { 214 if(0 == _stricmp(eps->mimetype, pluginType)) 215 { 216 nppfuncs = &eps->realNPPFuncs; 217 218 // now we should associate this plugin instance with plugin entry points 219 // so that later we could find entry points by instance rather than by mimetype 220 InstanceList * inst = new InstanceList(instance); 221 inst->next = eps->instances; 222 eps->instances = inst; 223 224 break; 225 } 226 } 227 228 if(!nppfuncs || !nppfuncs->newp) 229 return NPERR_GENERIC_ERROR; 230 231 NPError rv = CallNPP_NewProc(nppfuncs->newp, pluginType, instance, mode, argc, argn, argv, saved); 232 233 return rv; 234 } 235 236 NPError NPPEntryPointManager::callNPP_Destroy(NPP instance, NPSavedData** save, BOOL * last) 237 { 238 NPPluginFuncs * nppfuncs = NULL; 239 240 BOOL done = FALSE; 241 242 for(PluginEntryPointList * eps = mEntryPoints; eps != NULL; eps = eps->next) 243 { 244 InstanceList * prev = NULL; 245 for(InstanceList * instances = eps->instances; instances != NULL; instances = instances->next) 246 { 247 if(instances->instance == instance) 248 { 249 nppfuncs = &eps->realNPPFuncs; 250 done = TRUE; 251 252 // check if this is the last one 253 if(eps->instances->next == NULL) 254 *last = TRUE; 255 else 256 { 257 // deassociate instance if this is not the last one 258 // last instance will be needed to find corresponding shutdown proc 259 if(prev) 260 prev->next = instances->next; 261 else 262 eps->instances = instances->next; 263 264 delete instances; 265 } 266 267 break; 268 } 269 prev = instances; 270 } 271 if(done) 272 break; 273 } 274 275 if(!nppfuncs || !nppfuncs->destroy) 276 return NPERR_GENERIC_ERROR; 277 278 return CallNPP_DestroyProc(nppfuncs->destroy, instance, save); 279 } 280 281 NPError NPPEntryPointManager::callNPP_SetWindow(NPP instance, NPWindow* window) 282 { 283 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 284 if(!nppfuncs || !nppfuncs->setwindow) 285 return NPERR_GENERIC_ERROR; 286 287 return CallNPP_SetWindowProc(nppfuncs->setwindow, instance, window); 288 } 289 290 NPError NPPEntryPointManager::callNPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) 291 { 292 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 293 if(!nppfuncs || !nppfuncs->newstream) 294 return NPERR_GENERIC_ERROR; 295 296 return CallNPP_NewStreamProc(nppfuncs->newstream, instance, type, stream, seekable, stype); 297 } 298 299 NPError NPPEntryPointManager::callNPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) 300 { 301 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 302 if(!nppfuncs || !nppfuncs->destroystream) 303 return NPERR_GENERIC_ERROR; 304 305 return CallNPP_DestroyStreamProc(nppfuncs->destroystream, instance, stream, reason); 306 } 307 308 int32 NPPEntryPointManager::callNPP_WriteReady(NPP instance, NPStream* stream) 309 { 310 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 311 if(!nppfuncs || !nppfuncs->writeready) 312 return NPERR_GENERIC_ERROR; 313 314 return CallNPP_WriteReadyProc(nppfuncs->writeready, instance, stream); 315 } 316 317 int32 NPPEntryPointManager::callNPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) 318 { 319 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 320 if(!nppfuncs || !nppfuncs->write) 321 return NPERR_GENERIC_ERROR; 322 323 return CallNPP_WriteProc(nppfuncs->write, instance, stream, offset, len, buffer); 324 } 325 326 void NPPEntryPointManager::callNPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) 327 { 328 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 329 if(!nppfuncs || !nppfuncs->asfile) 330 return; 331 332 CallNPP_StreamAsFileProc(nppfuncs->asfile, instance, stream, fname); 333 } 334 335 void NPPEntryPointManager::callNPP_Print(NPP instance, NPPrint* platformPrint) 336 { 337 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 338 if(!nppfuncs || !nppfuncs->print) 339 return; 340 341 CallNPP_PrintProc(nppfuncs->print, instance, platformPrint); 342 } 343 344 void NPPEntryPointManager::callNPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) 345 { 346 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 347 if(!nppfuncs || !nppfuncs->urlnotify) 348 return; 349 350 CallNPP_URLNotifyProc(nppfuncs->urlnotify, instance, url, reason, notifyData); 351 } 352 353 NPError NPPEntryPointManager::callNPP_GetValue(NPP instance, NPPVariable variable, void *value) 354 { 355 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 356 if(!nppfuncs || !nppfuncs->getvalue) 357 return NPERR_GENERIC_ERROR; 358 359 return CallNPP_GetValueProc(nppfuncs->getvalue, instance, variable, value); 360 } 361 362 NPError NPPEntryPointManager::callNPP_SetValue(NPP instance, NPNVariable variable, void *value) 363 { 364 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 365 if(!nppfuncs || !nppfuncs->setvalue) 366 return NPERR_GENERIC_ERROR; 367 368 return CallNPP_SetValueProc(nppfuncs->setvalue, instance, variable, value); 369 } 370 371 int16 NPPEntryPointManager::callNPP_HandleEvent(NPP instance, void* event) 372 { 373 NPPluginFuncs * nppfuncs = findEntryPointsForInstance(instance); 374 if(!nppfuncs || !nppfuncs->event) 375 return NPERR_GENERIC_ERROR; 376 377 return CallNPP_HandleEventProc(nppfuncs->event, instance, event); 378 } 379