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 43extern Logger * logger; 44 45InstanceList::InstanceList(NPP _instance) : 46 next(NULL), 47 instance(_instance) 48{ 49} 50 51InstanceList::~InstanceList() 52{ 53} 54 55PluginEntryPointList::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 65PluginEntryPointList::~PluginEntryPointList() 66{ 67} 68 69NPPEntryPointManager::NPPEntryPointManager() : 70 mEntryPoints(NULL) 71{ 72} 73 74NPPEntryPointManager::~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 91void 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 127void 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 151NPPluginFuncs * 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 162NPPluginFuncs * 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 176void 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 189void 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 208NPError 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 236NPError 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 281NPError 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 290NPError 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 299NPError 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 308int32 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 317int32 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 326void 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 335void 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 344void 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 353NPError 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 362NPError 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 371int16 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