Bug 622199: Add support for NPNVdocumentOrigin, ability to pass document origin directly to NPAPI plugins. r=bz
authorJosh Aas <joshmoz@gmail.com>
Wed, 14 Sep 2011 12:22:27 -0400
changeset 76943 262cfa5c56ae88948a48bf0e0b2a1095b64d94f4
parent 76942 096051f47636e2c1bf58192c8134a6825376db6e
child 76944 145d437bebcfea6bfce41b078c13b1992334b3f7
child 76955 aebbccb359855db785f1404212058c62ea1995a8
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbz
bugs622199
milestone9.0a1
Bug 622199: Add support for NPNVdocumentOrigin, ability to pass document origin directly to NPAPI plugins. r=bz
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/ipc/PPluginInstance.ipdl
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginMessageUtils.h
dom/plugins/test/mochitest/Makefile.in
dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html
dom/plugins/test/testplugin/README
dom/plugins/test/testplugin/nptest.cpp
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -65,21 +65,24 @@
 #include "nsPluginLogging.h"
 
 #include "nsIJSContextStack.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocument.h"
+#include "nsIContent.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
+#include "nsIUnicodeNormalizer.h"
 #include "nsDOMJSUtils.h"
 #include "nsIPrincipal.h"
 #include "nsWildCard.h"
+#include "nsContentUtils.h"
 
 #include "nsIXPConnect.h"
 
 #include "nsIObserverService.h"
 #include <prinrval.h>
 
 #ifdef MOZ_WIDGET_COCOA
 #include <Carbon/Carbon.h>
@@ -2154,16 +2157,56 @@ NPError NP_CALLBACK
       PRBool enabled;
       pbs->GetPrivateBrowsingEnabled(&enabled);
       *(NPBool*)result = (NPBool)enabled;
       return NPERR_NO_ERROR;
     }
     return NPERR_GENERIC_ERROR;
   }
 
+  case NPNVdocumentOrigin: {
+    nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
+    if (!inst) {
+      return NPERR_GENERIC_ERROR;
+    }
+
+    nsCOMPtr<nsIDOMElement> element;
+    inst->GetDOMElement(getter_AddRefs(element));
+    if (!element) {
+      return NPERR_GENERIC_ERROR;
+    }
+
+    nsCOMPtr<nsIContent> content(do_QueryInterface(element));
+    if (!content) {
+      return NPERR_GENERIC_ERROR;
+    }
+
+    nsIPrincipal* principal = content->NodePrincipal();
+
+    nsAutoString utf16Origin;
+    res = nsContentUtils::GetUTFOrigin(principal, utf16Origin);
+    if (NS_FAILED(res)) {
+      return NPERR_GENERIC_ERROR;
+    }
+
+    nsCOMPtr<nsIUnicodeNormalizer> normalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
+    if (!normalizer) {
+      return NPERR_GENERIC_ERROR;
+    }
+
+    nsAutoString normalizedUTF16Origin;
+    res = normalizer->NormalizeUnicodeNFKC(utf16Origin, normalizedUTF16Origin);
+    if (NS_FAILED(res)) {
+      return NPERR_GENERIC_ERROR;
+    }
+
+    *(char**)result = ToNewUTF8String(normalizedUTF16Origin);
+    return *(char**)result ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
+  }
+
 #ifdef XP_MACOSX
   case NPNVpluginDrawingModel: {
     if (npp) {
       nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance*)npp->ndata;
       if (inst) {
         NPDrawingModel drawingModel;
         inst->GetDrawingModel((PRInt32*)&drawingModel);
         *(NPDrawingModel*)result = drawingModel;
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -166,16 +166,18 @@ parent:
   rpc NPN_GetValue_NPNVWindowNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
   rpc NPN_GetValue_NPNVPluginElementNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
   rpc NPN_GetValue_NPNVprivateModeBool()
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVnetscapeWindow()
     returns (NativeWindowHandle value, NPError result);
+  rpc NPN_GetValue_NPNVdocumentOrigin()
+    returns (nsCString value, NPError result);
 
   rpc NPN_SetValue_NPPVpluginWindow(bool windowed)
     returns (NPError result);
   rpc NPN_SetValue_NPPVpluginTransparent(bool transparent)
     returns (NPError result);
   rpc NPN_SetValue_NPPVpluginUsesDOMForCursor(bool useDOMForCursor)
     returns (NPError result);
   rpc NPN_SetValue_NPPVpluginDrawingModel(int drawingModel)
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -354,16 +354,28 @@ PluginInstanceChild::NPN_GetValue(NPNVar
         NPError result;
         if (!CallNPN_GetValue_NPNVprivateModeBool(&v, &result)) {
             return NPERR_GENERIC_ERROR;
         }
         *static_cast<NPBool*>(aValue) = v;
         return result;
     }
 
+    case NPNVdocumentOrigin: {
+        nsCString v;
+        NPError result;
+        if (!CallNPN_GetValue_NPNVdocumentOrigin(&v, &result)) {
+            return NPERR_GENERIC_ERROR;
+        }
+        if (result == NPERR_NO_ERROR) {
+            *static_cast<char**>(aValue) = ToNewCString(v);
+        }
+        return result;
+    }
+
     case NPNVWindowNPObject: // Intentional fall-through
     case NPNVPluginElementNPObject: {
         NPObject* object;
         NPError result = InternalGetNPObjectForValue(aVar, &object);
         if (result == NPERR_NO_ERROR) {
             *((NPObject**)aValue) = object;
         }
         return result;
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -337,16 +337,28 @@ PluginInstanceParent::AnswerNPN_GetValue
 {
     NPBool v;
     *result = mNPNIface->getvalue(mNPP, NPNVprivateModeBool, &v);
     *value = v;
     return true;
 }
 
 bool
+PluginInstanceParent::AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value,
+                                                            NPError* result)
+{
+    void *v = nsnull;
+    *result = mNPNIface->getvalue(mNPP, NPNVdocumentOrigin, &v);
+    if (*result == NPERR_NO_ERROR && v) {
+        value->Adopt(static_cast<char*>(v));
+    }
+    return true;
+}
+
+bool
 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
     const bool& windowed, NPError* result)
 {
     NPBool isWindowed = windowed;
     *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool,
                                   (void*)isWindowed);
     return true;
 }
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -125,16 +125,19 @@ public:
                                        PPluginScriptableObjectParent** value,
                                        NPError* result);
     virtual bool
     AnswerNPN_GetValue_NPNVPluginElementNPObject(
                                        PPluginScriptableObjectParent** value,
                                        NPError* result);
     virtual bool
     AnswerNPN_GetValue_NPNVprivateModeBool(bool* value, NPError* result);
+  
+    virtual bool
+    AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value, NPError* result);
 
     virtual bool
     AnswerNPN_SetValue_NPPVpluginWindow(const bool& windowed, NPError* result);
     virtual bool
     AnswerNPN_SetValue_NPPVpluginTransparent(const bool& transparent,
                                              NPError* result);
     virtual bool
     AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor(const bool& useDOMForCursor,
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -208,16 +208,17 @@ NPNVariableToString(NPNVariable aVar)
 
         VARSTR(NPNVWindowNPObject);
 
         VARSTR(NPNVPluginElementNPObject);
 
         VARSTR(NPNVSupportsWindowless);
 
         VARSTR(NPNVprivateModeBool);
+        VARSTR(NPNVdocumentOrigin);
 
     default: return "???";
     }
 }
 #undef VARSTR
 
 inline bool IsPluginThread()
 {
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -97,16 +97,17 @@ include $(topsrcdir)/config/rules.mk
   test_bug539565-2.html \
   test_enumerate.html \
   test_npruntime_construct.html \
   307-xo-redirect.sjs \
   test_redirect_handling.html \
   test_zero_opacity.html \
   test_NPPVpluginWantsAllNetworkStreams.html \
   test_npruntime_npnsetexception.html \
+  test_NPNVdocumentOrigin.html \
   $(NULL)
 
 #  test_plugin_scroll_painting.html \ bug 596491
 
 ifeq ($(OS_ARCH),WINNT)
 _MOCHITEST_FILES += \
   test_windowed_invalidate.html \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_NPNVdocumentOrigin.html
@@ -0,0 +1,34 @@
+<html>
+<head>
+  <title>Test NPNVdocumentOrigin</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body onload="runTest()">
+  <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+
+  <script class="testbody" type="application/javascript">
+    SimpleTest.waitForExplicitFinish();
+
+    function runTest() {
+      var p1 = document.getElementById("plugin1");
+      var realOrigin = "http://mochi.test:8888";
+
+      // Test with no modifications
+      is(p1.getNPNVdocumentOrigin(), realOrigin, "Checking for expected origin.");
+
+      // Mess with window.location.toString
+      window.location.toString = function() { return 'http://victim.rckc.at/'; }
+      is(p1.getNPNVdocumentOrigin(), realOrigin, "Checking for expected origin afer modifying window.location.toString.");
+
+      // Create a plugin in a new window with about:blank
+      var newWindow = window.open("about:blank");
+      newWindow.document.writeln('<embed id="plugin2" type="application/x-test" width="200" height="200"></embed>');
+      var p2 = newWindow.document.getElementById("plugin2");
+      is(p2.getNPNVdocumentOrigin(), realOrigin, "Checking for expected origin of plugin in new about:blank window.");
+      newWindow.close();
+
+      SimpleTest.finish();
+    }
+  </script>
+</body>
+</html>
--- a/dom/plugins/test/testplugin/README
+++ b/dom/plugins/test/testplugin/README
@@ -32,16 +32,20 @@ Attempts to set the value of an undefine
 returns true if it succeeds and false if it doesn't. It should never succeed.
 
 * .getReflector()
 Hands back an object which reflects properties as values, e.g.
   .getReflector().foo = 'foo'
   .getReflector()['foo'] = 'foo'
   .getReflector()[1] = 1
 
+* .getNPNVdocumentOrigin()
+Returns the origin string retrieved from the browser by a NPNVdocumentOrigin
+variable request. Does not cache the value, gets it from the browser every time.
+
 == NPN_ConvertPoint testing ==
 
 * convertPointX(sourceSpace, sourceX, sourceY, destSpace)
 * convertPointY(sourceSpace, sourceX, sourceY, destSpace)
 The plugin uses NPN_ConvertPoint to convert sourceX and sourceY from the source
 to dest space and returns the X or Y result based on the call.
 
 == NPCocoaEventWindowFocusChanged ==
--- a/dom/plugins/test/testplugin/nptest.cpp
+++ b/dom/plugins/test/testplugin/nptest.cpp
@@ -162,16 +162,17 @@ static bool getFocusEventCount(NPObject*
 static bool getEventModel(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool getReflector(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool isVisible(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool getWindowPosition(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool constructObject(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool setSitesWithData(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool setSitesWithDataCapabilities(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 static bool getLastKeyText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+static bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 
 static const NPUTF8* sPluginMethodIdentifierNames[] = {
   "npnEvaluateTest",
   "npnInvokeTest",
   "npnInvokeDefaultTest",
   "setUndefinedValueTest",
   "identifierToStringTest",
   "timerTest",
@@ -220,17 +221,18 @@ static const NPUTF8* sPluginMethodIdenti
   "getFocusEventCount",
   "getEventModel",
   "getReflector",
   "isVisible",
   "getWindowPosition",
   "constructObject",
   "setSitesWithData",
   "setSitesWithDataCapabilities",
-  "getLastKeyText"
+  "getLastKeyText",
+  "getNPNVdocumentOrigin"
 };
 static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
 static const ScriptableFunction sPluginMethodFunctions[] = {
   npnEvaluateTest,
   npnInvokeTest,
   npnInvokeDefaultTest,
   setUndefinedValueTest,
   identifierToStringTest,
@@ -280,17 +282,18 @@ static const ScriptableFunction sPluginM
   getFocusEventCount,
   getEventModel,
   getReflector,
   isVisible,
   getWindowPosition,
   constructObject,
   setSitesWithData,
   setSitesWithDataCapabilities,
-  getLastKeyText
+  getLastKeyText,
+  getNPNVdocumentOrigin
 };
 
 STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
               ARRAY_LENGTH(sPluginMethodFunctions));
 
 static const NPUTF8* sPluginPropertyIdentifierNames[] = {
   "propertyAndMethod"
 };
@@ -3469,8 +3472,27 @@ bool getLastKeyText(NPObject* npobj, con
     return false;
   }
 
   NPP npp = static_cast<TestNPObject*>(npobj)->npp;
   InstanceData* id = static_cast<InstanceData*>(npp->pdata);
   STRINGZ_TO_NPVARIANT(NPN_StrDup(id->lastKeyText.c_str()), *result);
   return true;
 }
+
+bool getNPNVdocumentOrigin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
+                           NPVariant* result)
+{
+  if (argCount != 0) {
+    return false;
+  }
+
+  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
+
+  char *origin = NULL;
+  NPError err = NPN_GetValue(npp, NPNVdocumentOrigin, &origin);
+  if (err != NPERR_NO_ERROR) {
+    return false;
+  }
+
+  STRINGZ_TO_NPVARIANT(origin, *result);
+  return true;
+}