Part 1 of bug 347743. Patch by Johnny Stenback, r=brendan, sr=jonas, a=blocking1.9+
authorsharparrow1@yahoo.com
Mon, 06 Aug 2007 09:36:03 -0700
changeset 4310 85c3a5d0867f356c32f8ee6642532ce254bcffb6
parent 4309 b52f7cd3d855e8008f36652b8ec8167316203a33
child 4311 15bbd07dd3d6dc9b976c4b286a839766ff7c6701
push idunknown
push userunknown
push dateunknown
reviewersbrendan, jonas, blocking1.9
bugs347743
milestone1.9a8pre
Part 1 of bug 347743. Patch by Johnny Stenback, r=brendan, sr=jonas, a=blocking1.9+
modules/plugin/base/src/nsJSNPRuntime.cpp
--- a/modules/plugin/base/src/nsJSNPRuntime.cpp
+++ b/modules/plugin/base/src/nsJSNPRuntime.cpp
@@ -1560,71 +1560,92 @@ JSObjWrapperPluginDestroyedCallback(PLDH
     table->ops = ops;
 
     return PL_DHASH_REMOVE;
   }
 
   return PL_DHASH_NEXT;
 }
 
+// Struct for passing an NPP and a JSContext to
+// NPObjWrapperPluginDestroyedCallback
+struct NppAndCx
+{
+  NPP npp;
+  JSContext *cx;
+};
+
 PR_STATIC_CALLBACK(PLDHashOperator)
 NPObjWrapperPluginDestroyedCallback(PLDHashTable *table, PLDHashEntryHdr *hdr,
                                     PRUint32 number, void *arg)
 {
   NPObjWrapperHashEntry *entry = (NPObjWrapperHashEntry *)hdr;
+  NppAndCx *nppcx = reinterpret_cast<NppAndCx *>(arg);
 
-  if (entry->mNpp == arg) {
+  if (entry->mNpp == nppcx->npp) {
     NPObject *npobj = entry->mNPObj;
 
     if (npobj->_class && npobj->_class->invalidate) {
       npobj->_class->invalidate(npobj);
     }
 
     // Force deallocation of plugin objects since the plugin they came
     // from is being torn down.
     if (npobj->_class && npobj->_class->deallocate) {
       npobj->_class->deallocate(npobj);
     } else {
       PR_Free(npobj);
     }
 
-    JSContext *cx = GetJSContext((NPP)arg);
-
-    if (cx) {
-      ::JS_SetPrivate(cx, entry->mJSObj, nsnull);
-    } else {
-      NS_ERROR("dangling entry->mJSObj JSPrivate because we can't find cx");
-    }
+    ::JS_SetPrivate(nppcx->cx, entry->mJSObj, nsnull);
 
     return PL_DHASH_REMOVE;
   }
 
   return PL_DHASH_NEXT;
 }
 
 // static
 void
 nsJSNPRuntime::OnPluginDestroy(NPP npp)
 {
   if (sJSObjWrappers.ops) {
     PL_DHashTableEnumerate(&sJSObjWrappers,
                            JSObjWrapperPluginDestroyedCallback, npp);
   }
 
+  // Use the safe JSContext here as we're not always able to find the
+  // JSContext associated with the NPP any more.
+
+  nsCOMPtr<nsIThreadJSContextStack> stack =
+    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
+  if (!stack) {
+    NS_ERROR("No context stack available!");
+
+    return;
+  }
+
+  stack->GetSafeJSContext(&cx);
+  if (!cx) {
+    NS_ERROR("No safe JS context available!");
+
+    return;
+  }
+
   if (sNPObjWrappers.ops) {
+    NppAndCx nppcx = { npp, cx };
     PL_DHashTableEnumerate(&sNPObjWrappers,
-                           NPObjWrapperPluginDestroyedCallback, npp);
+                           NPObjWrapperPluginDestroyedCallback, &nppcx);
   }
 
   // If this plugin was scripted from a webpage, the plugin's
   // scriptable object will be on the DOM element's prototype
   // chain. Now that the plugin is being destroyed we need to pull the
   // plugin's scriptable object out of that prototype chain.
-  JSContext *cx = GetJSContext(npp);
-  if (!cx || !npp) {
+  if (!npp) {
     return;
   }
 
   // Find the plugin instance so that we can (eventually) get to the
   // DOM element
   ns4xPluginInstance *inst = (ns4xPluginInstance *)npp->ndata;
   if (!inst) {
     return;