diff --git a/dom/plugins/PPluginIdentifier.ipdl b/dom/plugins/PPluginIdentifier.ipdl
--- a/dom/plugins/PPluginIdentifier.ipdl
+++ b/dom/plugins/PPluginIdentifier.ipdl
@@ -36,16 +36,19 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol "PPluginModule.ipdl";
 
 namespace mozilla {
 namespace plugins {
 
+/**
+ * Represents an NPIdentifier that wraps either a string or an integer.
+ */
 async protocol PPluginIdentifier
 {
   manager PPluginModule;
 
 child:
   async __delete__();
 };
 
diff --git a/dom/plugins/PPluginModule.ipdl b/dom/plugins/PPluginModule.ipdl
--- a/dom/plugins/PPluginModule.ipdl
+++ b/dom/plugins/PPluginModule.ipdl
@@ -50,18 +50,24 @@ namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginModule
 {
   manages PPluginInstance;
   manages PPluginIdentifier;
 
 both:
-  // Sending a void string to this constructor creates an int identifier
-  // whereas sending a non-void string will create a string identifier.
+  /**
+   * Sending a void string to this constructor creates an int identifier whereas
+   * sending a non-void string will create a string identifier. This constructor
+   * may be called by either child or parent. If a race occurs by calling the
+   * constructor with the same string or int argument then we create two actors
+   * and detect the second instance in the child. We prevent the parent's actor
+   * from leaking out to plugin code and only allow the child's to be used.
+   */
   async PPluginIdentifier(nsCString aString,
                           int32_t aInt);
 
 child:
   rpc NP_Initialize()
     returns (NPError rv);
 
   rpc PPluginInstance(nsCString aMimeType,
diff --git a/dom/plugins/PluginIdentifierChild.h b/dom/plugins/PluginIdentifierChild.h
--- a/dom/plugins/PluginIdentifierChild.h
+++ b/dom/plugins/PluginIdentifierChild.h
@@ -46,70 +46,87 @@
 #include "nsStringGlue.h"
 
 namespace mozilla {
 namespace plugins {
 
 class PluginIdentifierChild : public PPluginIdentifierChild
 {
   friend class PluginModuleChild;
-
 public:
   bool IsString()
   {
-    return !mString.IsVoid();
-  }
-
-  NPUTF8* ToString()
-  {
-    NS_ASSERTION(IsString(), "Not a string!");
-    return ToNewCString(mString);
-  }
-
-  int32_t ToInt()
-  {
-    NS_ASSERTION(!IsString(), "Not an int!");
-    return mInt;
+    return mType == TYPE_STRING;
   }
 
   NPIdentifier ToNPIdentifier()
   {
-    return mCanonicalIdentifier ? mCanonicalIdentifier : this;
+    return mCanonicalIdentifier;
   }
 
 protected:
-  PluginIdentifierChild(const nsCString& aString)
-    : mString(aString),
-      mInt(-1),
-      mCanonicalIdentifier(nsnull)
+  enum Type
+  {
+    TYPE_STRING,
+    TYPE_INT
+  };
+
+  PluginIdentifierChild(Type aType)
+    : mType(aType),
+      ALLOW_THIS_IN_INITIALIZER_LIST(mCanonicalIdentifier(this))
   {
     MOZ_COUNT_CTOR(PluginIdentifierChild);
-    NS_ASSERTION(!mString.IsVoid(), "Void string!");
   }
-
-  PluginIdentifierChild(int32_t aInt)
-    : mInt(aInt),
-      mCanonicalIdentifier(nsnull)
-  {
-    MOZ_COUNT_CTOR(PluginIdentifierChild);
-    mString.SetIsVoid(PR_TRUE);
-  }
-
   virtual ~PluginIdentifierChild()
   {
     MOZ_COUNT_DTOR(PluginIdentifierChild);
   }
 
-  void SetCanonicalIdentifier(PluginIdentifierChild* aCanonicalIdentifier)
+  void SetCanonicalIdentifier(PluginIdentifierChild* aIdentifier)
   {
-    mCanonicalIdentifier = aCanonicalIdentifier;
+    NS_ASSERTION(mCanonicalIdentifier == this, "Already got one!");
+    mCanonicalIdentifier = aIdentifier;
   }
 
-private:
+  Type mType;
+  PluginIdentifierChild* mCanonicalIdentifier;
+};
+
+class PluginIdentifierChildString : public PluginIdentifierChild
+{
+  friend class PluginModuleChild;
+public:
+  NPUTF8* ToString()
+  {
+    return ToNewCString(mString);
+  }
+
+protected:
+  PluginIdentifierChildString(const nsCString& aString)
+    : PluginIdentifierChild(TYPE_STRING),
+      mString(aString)
+  { }
+
   nsCString mString;
+};
+
+class PluginIdentifierChildInt : public PluginIdentifierChild
+{
+  friend class PluginModuleChild;
+public:
+  int32_t ToInt()
+  {
+    return mInt;
+  }
+
+protected:
+  PluginIdentifierChildInt(int32_t aInt)
+    : PluginIdentifierChild(TYPE_INT),
+      mInt(aInt)
+  { }
+
   int32_t mInt;
-  PluginIdentifierChild* mCanonicalIdentifier;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif // dom_plugins_PluginIdentifierChild_h
diff --git a/dom/plugins/PluginModuleChild.cpp b/dom/plugins/PluginModuleChild.cpp
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -1394,23 +1394,23 @@ PluginModuleChild::AllocPPluginIdentifie
     // There's a possibility that we already have an actor that wraps the same
     // string or int because we do all this identifier construction
     // asynchronously. Check to see if we've already wrapped here, and then set
     // canonical actor of the new one to the actor already in our hash.
     PluginIdentifierChild* newActor;
     PluginIdentifierChild* existingActor;
 
     if (aString.IsVoid()) {
-        newActor = new PluginIdentifierChild(aInt);
+        newActor = new PluginIdentifierChildInt(aInt);
         if (mIntIdentifiers.Get(aInt, &existingActor)) {
             newActor->SetCanonicalIdentifier(existingActor);
         }
     }
     else {
-        newActor = new PluginIdentifierChild(aString);
+        newActor = new PluginIdentifierChildString(aString);
         if (mStringIdentifiers.Get(aString, &existingActor)) {
             newActor->SetCanonicalIdentifier(existingActor);
         }
     }
     return newActor;
 }
 
 bool
@@ -1620,17 +1620,17 @@ PluginModuleChild::NPN_GetStringIdentifi
 
     PluginModuleChild* self = PluginModuleChild::current();
     nsDependentCString name(aName);
 
     PluginIdentifierChild* ident;
     if (!self->mStringIdentifiers.Get(name, &ident)) {
         nsCString nameCopy(name);
 
-        ident = new PluginIdentifierChild(nameCopy);
+        ident = new PluginIdentifierChildString(nameCopy);
         self->SendPPluginIdentifierConstructor(ident, nameCopy, -1);
         self->mStringIdentifiers.Put(nameCopy, ident);
     }
 
     return ident;
 }
 
 void NP_CALLBACK
@@ -1652,17 +1652,17 @@ PluginModuleChild::NPN_GetStringIdentifi
             aIdentifiers[index] = 0;
             continue;
         }
         nsDependentCString name(aNames[index]);
         PluginIdentifierChild* ident;
         if (!self->mStringIdentifiers.Get(name, &ident)) {
             nsCString nameCopy(name);
 
-            ident = new PluginIdentifierChild(nameCopy);
+            ident = new PluginIdentifierChildString(nameCopy);
             self->SendPPluginIdentifierConstructor(ident, nameCopy, -1);
             self->mStringIdentifiers.Put(nameCopy, ident);
         }
         aIdentifiers[index] = ident;
     }
 }
 
 bool NP_CALLBACK
@@ -1684,36 +1684,41 @@ PluginModuleChild::NPN_GetIntIdentifier(
 
     PluginModuleChild* self = PluginModuleChild::current();
 
     PluginIdentifierChild* ident;
     if (!self->mIntIdentifiers.Get(aIntId, &ident)) {
         nsCString voidString;
         voidString.SetIsVoid(PR_TRUE);
 
-        ident = new PluginIdentifierChild(aIntId);
+        ident = new PluginIdentifierChildInt(aIntId);
         self->SendPPluginIdentifierConstructor(ident, voidString, aIntId);
         self->mIntIdentifiers.Put(aIntId, ident);
     }
     return ident;
 }
 
 NPUTF8* NP_CALLBACK
 PluginModuleChild::NPN_UTF8FromIdentifier(NPIdentifier aIdentifier)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
 
-    PluginIdentifierChild* ident =
-        static_cast<PluginIdentifierChild*>(aIdentifier);
-    return ident->ToString();
+    if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
+      return static_cast<PluginIdentifierChildString*>(aIdentifier)->ToString();
+    }
+    return nsnull;
 }
 
 int32_t NP_CALLBACK
 PluginModuleChild::NPN_IntFromIdentifier(NPIdentifier aIdentifier)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
 
     PluginIdentifierChild* ident =
         static_cast<PluginIdentifierChild*>(aIdentifier);
-    return ident->ToInt();
+
+    if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
+      return static_cast<PluginIdentifierChildInt*>(aIdentifier)->ToInt();
+    }
+    return PR_INT32_MIN;
 }
