From: Steven Michaud <smichaud@pobox.com>
Date: Mon, 29 Nov 2010 13:47:03 -0600
Subject: Bug 611910 - r=josh a=blocking1.9.1.17+

---
 modules/plugin/base/src/nsNPAPIPlugin.cpp       |   84 ++++++++++++++++++++++-
 modules/plugin/base/src/nsNPAPIPluginInstance.h |    5 +-
 2 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/modules/plugin/base/src/nsNPAPIPlugin.cpp b/modules/plugin/base/src/nsNPAPIPlugin.cpp
index 0a91443..8d8e8a1 100644
--- a/modules/plugin/base/src/nsNPAPIPlugin.cpp
+++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp
@@ -89,6 +89,8 @@
 #include "nsIHttpAuthManager.h"
 #include "nsICookieService.h"
 
+#include "nsNetUtil.h"
+
 static PRLock *sPluginThreadAsyncCallLock = nsnull;
 static PRCList sPendingAsyncCalls = PR_INIT_STATIC_CLIST(&sPendingAsyncCalls);
 
@@ -1711,7 +1713,87 @@ _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
                  ("NPN_GetProperty(npp %p, npobj %p, property %p) called\n",
                   npp, npobj, property));
 
-  return npobj->_class->getProperty(npobj, property, result);
+  if (!npobj->_class->getProperty(npobj, property, result))
+    return false;
+
+  // If a Java plugin tries to get the document.URL or document.documentURI
+  // property from us, don't pass back a value that Java won't be able to
+  // understand -- one that will make the URL(String) constructor throw a
+  // MalformedURL exception.  Passing such a value causes Java Plugin2 to
+  // crash (to throw a RuntimeException in Plugin2Manager.getDocumentBase()).
+  // Also don't pass back a value that Java is likely to mishandle.
+
+  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*) npp->ndata;
+  if (!inst)
+    return false;
+  if (!inst->mIsJavaPlugin)
+    return true;
+
+  if (!NPVARIANT_IS_STRING(*result))
+    return true;
+
+  NPUTF8* propertyName = _utf8fromidentifier(property);
+  if (!propertyName)
+    return true;
+  bool notURL =
+    (PL_strcasecmp(propertyName, "URL") &&
+     PL_strcasecmp(propertyName, "documentURI"));
+  _memfree(propertyName);
+  if (notURL)
+    return true;
+
+  NPObject* window_obj = _getwindowobject(npp);
+  if (!window_obj)
+    return true;
+
+  NPVariant doc_v;
+  NPObject* document_obj = nsnull;
+  NPIdentifier doc_id = _getstringidentifier("document");
+  bool ok = npobj->_class->getProperty(window_obj, doc_id, &doc_v);
+  _releaseobject(window_obj);
+  if (ok) {
+    if (NPVARIANT_IS_OBJECT(doc_v)) {
+      document_obj = NPVARIANT_TO_OBJECT(doc_v);
+    } else {
+      _releasevariantvalue(&doc_v);
+      return true;
+    }
+  } else {
+    return true;
+  }
+  _releaseobject(document_obj);
+  if (document_obj != npobj)
+    return true;
+
+  NPString urlnp = NPVARIANT_TO_STRING(*result);
+  nsXPIDLCString url;
+  url.Assign(urlnp.utf8characters, urlnp.utf8length);
+
+  PRBool javaCompatible = PR_FALSE;
+  if (NS_FAILED(NS_CheckIsJavaCompatibleURLString(url, &javaCompatible)))
+    javaCompatible = PR_FALSE;
+  if (javaCompatible)
+    return true;
+
+  // If Java won't be able to interpret the original value of document.URL or
+  // document.documentURI, or is likely to mishandle it, pass back something
+  // that Java will understand but won't be able to use to access the network,
+  // and for which same-origin checks will always fail.
+
+  if (inst->mFakeURL.IsVoid()) {
+    // Abort (do an error return) if NS_MakeRandomInvalidURLString() fails.
+    if (NS_FAILED(NS_MakeRandomInvalidURLString(inst->mFakeURL))) {
+      _releasevariantvalue(result);
+      return false;
+    }
+  }
+
+  _releasevariantvalue(result);
+  char* fakeurl = (char *) _memalloc(inst->mFakeURL.Length() + 1);
+  strcpy(fakeurl, inst->mFakeURL);
+  STRINGZ_TO_NPVARIANT(fakeurl, *result);
+
+  return true;
 }
 
 bool NP_CALLBACK
diff --git a/modules/plugin/base/src/nsNPAPIPluginInstance.h b/modules/plugin/base/src/nsNPAPIPluginInstance.h
index 45f7325..e738832 100644
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.h
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.h
@@ -161,16 +161,19 @@ protected:
     PRPackedBool  mTransparent;
     PRPackedBool  mStarted;
     PRPackedBool  mCached;
-    PRPackedBool  mIsJavaPlugin;
     PRPackedBool  mWantsAllNetworkStreams;
 
 public:
+    PRPackedBool  mIsJavaPlugin;
+
     // True while creating the plugin, or calling NPP_SetWindow() on it.
     PRPackedBool  mInPluginInitCall;
     PRLibrary* fLibrary;
     nsInstanceStream *mStreams;
 
     nsVoidArray mPopupStates;
+
+    nsXPIDLCString mFakeURL;
 };
 
 #endif // nsNPAPIPluginInstance_h_
