Brought NPAPI plugin up to current specs for the common code, built and
installed in Chrome.  Mostly works, but doesn't respond to button clicks.

Patch by: jat
Unreviewed


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6093 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/npapi/ScriptableInstance.cpp b/plugins/npapi/ScriptableInstance.cpp
index b171b32..0a5c8c3 100644
--- a/plugins/npapi/ScriptableInstance.cpp
+++ b/plugins/npapi/ScriptableInstance.cpp
@@ -20,6 +20,7 @@
 #include "InvokeMessage.h"
 #include "ReturnMessage.h"
 #include "ServerMethods.h"
+#include "AllowedConnections.h"
 #include "mozincludes.h"
 #include "scoped_ptr/scoped_ptr.h"
 #include "NPVariantWrapper.h"
@@ -27,6 +28,20 @@
 using std::string;
 using std::endl;
 
+static inline string convertToString(const NPString& str) {
+  return string(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
+}
+
+static bool askUserToAllow(const std::string& url, bool* remember) {
+  // TODO(jat): implement, for now allow anything but don't remember
+  *remember = false;
+  return true;
+}
+
+string ScriptableInstance::computeTabIdentity() {
+  return "";
+}
+
 void ScriptableInstance::dumpObjectBytes(NPObject* obj) {
   char buf[20];
   Debug::log(Debug::Debugging) << "   object bytes:\n";
@@ -46,6 +61,7 @@
     _channel(new HostChannel()),
     localObjects(),
     _connectId(NPN_GetStringIdentifier("connect")),
+    initID(NPN_GetStringIdentifier("init")),
     toStringID(NPN_GetStringIdentifier("toString")),
     connectedID(NPN_GetStringIdentifier("connected")),
     statsID(NPN_GetStringIdentifier("stats")),
@@ -177,7 +193,7 @@
 bool ScriptableInstance::hasMethod(NPIdentifier name) {
   Debug::log(Debug::Debugging) << "ScriptableInstance::hasMethod(name=" << NPN_UTF8FromIdentifier(name) << ")"
       << Debug::flush; 
-  if (name == _connectId || name == toStringID) {
+  if (name == _connectId || name == initID || name == toStringID) {
     return true;
   }
   return false;
@@ -191,6 +207,8 @@
   VOID_TO_NPVARIANT(*result);
   if (name == _connectId) {
     connect(args, argCount, result);
+  } else if (name == initID) {
+    init(args, argCount, result);
   } else if (name == toStringID) {
     // TODO(jat): figure out why this doesn't show in Firebug
     string val("[GWT OOPHM Plugin: connected=");
@@ -224,10 +242,33 @@
 // internal methods
 //=====================================================================================
 
+void ScriptableInstance::init(const NPVariant* args, unsigned argCount, NPVariant* result) {
+  if (argCount != 1 || !NPVariantProxy::isObject(args[0])) {
+    // TODO: better failure?
+    Debug::log(Debug::Error) << "ScriptableInstance::init called with incorrect arguments:\n";
+    for (unsigned i = 0; i < argCount; ++i) {
+      Debug::log(Debug::Error) << " " << i << " " << NPVariantProxy::toString(args[i]) << "\n";
+    }
+    Debug::log(Debug::Error) << Debug::flush;
+    result->type = NPVariantType_Void;
+    return;
+  }
+  if (window) {
+    NPN_ReleaseObject(window);
+  }
+  // replace our window object with that passed by the caller
+  window = NPVariantProxy::getAsObject(args[0]);
+  NPN_RetainObject(window);
+  BOOLEAN_TO_NPVARIANT(true, *result);
+  result->type = NPVariantType_Bool;
+}
+
 void ScriptableInstance::connect(const NPVariant* args, unsigned argCount, NPVariant* result) {
-  if (argCount < 2 || argCount > 4 || !NPVariantProxy::isString(args[0])
+  if (argCount != 5 || !NPVariantProxy::isString(args[0])
       || !NPVariantProxy::isString(args[1])
-      || (argCount == 3 && !NPVariantProxy::isObject(args[2]))) {
+      || !NPVariantProxy::isString(args[2])
+      || !NPVariantProxy::isString(args[3])
+      || !NPVariantProxy::isString(args[4])) {
     // TODO: better failure?
     Debug::log(Debug::Error) << "ScriptableInstance::connect called with incorrect arguments:\n";
     for (unsigned i = 0; i < argCount; ++i) {
@@ -237,18 +278,32 @@
     result->type = NPVariantType_Void;
     return;
   }
-  const NPString hostAddr = args[0].value.stringValue;
-  const NPString moduleName = args[1].value.stringValue;
-  if (argCount >= 3) {
-    if (window) {
-      NPN_ReleaseObject(window);
-    }
-    // replace our window object with that passed by the caller
-    window = NPVariantProxy::getAsObject(args[2]);
-    NPN_RetainObject(window);
-  }
-  Debug::log(Debug::Info) << "ScriptableInstance::connect(host=" << NPVariantProxy::toString(args[0])
-      << ",module=" << NPVariantProxy::toString(args[1]) << ")" << Debug::flush;
+  const NPString url = args[0].value.stringValue;
+  const NPString sessionKey = args[1].value.stringValue;
+  const NPString hostAddr = args[2].value.stringValue;
+  const NPString moduleName = args[3].value.stringValue;
+  const NPString hostedHtmlVersion = args[4].value.stringValue;
+  Debug::log(Debug::Info) << "ScriptableInstance::connect(url=" << NPVariantProxy::toString(args[0])
+      << ",sessionKey=" << NPVariantProxy::toString(args[1]) << ",host=" << NPVariantProxy::toString(args[2])
+      << ",module=" << NPVariantProxy::toString(args[3]) << ",hostedHtmlVers=" << NPVariantProxy::toString(args[4])
+      << ")" << Debug::flush;
+  const std::string urlStr = convertToString(url);
+  bool allowed = false;

+  // TODO(jat): load access list

+  if (!AllowedConnections::matchesRule(urlStr, &allowed)) {

+    // If we didn't match an existing rule, prompt the user

+    bool remember = false;

+    allowed = askUserToAllow(urlStr, &remember);

+    if (remember) {

+      // TODO(jat): update access list

+    }

+  }

+  if (!allowed) {

+    BOOLEAN_TO_NPVARIANT(false, *result);
+    result->type = NPVariantType_Bool;
+    return;

+  }

+
   bool connected = false;
   unsigned port = 9997;  // TODO(jat): should there be a default?
   int n = GetNPStringUTF8Length(hostAddr);
@@ -264,15 +319,36 @@
     port = atoi(s + 1);
   }
   Debug::log(Debug::Info) << "  host=" << host.get() << ",port=" << port << Debug::flush;
-  if (_channel->connectToHost(host.get(), port)) {
-    Debug::log(Debug::Debugging) << "  connected, sending loadModule" << Debug::flush;
-    connected = LoadModuleMessage::send(*_channel, VERSION, GetNPStringUTF8Characters(moduleName),
-        GetNPStringUTF8Length(moduleName), NPN_UserAgent(getNPP()), this);
+
+
+  if (!_channel->connectToHost(host.get(), port)) {
+    BOOLEAN_TO_NPVARIANT(false, *result);
+    result->type = NPVariantType_Bool;
   }
+
+  string hostedHtmlVersionStr = convertToString(hostedHtmlVersion);
+  if (!_channel->init(this, BROWSERCHANNEL_PROTOCOL_VERSION,
+      BROWSERCHANNEL_PROTOCOL_VERSION, hostedHtmlVersionStr)) {
+    BOOLEAN_TO_NPVARIANT(false, *result);
+    result->type = NPVariantType_Bool;
+  }
+
+  string moduleNameStr = convertToString(moduleName);
+  string userAgent(NPN_UserAgent(getNPP()));
+  string tabKeyStr = computeTabIdentity();
+  string sessionKeyStr = convertToString(sessionKey);
+  Debug::log(Debug::Debugging) << "  connected, sending loadModule" << Debug::flush;
+  connected = LoadModuleMessage::send(*_channel, urlStr, tabKeyStr, sessionKeyStr,
+      moduleNameStr, userAgent, this);
   BOOLEAN_TO_NPVARIANT(connected, *result);
   result->type = NPVariantType_Bool;
 }
 
+void ScriptableInstance::fatalError(HostChannel& channel, const std::string& message) {
+  // TODO(jat): better error handling
+  Debug::log(Debug::Error) << "Fatal error: " << message << Debug::flush;
+}
+
 void ScriptableInstance::dupString(const char* str, NPString& npString) {
   npString.UTF8Length = static_cast<uint32_t>(strlen(str));
   NPUTF8* chars = static_cast<NPUTF8*>(NPN_MemAlloc(npString.UTF8Length));
diff --git a/plugins/npapi/ScriptableInstance.h b/plugins/npapi/ScriptableInstance.h
index 4b4d5c0..035f823 100644
--- a/plugins/npapi/ScriptableInstance.h
+++ b/plugins/npapi/ScriptableInstance.h
@@ -87,6 +87,7 @@
 
   // Identifiers
   const NPIdentifier _connectId;
+  const NPIdentifier initID;
   const NPIdentifier toStringID;
   
   const NPIdentifier connectedID;
@@ -114,8 +115,10 @@
   virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
   virtual void sendFreeValues(HostChannel& channel);
   virtual void loadJsni(HostChannel& channel, const std::string& js);
+  virtual void fatalError(HostChannel& channel, const std::string& message);
 
   void connect(const NPVariant* args, unsigned argCount, NPVariant* result);
+  void init(const NPVariant* args, unsigned argCount, NPVariant* result);
   
   Value clientMethod_getProperty(HostChannel& channel, int numArgs, const Value* const args);
   Value clientMethod_setProperty(HostChannel& channel, int numArgs, const Value* const args);
@@ -126,6 +129,9 @@
   bool JavaObject_getProperty(int objectId, int dispId, NPVariant* result);
   bool JavaObject_setProperty(int objectId, int dispId, const NPVariant* value);
   bool JavaObject_getToStringTearOff(NPVariant* result);
+
+private:
+  std::string computeTabIdentity();
 };
 
 #endif
diff --git a/plugins/npapi/VisualStudio/firefox-plugin.vcproj b/plugins/npapi/VisualStudio/firefox-plugin.vcproj
index e24968f..7ca867f 100755
--- a/plugins/npapi/VisualStudio/firefox-plugin.vcproj
+++ b/plugins/npapi/VisualStudio/firefox-plugin.vcproj
@@ -63,7 +63,7 @@
 				Name="VCLinkerTool"

 				AdditionalDependencies="ws2_32.lib"

 				ShowProgress="2"

-				OutputFile="$(ProjectDir)\..\extension\platform\WINNT_x86-msvc\plugins\npOOPHM.dll"

+				OutputFile="$(ProjectDir)\..\prebuilt\WINNT_x86-msvc\npOOPHM.dll"

 				LinkIncremental="1"

 				ModuleDefinitionFile="$(ProjectDir)\..\npOOPHM.def"

 				GenerateDebugInformation="true"

@@ -199,6 +199,14 @@
 				>

 			</File>

 			<File

+				RelativePath="..\..\common\CheckVersionsMessage.h"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\ChooseTransportMessage.h"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\Debug.h"

 				>

 			</File>

@@ -207,6 +215,10 @@
 				>

 			</File>

 			<File

+				RelativePath="..\..\common\FatalErrorMessage.h"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\FreeValueMessage.h"

 				>

 			</File>

@@ -279,6 +291,10 @@
 				>

 			</File>

 			<File

+				RelativePath="..\..\common\ProtocolVersionMessage.h"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\QuitMessage.h"

 				>

 			</File>

@@ -311,6 +327,10 @@
 				>

 			</File>

 			<File

+				RelativePath="..\..\common\SwitchTransportMessage.h"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\Value.h"

 				>

 			</File>

@@ -335,10 +355,22 @@
 				>

 			</File>

 			<File

+				RelativePath="..\..\common\CheckVersionsMessage.cpp"

+				>

+			</File>

+			<File

+				RelativePath="..\..\common\ChooseTransportMessage.cpp"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\Debug.cpp"

 				>

 			</File>

 			<File

+				RelativePath="..\..\common\FatalErrorMessage.cpp"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\FreeValueMessage.cpp"

 				>

 			</File>

@@ -387,6 +419,10 @@
 				>

 			</File>

 			<File

+				RelativePath="..\..\common\ProtocolVersionMessage.cpp"

+				>

+			</File>

+			<File

 				RelativePath="..\..\common\ReturnMessage.cpp"

 				>

 			</File>

@@ -402,6 +438,10 @@
 				RelativePath="..\..\common\Socket.cpp"

 				>

 			</File>

+			<File

+				RelativePath="..\..\common\SwitchTransportMessage.cpp"

+				>

+			</File>

 		</Filter>

 	</Files>

 	<Globals>

diff --git a/plugins/npapi/npOOPHM.rc b/plugins/npapi/npOOPHM.rc
index 5863b24..8c0f920 100644
--- a/plugins/npapi/npOOPHM.rc
+++ b/plugins/npapi/npOOPHM.rc
@@ -1,7 +1,7 @@
 #include "resource.h"
 
 #define APSTUDIO_READONLY_SYMBOLS
-#include "mfc/afxres.h"
+#include "windows.h"
 #undef APSTUDIO_READONLY_SYMBOLS
 
 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
diff --git a/plugins/npapi/prebuilt/winnt_x86-msvc/npOOPHM.dll b/plugins/npapi/prebuilt/winnt_x86-msvc/npOOPHM.dll
new file mode 100644
index 0000000..8e91518
--- /dev/null
+++ b/plugins/npapi/prebuilt/winnt_x86-msvc/npOOPHM.dll
Binary files differ