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 id21157
push userjosh@mozilla.com
push dateWed, 14 Sep 2011 16:23:20 +0000
treeherdermozilla-central@262cfa5c56ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs622199
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;
+}