peer->GetOwner(owner);
peer->GetOwner(*getter_AddRefs(owner));
nsresult PostPluginUnloadEvent(PRLibrary * aLibrary);/** * Used in DisplayNoDefaultPlugindialog to prevent showing the dialog twice * for the same mimetype. */static nsHashtable *mimeTypesSeen = nsnull;/** * placeholder value for mimeTypesSeen hashtable */static const char *hashValue = "value";/** * Default number of entries in the mimeTypesSeen hashtable */ #define NS_MIME_TYPES_HASH_NUM (20)////////////////////////////////////////////////////////////////////////void DisplayNoDefaultPluginDialog(const char *mimeType, nsIPrompt *prompt){  nsresult rv;  nsCOMPtr<nsIPref> prefs(do_GetService(kPrefServiceCID));  if (!prefs || !prompt)    return;  PRBool displayDialogPrefValue = PR_FALSE;  rv = prefs->GetBoolPref("plugin.display_plugin_downloader_dialog", &displayDialogPrefValue);  // if the pref is false, don't display the dialog  if (NS_SUCCEEDED(rv) && !displayDialogPrefValue)      return;  if (nsnull == mimeTypesSeen) {    mimeTypesSeen = new nsHashtable(NS_MIME_TYPES_HASH_NUM);  }  if ((mimeTypesSeen != nsnull) && (mimeType != nsnull)) {    nsCStringKey key(mimeType);    // if we've seen this mimetype before    if (mimeTypesSeen->Get(&key)) {      // don't display the dialog      return;    }    else {      mimeTypesSeen->Put(&key, (void *) hashValue);    }  }  nsCOMPtr<nsIStringBundleService> strings(do_GetService(kStringBundleServiceCID, &rv));  if (NS_SUCCEEDED(rv)) {    nsCOMPtr<nsIStringBundle> bundle;    if (NS_SUCCEEDED(strings->CreateBundle(PLUGIN_PROPERTIES_URL, getter_AddRefs(bundle)))) {      nsCOMPtr<nsIStringBundle> regionalBundle;      if (NS_SUCCEEDED(strings->CreateBundle(PLUGIN_REGIONAL_URL, getter_AddRefs(regionalBundle)))) {        nsXPIDLString titleUni, messageUni, checkboxMessageUni;        if (NS_SUCCEEDED(bundle->GetStringFromName(              NS_LITERAL_STRING("noDefaultPluginTitle").get(),                getter_Copies(titleUni))) &&            NS_SUCCEEDED(bundle->GetStringFromName(              NS_LITERAL_STRING("noDefaultPluginCheckboxMessage").get(),                getter_Copies(checkboxMessageUni))) &&            NS_SUCCEEDED(regionalBundle->GetStringFromName(              NS_LITERAL_STRING("noDefaultPluginMessage").get(),                getter_Copies(messageUni)))           )         {          PRBool checkboxState = PR_FALSE;          PRInt32 buttonPressed;          rv = prompt->ConfirmEx(titleUni, messageUni,                         nsIPrompt::BUTTON_TITLE_OK * nsIPrompt::BUTTON_POS_0,                         nsnull, nsnull, nsnull,                         checkboxMessageUni, &checkboxState, &buttonPressed);          // if the user checked the checkbox, make it so the dialog doesn't          // display again.          if (NS_SUCCEEDED(rv) && checkboxState) {            prefs->SetBoolPref("plugin.display_plugin_downloader_dialog",                       !checkboxState);          }        }      }    }  }  return;}////////////////////////////////////////////////////////////////////////// flat file reg funcsstaticPRBool ReadSectionHeader(nsManifestLineReader& reader, const char *token){  do {    if (*reader.LinePtr() == '[') {      char* p = reader.LinePtr() + (reader.LineLength() - 1);      if (*p != ']')        break;      *p = 0;            char* values[1];      if (1 != reader.ParseLine(values, 1))        break;      // ignore the leading '['      if (PL_strcmp(values[0]+1, token)) {        break; // it's wrong token      }      return PR_TRUE;    }  } while (reader.NextLine());  return PR_FALSE;}////////////////////////////////////////////////////////////////////////// Little helper struct to asynchronously reframe any presentations (embedded)// or reload any documents (full-page), that contained plugins // which were shutdown as a result of a plugins.refresh(1)struct nsPluginDocReframeEvent: public PLEvent {  nsPluginDocReframeEvent (nsISupportsArray* aDocs)  { mDocs = aDocs; }  nsresult HandlePluginDocReframeEvent();  nsCOMPtr<nsISupportsArray> mDocs;};nsresult nsPluginDocReframeEvent::HandlePluginDocReframeEvent() {      NS_ENSURE_TRUE(mDocs, NS_ERROR_FAILURE);    PRUint32 c;  mDocs->Count(&c);    // for each document (which previously had a running instance), tell  // the frame constructor to rebuild  for (PRUint32 i = 0; i < c; i++) {    nsCOMPtr<nsIDocument> doc (do_QueryElementAt(mDocs, i));    if (doc) {      nsCOMPtr<nsIPresShell> shell;      doc->GetShellAt(0, getter_AddRefs(shell));            // if this document has a presentation shell, then it has frames and can be reframed      if (shell) {        nsCOMPtr<nsIPresContext> pc;        nsCOMPtr<nsIStyleSet> set;        shell->GetPresContext(getter_AddRefs(pc));        shell->GetStyleSet(getter_AddRefs(set));        if (pc && set) {          nsCOMPtr<nsIStyleFrameConstruction> fc;          set->GetStyleFrameConstruction(getter_AddRefs(fc));          if (fc)                     /**          * A reframe will cause a fresh object frame, instance owner, and instance          * to be created. Reframing of the entire document is necessary as we may have          * recently found new plugins and we want a shot at trying to use them instead          * of leaving alternate renderings.          * We do not want to completely reload all the documents that had running plugins          * because we could possibly trigger a script to run in the unload event handler          * which may want to access our defunct plugin and cause us to crash.          */                      fc->ReconstructDocElementHierarchy(pc); // causes reframe of document        }      } else {  // no pres shell --> full-page plugin               /**        * This document does not have a presentation shell. It may be a full-page plugin.        * Full-page plugins don't really have the same problem of crashing because they        * are not currently scriptable. However, they do leave a non-painting, defunct        * window which doesn't look good. A reload of the page for full-page plugins        * is needed to kickstart the instance.        */                nsCOMPtr<nsIScriptGlobalObject> gso;        doc->GetScriptGlobalObject(getter_AddRefs(gso));        if (gso) {          nsCOMPtr<nsIDocShell> docShell;          gso->GetDocShell(getter_AddRefs(docShell));          nsCOMPtr<nsIWebNavigation> webNav (do_QueryInterface(docShell));          if (webNav)            webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);                    else NS_WARNING("refreshing plugins: couldn't get webnav or docshell from gso");        } else NS_WARNING("refreshing plugins: could not get the global script object -- did the plugin set it?");      }    }  }  return mDocs->Clear();}  //----------------------------------------------------------------------static void* PR_CALLBACK HandlePluginDocReframePLEvent(PLEvent* aEvent){  nsPluginDocReframeEvent* event = NS_REINTERPRET_CAST(nsPluginDocReframeEvent*, aEvent);  event->HandlePluginDocReframeEvent();  return nsnull;}static void PR_CALLBACK DestroyPluginDocReframePLEvent(PLEvent* aEvent){  delete aEvent;}////////////////////////////////////////////////////////////////////////nsActivePlugin::nsActivePlugin(nsPluginTag* aPluginTag,                               nsIPluginInstance* aInstance,                                const char * url,                               PRBool aDefaultPlugin,                               nsIPluginInstancePeer* peer){  mNext = nsnull;  mPeer = nsnull;  mPluginTag = aPluginTag;  mURL = PL_strdup(url);  mInstance = aInstance;  if(aInstance && peer)  {    mPeer = peer;    NS_ADDREF(mPeer);    NS_ADDREF(aInstance);  }  mXPConnected = PR_FALSE;  mDefaultPlugin = aDefaultPlugin;  mStopped = PR_FALSE;  mllStopTime = LL_ZERO;  mStreams = new nsVoidArray();   // create a new stream array}////////////////////////////////////////////////////////////////////////nsActivePlugin::~nsActivePlugin(){  mPluginTag = nsnull;  // free our streams array  if (mStreams)  {    delete mStreams;    mStreams = nsnull;  }  if(mInstance != nsnull)  {    if(mPeer)    {      nsresult rv = NS_OK;      nsCOMPtr<nsPIPluginInstancePeer> peer(do_QueryInterface(mPeer));      nsCOMPtr<nsIPluginInstanceOwner> owner;      rv = peer->GetOwner(owner);      if (owner)        owner->SetInstance(nsnull);    }    // now check for cached plugins because they haven't had nsIPluginInstance::Destroy()    // called yet. For non-cached plugins, nsIPluginInstance::Destroy() is called     // in either nsObjectFrame::Destroy() or nsActivePluginList::stopRunning()    PRBool doCache = PR_TRUE;        mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache);    if (doCache)       mInstance->Destroy();    NS_RELEASE(mInstance);    NS_RELEASE(mPeer);  }  PL_strfree(mURL);}////////////////////////////////////////////////////////////////////////void nsActivePlugin::setStopped(PRBool stopped){  mStopped = stopped;  if(mStopped) // plugin instance is told to stop  {    mllStopTime = PR_Now();    // Since we are "stopped", we should clear our our streams array    if (mStreams)      while (mStreams->Count() > 0 )  // simple loop, always removing the first element      {        nsIStreamListener * s = (nsIStreamListener *) mStreams->ElementAt(0);  // XXX nasty cast!        if (s)        {          NS_RELEASE(s);    // should cause stream destructions (and prevent leaks!)          mStreams->RemoveElementAt(0);        }      }  }  else    mllStopTime = LL_ZERO;}////////////////////////////////////////////////////////////////////////nsActivePluginList::nsActivePluginList(){  mFirst = nsnull;  mLast = nsnull;  mCount = 0;}////////////////////////////////////////////////////////////////////////nsActivePluginList::~nsActivePluginList(){  if(mFirst == nsnull)    return;  shut();}////////////////////////////////////////////////////////////////////////void nsActivePluginList::shut(){  if(mFirst == nsnull)    return;  for(nsActivePlugin * plugin = mFirst; plugin != nsnull;)  {    nsActivePlugin * next = plugin->mNext;    remove(plugin);    plugin = next;  }  mFirst = nsnull;  mLast = nsnull;}////////////////////////////////////////////////////////////////////////PRInt32 nsActivePluginList::add(nsActivePlugin * plugin){  if (mFirst == nsnull)  {    mFirst = plugin;    mLast = plugin;    mFirst->mNext = nsnull;  }  else  {    mLast->mNext = plugin;    mLast = plugin;  }  mLast->mNext = nsnull;  mCount++;  return mCount;}////////////////////////////////////////////////////////////////////////PRBool nsActivePluginList::IsLastInstance(nsActivePlugin * plugin){  if(!plugin)    return PR_FALSE;  if(!plugin->mPluginTag)    return PR_FALSE;  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if((p->mPluginTag == plugin->mPluginTag) && (p != plugin))      return PR_FALSE;  }  return PR_TRUE;}////////////////////////////////////////////////////////////////////////PRBool nsActivePluginList::remove(nsActivePlugin * plugin){  if(mFirst == nsnull)    return PR_FALSE;  nsActivePlugin * prev = nsnull;  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if(p == plugin)    {      PRBool lastInstance = IsLastInstance(p);      if(p == mFirst)        mFirst = p->mNext;      else        prev->mNext = p->mNext;      if((prev != nsnull) && (prev->mNext == nsnull))        mLast = prev;      // see if this is going to be the last instance of a plugin      // if so we should perform nsIPlugin::Shutdown and unload the library      // by calling nsPluginTag::TryUnloadPlugin()      if(lastInstance)      {        // cache some things as we are going to destroy it right now        nsPluginTag *pluginTag = p->mPluginTag;                delete p; // plugin instance is destroyed here                if(pluginTag)          pluginTag->TryUnloadPlugin();        else          NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");      }      else        delete p;      mCount--;      return PR_TRUE;    }    prev = p;  }  return PR_FALSE;}////////////////////////////////////////////////////////////////////////// This method terminates all running instances of plugins and collects their// documents to be returned through an array. This method is used// when we are shutting down or when a plugins.refresh(1) happens.void nsActivePluginList::stopRunning(nsISupportsArray* aReloadDocs){  if(mFirst == nsnull)    return;  PRBool doCallSetWindowAfterDestroy = PR_FALSE;  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if(!p->mStopped && p->mInstance)    {      // then determine if the plugin wants Destroy to be called after      // Set Window.  This is for bug 50547.      p->mInstance->GetValue(nsPluginInstanceVariable_CallSetWindowAfterDestroyBool,                              (void *) &doCallSetWindowAfterDestroy);      if (doCallSetWindowAfterDestroy) {        p->mInstance->Stop();        p->mInstance->Destroy();        p->mInstance->SetWindow(nsnull);      }      else {        p->mInstance->SetWindow(nsnull);        p->mInstance->Stop();        p->mInstance->Destroy();      }      doCallSetWindowAfterDestroy = PR_FALSE;      p->setStopped(PR_TRUE);      // If we've been passed an array to return, lets collect all our documents,      // removing duplicates. These will be reframed (embedded) or reloaded (full-page) later       // to kickstart our instances.      if (aReloadDocs && p->mPeer) {        nsCOMPtr<nsPIPluginInstancePeer> peer(do_QueryInterface(p->mPeer));        nsCOMPtr<nsIPluginInstanceOwner> owner;        peer->GetOwner(owner);        if (owner) {          nsCOMPtr<nsIDocument> doc;          owner->GetDocument(getter_AddRefs(doc));          if (doc && aReloadDocs->IndexOf(doc) == -1)  // don't allow for duplicates            aReloadDocs->AppendElement(doc);        }      }    }  }}////////////////////////////////////////////////////////////////////////void nsActivePluginList::removeAllStopped(){  if(mFirst == nsnull)    return;  nsActivePlugin * next = nsnull;  for(nsActivePlugin * p = mFirst; p != nsnull;)  {    next = p->mNext;    if(p->mStopped)      remove(p);    p = next;  }  return;}////////////////////////////////////////////////////////////////////////nsActivePlugin * nsActivePluginList::find(nsIPluginInstance* instance){  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if(p->mInstance == instance)    {#ifdef NS_DEBUG      PRBool doCache = PR_TRUE;      p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache);      NS_ASSERTION(!p->mStopped || doCache, "This plugin is not supposed to be cached!");#endif      return p;    }  }  return nsnull;}nsActivePlugin * nsActivePluginList::find(const char * mimetype){  PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    // give it some special treatment for the default plugin first    // because we cannot tell the default plugin by asking peer for a mime type    if(defaultplugin && p->mDefaultPlugin)      return p;    if(!p->mPeer)      continue;    nsMIMEType mt;    nsresult res = p->mPeer->GetMIMEType(&mt);    if(NS_FAILED(res))      continue;    if(PL_strcasecmp(mt, mimetype) == 0)    {#ifdef NS_DEBUG      PRBool doCache = PR_TRUE;      p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache);      NS_ASSERTION(!p->mStopped || doCache, "This plugin is not supposed to be cached!");#endif       return p;    }  }  return nsnull;}////////////////////////////////////////////////////////////////////////nsActivePlugin * nsActivePluginList::findStopped(const char * url){  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if(!PL_strcmp(url, p->mURL) && p->mStopped)    {#ifdef NS_DEBUG      PRBool doCache = PR_TRUE;      p->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache);      NS_ASSERTION(doCache, "This plugin is not supposed to be cached!");#endif       return p;    }  }  return nsnull;}////////////////////////////////////////////////////////////////////////PRUint32 nsActivePluginList::getStoppedCount(){  PRUint32 stoppedCount = 0;  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if(p->mStopped)      stoppedCount++;  }  return stoppedCount;}////////////////////////////////////////////////////////////////////////nsActivePlugin * nsActivePluginList::findOldestStopped(){  nsActivePlugin * res = nsnull;  PRInt64 llTime = LL_MAXINT;  for(nsActivePlugin * p = mFirst; p != nsnull; p = p->mNext)  {    if(!p->mStopped)      continue;    if(LL_CMP(p->mllStopTime, <, llTime))    {      llTime = p->mllStopTime;      res = p;    }  }#ifdef NS_DEBUG  if(res)  {    PRBool doCache = PR_TRUE;    res->mInstance->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *) &doCache);    NS_ASSERTION(doCache, "This plugin is not supposed to be cached!");  }#endif  return res;}////////////////////////////////////////////////////////////////////////nsPluginTag::nsPluginTag(){  mPluginHost = nsnull;  mNext = nsnull;  mName = nsnull;  mDescription = nsnull;  mVariants = 0;  mMimeTypeArray = nsnull;  mMimeDescriptionArray = nsnull;  mExtensionsArray = nsnull;  mLibrary = nsnull;  mCanUnloadLibrary = PR_TRUE;  mEntryPoint = nsnull;  mFlags = NS_PLUGIN_FLAG_ENABLED;  mXPConnected = PR_FALSE;  mFileName = nsnull;  mFullPath = nsnull;}////////////////////////////////////////////////////////////////////////inline char* new_str(const char* str){  if(str == nsnull)    return nsnull;  char* result = new char[strlen(str) + 1];  if (result != nsnull)    return strcpy(result, str);  return result;}////////////////////////////////////////////////////////////////////////nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag){  mPluginHost = nsnull;  mNext = nsnull;  mName = new_str(aPluginTag->mName);  mDescription = new_str(aPluginTag->mDescription);  mVariants = aPluginTag->mVariants;  mMimeTypeArray = nsnull;  mMimeDescriptionArray = nsnull;  mExtensionsArray = nsnull;  if(aPluginTag->mMimeTypeArray != nsnull)  {    mMimeTypeArray = new char*[mVariants];    for (int i = 0; i < mVariants; i++)      mMimeTypeArray[i] = new_str(aPluginTag->mMimeTypeArray[i]);  }  if(aPluginTag->mMimeDescriptionArray != nsnull)   {    mMimeDescriptionArray = new char*[mVariants];    for (int i = 0; i < mVariants; i++)      mMimeDescriptionArray[i] = new_str(aPluginTag->mMimeDescriptionArray[i]);  }  if(aPluginTag->mExtensionsArray != nsnull)   {    mExtensionsArray = new char*[mVariants];    for (int i = 0; i < mVariants; i++)      mExtensionsArray[i] = new_str(aPluginTag->mExtensionsArray[i]);  }  mLibrary = nsnull;  mCanUnloadLibrary = PR_TRUE;  mEntryPoint = nsnull;  mFlags = NS_PLUGIN_FLAG_ENABLED;  mXPConnected = PR_FALSE;  mFileName = new_str(aPluginTag->mFileName);  mFullPath = new_str(aPluginTag->mFullPath);}////////////////////////////////////////////////////////////////////////nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo){  mPluginHost = nsnull;  mNext = nsnull;  mName = new_str(aPluginInfo->fName);  mDescription = new_str(aPluginInfo->fDescription);  mVariants = aPluginInfo->fVariantCount;  mMimeTypeArray = nsnull;  mMimeDescriptionArray = nsnull;  mExtensionsArray = nsnull;  if(aPluginInfo->fMimeTypeArray != nsnull)  {    mMimeTypeArray = new char*[mVariants];    for (int i = 0; i < mVariants; i++)      mMimeTypeArray[i] = new_str(aPluginInfo->fMimeTypeArray[i]);  }  if(aPluginInfo->fMimeDescriptionArray != nsnull)   {    mMimeDescriptionArray = new char*[mVariants];    for (int i = 0; i < mVariants; i++) {      // we should cut off the list of suffixes which the mime       // description string may have, see bug 53895      // it is usually in form "some description (*.sf1, *.sf2)"       // so we can search for the opening round bracket      char cur = '\0';      char pre = '\0';      char * p = PL_strrchr(aPluginInfo->fMimeDescriptionArray[i], '(');      if (p && (p != aPluginInfo->fMimeDescriptionArray[i])) {        if ((p - 1) && *(p - 1) == ' ') {          pre = *(p - 1);          *(p - 1) = '\0';        } else {          cur = *p;          *p = '\0';        }                }      mMimeDescriptionArray[i] = new_str(aPluginInfo->fMimeDescriptionArray[i]);      // restore the original string      if (cur != '\0')        *p = cur;      if (pre != '\0')        *(p - 1) = pre;    }  }  if(aPluginInfo->fExtensionArray != nsnull)   {    mExtensionsArray = new char*[mVariants];    for (int i = 0; i < mVariants; i++)      mExtensionsArray[i] = new_str(aPluginInfo->fExtensionArray[i]);  }  mFileName = new_str(aPluginInfo->fFileName);  mFullPath = new_str(aPluginInfo->fFullPath);  mLibrary = nsnull;  mCanUnloadLibrary = PR_TRUE;  mEntryPoint = nsnull;#if TARGET_CARBON  mCanUnloadLibrary = !aPluginInfo->fBundle;#endif  mFlags = NS_PLUGIN_FLAG_ENABLED;  mXPConnected = PR_FALSE;}////////////////////////////////////////////////////////////////////////nsPluginTag::nsPluginTag(const char* aName,                         const char* aDescription,                         const char* aFileName,                         const char* aFullPath,                         const char* const* aMimeTypes,                         const char* const* aMimeDescriptions,                         const char* const* aExtensions,                         PRInt32 aVariants,                         PRInt64 aLastModifiedTime,                         PRBool aCanUnload)  : mNext(nsnull),    mVariants(aVariants),    mMimeTypeArray(nsnull),    mMimeDescriptionArray(nsnull),    mExtensionsArray(nsnull),    mLibrary(nsnull),    mCanUnloadLibrary(aCanUnload),    mEntryPoint(nsnull),    mFlags(0),    mXPConnected(PR_FALSE),    mLastModifiedTime(aLastModifiedTime){  mPluginHost = nsnull;  mName            = new_str(aName);  mDescription     = new_str(aDescription);  mFileName        = new_str(aFileName);  mFullPath        = new_str(aFullPath);  if (mVariants) {    mMimeTypeArray        = new char*[mVariants];    mMimeDescriptionArray = new char*[mVariants];    mExtensionsArray      = new char*[mVariants];    for (PRInt32 i = 0; i < aVariants; ++i) {      mMimeTypeArray[i]        = new_str(aMimeTypes[i]);      mMimeDescriptionArray[i] = new_str(aMimeDescriptions[i]);      mExtensionsArray[i]      = new_str(aExtensions[i]);    }  }}nsPluginTag::~nsPluginTag(){  TryUnloadPlugin(PR_TRUE);  if (nsnull != mName) {    delete[] (mName);    mName = nsnull;  }  if (nsnull != mDescription) {    delete[] (mDescription);    mDescription = nsnull;  }  if (nsnull != mMimeTypeArray) {    for (int i = 0; i < mVariants; i++)      delete[] mMimeTypeArray[i];    delete[] (mMimeTypeArray);    mMimeTypeArray = nsnull;  }  if (nsnull != mMimeDescriptionArray) {    for (int i = 0; i < mVariants; i++)      delete[] mMimeDescriptionArray[i];    delete[] (mMimeDescriptionArray);    mMimeDescriptionArray = nsnull;  }  if (nsnull != mExtensionsArray) {    for (int i = 0; i < mVariants; i++)      delete[] mExtensionsArray[i];    delete[] (mExtensionsArray);    mExtensionsArray = nsnull;  }  if(nsnull != mFileName)  {    delete [] mFileName;    mFileName = nsnull;  }  if(nsnull != mFullPath)  {    delete [] mFullPath;    mFullPath = nsnull;  }}void nsPluginTag::SetHost(nsPluginHostImpl * aHost){  mPluginHost = aHost;}//----------------------------------------------------------------------// helper struct for asynchronous handeling of plugin unloadingstruct nsPluginUnloadEvent: public PLEvent {  nsPluginUnloadEvent (PRLibrary* aLibrary);   void HandleEvent() {    if (mLibrary)      NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(mLibrary), nsnull, nsnull);  // put our unload call in a saftey wrapper    else       NS_WARNING("missing library from nsPluginUnloadEvent");  }  PRLibrary* mLibrary;};nsPluginUnloadEvent::nsPluginUnloadEvent (PRLibrary* aLibrary){  mLibrary = aLibrary;}//----------------------------------------------------------------------// helper static callback functions for plugin unloading PLEventsstatic void PR_CALLBACK HandlePluginUnloadPLEvent(nsPluginUnloadEvent* aEvent){  aEvent->HandleEvent();}static void PR_CALLBACK DestroyPluginUnloadPLEvent(nsPluginUnloadEvent* aEvent){  delete aEvent;}// unload plugin asynchronously if possible, otherwise just unload nownsresult PostPluginUnloadEvent (PRLibrary* aLibrary){  nsCOMPtr<nsIEventQueueService> eventService(do_GetService(kEventQueueServiceCID));  if (eventService) {    nsCOMPtr<nsIEventQueue> eventQueue;      eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue));    if (eventQueue) {      nsPluginUnloadEvent * ev = new nsPluginUnloadEvent(aLibrary);      if (ev) {        PL_InitEvent(ev, nsnull, (PLHandleEventProc) ::HandlePluginUnloadPLEvent, (PLDestroyEventProc) ::DestroyPluginUnloadPLEvent);        if (NS_SUCCEEDED(eventQueue->PostEvent(ev)))          return NS_OK;                else NS_WARNING("failed to post event onto queue");      } else NS_WARNING("not able to create plugin unload event");    } else NS_WARNING("couldn't get event queue");  } else NS_WARNING("couldn't get event queue service");  // failure case  NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(aLibrary), nsnull, nsnull);  return NS_ERROR_FAILURE;}