Initial checkin of OOPHM plugins into trunk. Testing of non-XPCOM plugins
is still required, and more platforms need to be built.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5868 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/common/AllowedConnections.cpp b/plugins/common/AllowedConnections.cpp
new file mode 100644
index 0000000..1f93f65
--- /dev/null
+++ b/plugins/common/AllowedConnections.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Debug.h"
+
+#include "AllowedConnections.h"
+
+void AllowedConnections::init() {
+}
+
+bool AllowedConnections::isAllowed(const std::string& target) {
+ return true;
+}
+
+bool AllowedConnections::isAllowed(const char* host, int port) {
+ return true;
+}
+
+void AllowedConnections::parseRule(const std::string& rule) {
+};
diff --git a/plugins/common/AllowedConnections.h b/plugins/common/AllowedConnections.h
new file mode 100644
index 0000000..0dbed2e
--- /dev/null
+++ b/plugins/common/AllowedConnections.h
@@ -0,0 +1,55 @@
+#ifndef _H_AllowedConnections
+#define _H_AllowedConnections
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+
+/**
+ * Manages rules to control access to other sites.
+ */
+class AllowedConnections {
+public:
+ AllowedConnections() {
+ init();
+ }
+
+ AllowedConnections(const std::string& rule) {
+ init();
+ parseRule(rule);
+ }
+
+ /**
+ * Returns true if a connection to the requested target is allowed.
+ *
+ * @param target host or host:port to test
+ */
+ bool isAllowed(const std::string& target);
+
+ /**
+ * Returns true if a connection to the requested target is allowed.
+ *
+ * @param host name or address to connect to
+ * @param port TCP port to connect to
+ */
+ bool isAllowed(const char* host, int port);
+
+private:
+ void init();
+ void parseRule(const std::string& rule);
+};
+
+#endif
diff --git a/plugins/common/BrowserChannel.h b/plugins/common/BrowserChannel.h
new file mode 100644
index 0000000..0a65c62
--- /dev/null
+++ b/plugins/common/BrowserChannel.h
@@ -0,0 +1,38 @@
+/*
+ * DO NOT EDIT
+ * Generated by com.google.gwt.util.tools.OophmHeaderFileGenerator
+ * TODO(jat): update generator to handle modifications
+ */
+
+/* from BrowserChannel.BROWSERCHANNEL_PROTOCOL_VERSION */
+#define BROWSERCHANNEL_PROTOCOL_VERSION 1
+
+/* from com.google.gwt.dev.shell.BrowserChannel.SpecialDispatchId */
+#define SPECIAL_HAS_METHOD 0
+#define SPECIAL_HAS_PROPERTY 1
+#define SPECIAL_GET_PROPERTY 2
+#define SPECIAL_SET_PROPERTY 3
+
+/* from com.google.gwt.dev.shell.BrowserChannel.MessageType */
+#define MESSAGE_TYPE_INVOKE 0
+#define MESSAGE_TYPE_RETURN 1
+#define MESSAGE_TYPE_LOAD_MODULE 2
+#define MESSAGE_TYPE_QUIT 3
+#define MESSAGE_TYPE_LOADJSNI 4
+#define MESSAGE_TYPE_INVOKESPECIAL 5
+#define MESSAGE_TYPE_FREEVALUE 6
+
+/* from com.google.gwt.dev.shell.BrowserChannel.Value.ValueType */
+#define VALUE_TYPE_NULL 0
+#define VALUE_TYPE_BOOLEAN 1
+#define VALUE_TYPE_BYTE 2
+#define VALUE_TYPE_CHAR 3
+#define VALUE_TYPE_SHORT 4
+#define VALUE_TYPE_INT 5
+#define VALUE_TYPE_LONG 6
+#define VALUE_TYPE_FLOAT 7
+#define VALUE_TYPE_DOUBLE 8
+#define VALUE_TYPE_STRING 9
+#define VALUE_TYPE_JAVA_OBJECT 10
+#define VALUE_TYPE_JS_OBJECT 11
+#define VALUE_TYPE_UNDEFINED 12
diff --git a/plugins/common/ByteOrder.h b/plugins/common/ByteOrder.h
new file mode 100644
index 0000000..7e6bd86
--- /dev/null
+++ b/plugins/common/ByteOrder.h
@@ -0,0 +1,141 @@
+#ifndef __H_ByteOrder
+#define __H_ByteOrder
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Platform.h"
+#include <cstring>
+
+class ByteOrder {
+private:
+ enum FloatByteOrder {
+ FLOAT_BIG_ENDIAN,
+ FLOAT_LITTLE_ENDIAN,
+ // TODO(jat): do we need to consider anything other than straight
+ // big-endian or little-endian? PDP-11 (irrelevant), ARM (probably
+ // relevant for mobile devices), MIPS (probably not relevant, but maybe)
+ // and others have some intermediate endianess. Also, FP-endianess is not
+ // necessarily the same as that for integers.
+ };
+#ifdef PLATFORM_FLOAT_ENDIANESS
+ static const FloatByteOrder floatByteOrder = PLATFORM_FLOAT_ENDIANESS;
+#else
+ FloatByteOrder floatByteOrder;
+#endif
+
+ typedef union {
+ float v;
+ char b[sizeof(float)];
+ } FloatUnion;
+
+ typedef union {
+ double v;
+ char b[sizeof(double)];
+ } DoubleUnion;
+
+ /**
+ * Copy src to dest, reversing the order of the bytes.
+ * Assumes src and dest do not overlap.
+ */
+ void memcpyrev(char* dest, const char* src, size_t n) {
+ src += n;
+ while (n-- > 0) {
+ *dest++ = *--src;
+ }
+ }
+public:
+ ByteOrder() {
+#ifndef PLATFORM_FLOAT_ENDIANESS
+ DoubleUnion u;
+ memset(u.b, 0, sizeof(u.b));
+ u.b[0] = (char) 0x80;
+ u.b[7] = (char) 0x02;
+ // TODO(jat): add more tests here if we support other endianess
+ floatByteOrder = u.v > 0 ? FLOAT_LITTLE_ENDIAN : FLOAT_BIG_ENDIAN;
+ if (Debug::level(Debug::Debugging)) {
+ std::string str = "Unknown";
+ switch (floatByteOrder) {
+ case FLOAT_LITTLE_ENDIAN:
+ str = "little-endian";
+ break;
+ case FLOAT_BIG_ENDIAN:
+ str = "big-endian";
+ break;
+ }
+ Debug::log(Debug::Debugging) << "Dynamically detected float byte order: "
+ << str << Debug::flush;
+ }
+#endif
+ }
+
+ void bytesFromDouble(double v, char* bytes) {
+ DoubleUnion u;
+ u.v = v;
+ switch (floatByteOrder) {
+ case FLOAT_LITTLE_ENDIAN:
+ memcpyrev(bytes, u.b, sizeof(u.b));
+ break;
+ case FLOAT_BIG_ENDIAN:
+ memcpy(bytes, u.b, sizeof(u.b));
+ break;
+ }
+ }
+
+ void bytesFromFloat(float v, char* bytes) {
+ FloatUnion u;
+ u.v = v;
+ switch (floatByteOrder) {
+ case FLOAT_LITTLE_ENDIAN:
+ memcpyrev(bytes, u.b, sizeof(u.b));
+ break;
+ case FLOAT_BIG_ENDIAN:
+ memcpy(bytes, u.b, sizeof(u.b));
+ break;
+ }
+ }
+
+ double doubleFromBytes(const char* bytes) {
+ DoubleUnion u;
+ switch (floatByteOrder) {
+ case FLOAT_LITTLE_ENDIAN:
+ memcpyrev(u.b, bytes, sizeof(u.b));
+ break;
+ case FLOAT_BIG_ENDIAN:
+ // TODO(jat): find a way to avoid the extra copy while keeping the
+ // compiler happy.
+ memcpy(u.b, bytes, sizeof(u.b));
+ break;
+ }
+ return u.v;
+ }
+
+ float floatFromBytes(const char* bytes) {
+ FloatUnion u;
+ switch (floatByteOrder) {
+ case FLOAT_LITTLE_ENDIAN:
+ memcpyrev(u.b, bytes, sizeof(u.b));
+ break;
+ case FLOAT_BIG_ENDIAN:
+ // TODO(jat): find a way to avoid the extra copy while keeping the
+ // compiler happy.
+ memcpy(u.b, bytes, sizeof(u.b));
+ break;
+ }
+ return u.v;
+ }
+};
+
+#endif
diff --git a/plugins/common/Debug.cpp b/plugins/common/Debug.cpp
new file mode 100644
index 0000000..66382bd
--- /dev/null
+++ b/plugins/common/Debug.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <cstdio>
+
+#ifdef _WINDOWS
+#include <windows.h>
+#endif
+
+#include "Debug.h"
+
+#ifdef GWT_DEBUGDISABLE
+// Dummy implementations for when debugging has been disabled
+Debug::DebugStream& Debug::flush(Debug::DebugStream& dbg) {
+ return dbg;
+}
+
+void Debug::logFinish() {}
+
+void Debug::logString(const char* str) {}
+
+#else
+// Warning: this function is inlined in the manipulator output operator in DebugStream.
+// It only remains here because some compiler/linker combinations such as MSVC will
+// give unresolved symbol errors if it isn't -- GCC, for example, will completely remove
+// all traces of this method.
+Debug::DebugStream& Debug::flush(Debug::DebugStream& dbg) {
+ Debug::logFinish();
+ return dbg;
+}
+
+// These methods are implemented in an Objective-C++ file on OSX
+#if !defined(__APPLE_CC__) || defined(__mac)
+
+#ifdef _WINDOWS
+#define DEBUG_BUF_SIZE 2048
+
+static char buf[DEBUG_BUF_SIZE + 3]; // room for CR NL Null
+static char *bufPtr = buf;
+#endif
+
+void Debug::logFinish() {
+#ifdef _WINDOWS
+ logString("\r\n");
+ ::OutputDebugStringA(buf);
+ bufPtr = buf;
+#else
+ putchar('\n');
+#endif
+}
+
+// logStart may be called multiple times per logFinish
+void Debug::logStart(LogLevel level) {
+}
+
+void Debug::logString(const char* str) {
+#ifdef _WINDOWS
+ size_t len = strlen(str);
+ size_t buflen = DEBUG_BUF_SIZE - (bufPtr - buf);
+ if (len >= buflen) {
+ len = buflen - 1;
+ }
+ strncpy_s(bufPtr, buflen, str, len);
+ bufPtr += len;
+#else
+ printf("%s", str);
+#endif
+}
+#endif
+#endif
+
diff --git a/plugins/common/Debug.h b/plugins/common/Debug.h
new file mode 100644
index 0000000..c44e824
--- /dev/null
+++ b/plugins/common/Debug.h
@@ -0,0 +1,214 @@
+#ifndef _H_Debug
+#define _H_Debug
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+#ifndef _WINDOWS
+// TODO(jat): remove, for snprintf prototypes which should go away
+#include <stdio.h>
+#endif
+
+#include <ostream>
+#include <string>
+
+#include "Platform.h"
+
+// Get a default debug config if none supplied.
+#ifndef GWT_DEBUGLEVEL
+#include "DebugLevel.h"
+#endif
+
+/**
+ * Debugging class to get debugging output to a platform-specific location, with multiple
+ * levels supported.
+ *
+ * To use:
+ * #define GWT_DEBUGLEVEL level // where level is in LogLevel
+ * #include "Debug.h"
+ * Debug::log(Debug::Warning) << ...
+ *
+ * Zero overhead if GWT_DEBUGDISABLE is defined, other than the effort spent on side
+ * effects for stream object construction. If that is expensive, use something like
+ * Debug::level(Debug::Warning) to conditionalize expensive logging computations.
+ */
+class Debug {
+public:
+ enum LogLevel {
+ None,
+ Error,
+ Warning,
+ Info,
+ Debugging,
+ Spam
+ };
+
+private:
+ static const LogLevel minLogLevel = GWT_DEBUGLEVEL;
+
+public:
+ /**
+ * Return true if the requested level would be logged. Use to protect
+ * expensive computations for logging.
+ */
+ static bool level(LogLevel testLevel) {
+#ifdef GWT_DEBUGDISABLE
+ return false;
+#else
+ return testLevel <= minLogLevel;
+#endif
+ }
+
+private:
+ // complete the current log message
+ static void logFinish();
+
+ // begin a new log message
+ static void logStart(LogLevel level);
+
+ // add a string to the current log message
+ static void logString(const char* str);
+ static void logString(const std::string& str) {
+ logString(str.c_str());
+ }
+
+public:
+ // Note that flush is special-cased in the manipulator output operator,
+ // and its implementation is inlined there. If its implementation is
+ // modified, the implementation of the manipulator output operator will
+ // need to be modified as well.
+ class DebugStream;
+ static DebugStream& flush(DebugStream& dbg);
+
+ class DebugStream {
+
+ const bool shouldLog;
+
+ // TODO(jat): better implementations of output operators
+ public:
+ DebugStream(LogLevel level) : shouldLog(Debug::level(level)) {
+ if (shouldLog) {
+ Debug::logStart(level);
+ }
+ }
+
+ bool isActive() const {
+ return shouldLog;
+ }
+
+ DebugStream& operator<<(long v) {
+ if (shouldLog) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%ld", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(unsigned long v) {
+ if (shouldLog) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%lu", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(long long v) {
+ if (shouldLog) {
+ char buf[40];
+ snprintf(buf, sizeof(buf), "%lld", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(unsigned long long v) {
+ if (shouldLog) {
+ char buf[40];
+ snprintf(buf, sizeof(buf), "%llu", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(int v) {
+ if (shouldLog) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%d", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(unsigned int v) {
+ if (shouldLog) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%u", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(double v) {
+ if (shouldLog) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%g", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(const std::string& str) {
+ if (shouldLog) {
+ Debug::logString(str);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(const char* str) {
+ if (shouldLog) {
+ Debug::logString(str);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(const void* v) {
+ if (shouldLog) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%p", v);
+ Debug::logString(buf);
+ }
+ return *this;
+ }
+
+ DebugStream& operator<<(DebugStream& (*manip)(DebugStream&)) {
+ if (shouldLog) {
+ // Special-case flush for efficiency.
+ if (manip == Debug::flush) {
+ Debug::logFinish();
+ } else {
+ return manip(*this);
+ }
+ }
+ return *this;
+ }
+ };
+
+ static DebugStream log(LogLevel testLevel) {
+ return DebugStream(testLevel);
+ }
+};
+
+#endif
diff --git a/plugins/common/DebugLevel.h b/plugins/common/DebugLevel.h
new file mode 100644
index 0000000..d172e99
--- /dev/null
+++ b/plugins/common/DebugLevel.h
@@ -0,0 +1,25 @@
+#ifndef _H_DebugLevel
+#define _H_DebugLevel
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+// Defines the default debug level if not defined -- see Debug.h
+// Can also define GWT_DEBUGDISABLE to remove all traces of the debug code.
+//#define GWT_DEBUGLEVEL Debugging
+#define GWT_DEBUGLEVEL Spam
+//#define GWT_DEBUGDISABLE
+
+#endif
diff --git a/plugins/common/FreeValueMessage.cpp b/plugins/common/FreeValueMessage.cpp
new file mode 100644
index 0000000..b7f0bab
--- /dev/null
+++ b/plugins/common/FreeValueMessage.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "FreeValueMessage.h"
+#include "HostChannel.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+FreeValueMessage::~FreeValueMessage() {
+ delete[] ids;
+}
+
+FreeValueMessage* FreeValueMessage::receive(HostChannel& channel) {
+ int idCount;
+ if (!channel.readInt(idCount)) {
+ // TODO(jat): error handling
+ return 0;
+ }
+ // TODO: validate idCount
+ scoped_array<int> ids(new int[idCount]);
+
+ for (int i = 0; i < idCount; ++i) {
+ if (!channel.readInt(ids[i])) return 0;
+ }
+ return new FreeValueMessage(idCount, ids.release());
+}
+
+bool FreeValueMessage::send(HostChannel& channel, int idCount, const int* ids) {
+ if (!channel.sendByte(TYPE)) return false;
+ if (!channel.sendInt(idCount)) return false;
+ for (int i = 0; i < idCount; ++i) {
+ if (!channel.sendInt(ids[i])) return false;
+ }
+ return true;
+}
diff --git a/plugins/common/FreeValueMessage.h b/plugins/common/FreeValueMessage.h
new file mode 100644
index 0000000..a8b7a64
--- /dev/null
+++ b/plugins/common/FreeValueMessage.h
@@ -0,0 +1,51 @@
+#ifndef __H_FreeValueMessage
+#define __H_FreeValueMessage
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+#include "Message.h"
+#include "BrowserChannel.h"
+#include "HostChannel.h"
+
+class FreeValueMessage : public Message {
+public:
+ static const char TYPE = MESSAGE_TYPE_FREEVALUE;
+private:
+ int idCount;
+ const int* ids;
+
+ FreeValueMessage(int idCount, const int* ids) : idCount(idCount), ids(ids) {}
+
+public:
+ ~FreeValueMessage();
+
+ virtual char getType() const {
+ return TYPE;
+ }
+
+ int getIdCount() const {
+ return idCount;
+ }
+
+ const int* const getIds() const {
+ return ids;
+ }
+
+ static FreeValueMessage* receive(HostChannel& channel);
+ static bool send(HostChannel& channel, int idCount, const int* ids);
+};
+#endif
diff --git a/plugins/common/HashMap.h b/plugins/common/HashMap.h
new file mode 100644
index 0000000..c76b220
--- /dev/null
+++ b/plugins/common/HashMap.h
@@ -0,0 +1,58 @@
+#ifndef _H_HashMap
+#define _H_HashMap
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+// Portability wrapper for hash maps, since they aren't part of the standard C++ library
+
+#ifdef __GNUC__
+#if 0
+// future support
+#include <unordered_map>
+#define hash_map unordered_map
+
+namespace HashFunctions = std;
+#else
+#include <ext/hash_map>
+using __gnu_cxx::hash_map;
+
+// TODO(jat): surely this exists somewhere already?
+// TODO(jat): portability issues
+namespace __gnu_cxx {
+ using std::size_t;
+
+ template<> struct hash<std::string> {
+ size_t operator()(const std::string& str) const {
+ return hash<const char*>()(str.c_str());
+ }
+ };
+};
+namespace HashFunctions = __gnu_cxx;
+#endif
+#elif sun
+// TODO(jat): find a hash_map implementation for Solaris
+#include <map>
+namespace HashFunctions = std;
+#define hash_map map
+using std::map;
+#else
+// Try something reasonably standard, which works in Windows
+#include <hash_map>
+using stdext::hash_map;
+namespace HashFunctions = stdext;
+#endif
+
+#endif
diff --git a/plugins/common/HostChannel.cpp b/plugins/common/HostChannel.cpp
new file mode 100644
index 0000000..896667e
--- /dev/null
+++ b/plugins/common/HostChannel.cpp
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+#include "Debug.h"
+
+#ifdef _WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+#include <time.h>
+
+#include "Platform.h"
+#include "ByteOrder.h"
+
+#include "FreeValueMessage.h"
+#include "HostChannel.h"
+#include "LoadJsniMessage.h"
+#include "InvokeMessage.h"
+#include "InvokeSpecialMessage.h"
+#include "QuitMessage.h"
+#include "ReturnMessage.h"
+#include "Value.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+using namespace std;
+
+ByteOrder HostChannel::byteOrder;
+
+bool HostChannel::connectToHost(const char* host, unsigned port) {
+ Debug::log(Debug::Info) << "Initiating GWT hosted mode connection to host "
+ << host << ", port " << port << Debug::flush;
+ if (!port) {
+ port = 9997;
+ }
+ if (!whitelist.isAllowed(host, port)) {
+ Debug::log(Debug::Error) << "Permission to connect to " << host << ":" << port
+ << " denied" << Debug::flush;
+ return false;
+ }
+ return sock.connect(host, port);
+}
+
+bool HostChannel::disconnectFromHost() {
+ Debug::log(Debug::Debugging) << "Disconnecting channel" << Debug::flush;
+ if (!isConnected()) {
+ Debug::log(Debug::Error) << "Disconnecting already disconnected channel" << Debug::flush;
+ return false;
+ }
+ QuitMessage::send(*this);
+ flush();
+ sock.disconnect();
+ return true;
+}
+
+bool HostChannel::readInt(int32_t& data) {
+ int32_t d;
+ if (!readBytes(&d, sizeof(d))) return false;
+ data = ntohl(d);
+ return true;
+}
+
+bool HostChannel::sendInt(int32_t data) {
+ uint32_t d = htonl(data);
+ return sendBytes(&d, sizeof(d));
+}
+
+bool HostChannel::readShort(short& data) {
+ int16_t d;
+ if (!readBytes(&d, sizeof(d))) return false;
+ data = ntohs(d);
+ return true;
+}
+
+bool HostChannel::sendShort(const short data) {
+ uint16_t d = htons(data);
+ return sendBytes(&d, sizeof(d));
+}
+
+bool HostChannel::readLong(int64_t& data) {
+ // network is big-endian
+ int32_t d[2];
+ if (!readInt(d[0])) return false;
+ if (!readInt(d[1])) return false;
+ data = (static_cast<int64_t>(d[0]) << 32) | ntohl(d[1]);
+ return true;
+}
+
+bool HostChannel::sendLong(const int64_t data) {
+ if (!sendInt(static_cast<int32_t>(data >> 32))) {
+ return false;
+ }
+ return sendInt(static_cast<int32_t>(data));
+}
+
+bool HostChannel::readFloat(float& data) {
+ char bytes[sizeof(data)];
+ if (!readBytes(bytes, sizeof(bytes))) {
+ return false;
+ }
+ data = byteOrder.floatFromBytes(bytes);
+ return true;
+}
+
+bool HostChannel::sendFloat(const float data) {
+ char bytes[sizeof(data)];
+ byteOrder.bytesFromFloat(data, bytes);
+ return sendBytes(bytes, sizeof(bytes));
+}
+
+bool HostChannel::readDouble(double& data) {
+ char bytes[sizeof(data)];
+ if (!readBytes(bytes, sizeof(bytes))) {
+ return false;
+ }
+ data = byteOrder.doubleFromBytes(bytes);
+ return true;
+}
+
+bool HostChannel::sendDouble(const double data) {
+ char bytes[sizeof(data)];
+ byteOrder.bytesFromDouble(data, bytes);
+ return sendBytes(bytes, sizeof(bytes));
+}
+
+bool HostChannel::readStringLength(uint32_t& data) {
+ int32_t val;
+ if (!readInt(val)) return false;
+ // TODO: assert positive?
+ data = val;
+ return true;
+}
+
+bool HostChannel::readStringBytes(char* data, const uint32_t len) {
+ return readBytes(data, len);
+}
+
+bool HostChannel::readString(std::string& strRef) {
+ uint32_t len;
+ if (!readStringLength(len)) {
+ Debug::log(Debug::Error) << "readString: failed to read length"
+ << Debug::flush;
+ return false;
+ }
+ // Allocating variable-length arrays on the stack is a GCC feature,
+ // and is vulnerable to stack overflow attacks, so we allocate on the heap.
+ scoped_array<char> buf(new char[len]);
+ if (!readStringBytes(buf.get(), len)) {
+ Debug::log(Debug::Error) << "readString: failed to read " << len
+ << " bytes" << Debug::flush;
+ return false;
+ }
+ strRef.assign(buf.get(), len);
+ return true;
+}
+
+static inline double operator-(const struct timeval& end,
+ const struct timeval& begin) {
+ double us = end.tv_sec * 1000000.0 + end.tv_usec - begin.tv_sec * 1000000.0
+ - begin.tv_usec;
+ return us;
+}
+
+ReturnMessage* HostChannel::reactToMessages(SessionHandler* handler, bool expectReturn) {
+ char type;
+ while (true) {
+ flush();
+ Debug::log(Debug::Spam) << "Waiting for response, flushed output" << Debug::flush;
+ if (!readByte(type)) {
+ Debug::log(Debug::Error) << "Failed to receive message type" << Debug::flush;
+ return 0;
+ }
+ switch (type) {
+ case MESSAGE_TYPE_INVOKE:
+ {
+ scoped_ptr<InvokeMessage> imsg(InvokeMessage::receive(*this));
+ if (!imsg.get()) {
+ Debug::log(Debug::Error) << "Failed to receive invoke message" << Debug::flush;
+ return 0;
+ }
+ Value returnValue;
+ bool exception = handler->invoke(*this, imsg->getThis(), imsg->getMethodName(),
+ imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+ handler->sendFreeValues(*this);
+ ReturnMessage::send(*this, exception, returnValue);
+ }
+ break;
+ case MESSAGE_TYPE_INVOKESPECIAL:
+ {
+ // scottb: I think this is never used; I think server never sends invokeSpecial
+ scoped_ptr<InvokeSpecialMessage> imsg(InvokeSpecialMessage::receive(*this));
+ if (!imsg.get()) {
+ Debug::log(Debug::Error) << "Failed to receive invoke special message" << Debug::flush;
+ return 0;
+ }
+ Value returnValue;
+ bool exception = handler->invokeSpecial(*this, imsg->getDispatchId(),
+ imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+ handler->sendFreeValues(*this);
+ ReturnMessage::send(*this, exception, returnValue);
+ }
+ break;
+ case MESSAGE_TYPE_FREEVALUE:
+ {
+ scoped_ptr<FreeValueMessage> freeMsg(FreeValueMessage::receive(*this));
+ if (!freeMsg.get()) {
+ Debug::log(Debug::Error) << "Failed to receive free value message" << Debug::flush;
+ return 0;
+ }
+ handler->freeValue(*this, freeMsg->getIdCount(), freeMsg->getIds());
+ }
+ // do not send a response
+ break;
+ case MESSAGE_TYPE_LOADJSNI:
+ {
+ scoped_ptr<LoadJsniMessage> loadMsg(LoadJsniMessage::receive(*this));
+ if (!loadMsg.get()) {
+ Debug::log(Debug::Error) << "Failed to receive load JSNI message" << Debug::flush;
+ return 0;
+ }
+ handler->loadJsni(*this, loadMsg->getJs());
+ }
+ // do not send a response
+ break;
+ case MESSAGE_TYPE_RETURN:
+ if (!expectReturn) {
+ Debug::log(Debug::Error) << "Received unexpected RETURN" << Debug::flush;
+ }
+ return ReturnMessage::receive(*this);
+ case MESSAGE_TYPE_QUIT:
+ if (expectReturn) {
+ Debug::log(Debug::Error) << "Received QUIT while waiting for return" << Debug::flush;
+ }
+ disconnectFromHost();
+ return 0;
+ default:
+ // TODO(jat): error handling
+ Debug::log(Debug::Error) << "Unexpected message type " << type
+ << ", expectReturn=" << expectReturn << Debug::flush;
+ disconnectFromHost();
+ return 0;
+ }
+ }
+}
+
+bool HostChannel::readValue(Value& valueRef) {
+ char typeBuf;
+ if (!readByte(typeBuf)) return false;
+ Value::ValueType type = Value::ValueType(typeBuf);
+ switch (type) {
+ case Value::NULL_TYPE:
+ valueRef.setNull();
+ return true;
+ case Value::UNDEFINED:
+ valueRef.setUndefined();
+ return true;
+ case Value::BOOLEAN:
+ {
+ char val;
+ if (!readByte(val)) return false;
+ valueRef.setBoolean(val != 0);
+ }
+ return true;
+ case Value::BYTE:
+ {
+ char val;
+ if (!readByte(val)) return false;
+ valueRef.setByte(val);
+ }
+ return true;
+ case Value::CHAR:
+ {
+ short val;
+ if (!readShort(val)) return false;
+ valueRef.setChar(val);
+ }
+ return true;
+ case Value::SHORT:
+ {
+ short val;
+ if (!readShort(val)) return false;
+ valueRef.setShort(val);
+ }
+ return true;
+ case Value::STRING:
+ {
+ std::string val;
+ if (!readString(val)) return false;
+ valueRef.setString(val);
+ }
+ return true;
+ case Value::INT:
+ {
+ int val;
+ if (!readInt(val)) return false;
+ valueRef.setInt(val);
+ }
+ return true;
+ case Value::LONG:
+ {
+ int64_t val;
+ if (!readLong(val)) return false;
+ valueRef.setLong(val);
+ }
+ return true;
+ case Value::DOUBLE:
+ {
+ double val;
+ if (!readDouble(val)) return false;
+ valueRef.setDouble(val);
+ }
+ return true;
+ case Value::JAVA_OBJECT:
+ {
+ int objId;
+ if (!readInt(objId)) return false;
+ valueRef.setJavaObject(objId);
+ }
+ return true;
+ case Value::JS_OBJECT:
+ {
+ int val;
+ if (!readInt(val)) return false;
+ valueRef.setJsObjectId(val);
+ }
+ return true;
+ default:
+ Debug::log(Debug::Error) << "Unhandled value type sent from server: " << type << Debug::flush;
+ break;
+ }
+ return false;
+}
+
+bool HostChannel::sendValue(const Value& value) {
+ Value::ValueType type = value.getType();
+ if (!sendByte(type)) return false;
+ switch (type) {
+ case Value::NULL_TYPE:
+ case Value::UNDEFINED:
+ // Null and Undefined only have the tag byte, no data
+ return true;
+ case Value::BOOLEAN:
+ return sendByte(value.getBoolean() ? 1 : 0);
+ case Value::BYTE:
+ return sendByte(value.getByte());
+ case Value::CHAR:
+ return sendShort(short(value.getChar()));
+ case Value::SHORT:
+ return sendShort(value.getShort());
+ case Value::INT:
+ return sendInt(value.getInt());
+ case Value::LONG:
+ return sendLong(value.getLong());
+ case Value::STRING:
+ return sendString(value.getString());
+ case Value::DOUBLE:
+ return sendDouble(value.getDouble());
+ case Value::FLOAT:
+ return sendFloat(value.getFloat());
+ case Value::JS_OBJECT:
+ return sendInt(value.getJsObjectId());
+ case Value::JAVA_OBJECT:
+ return sendInt(value.getJavaObjectId());
+ default:
+ Debug::log(Debug::Error) << "Unhandled value type sent to server: " << type << Debug::flush;
+ break;
+ }
+ return false;
+}
diff --git a/plugins/common/HostChannel.h b/plugins/common/HostChannel.h
new file mode 100644
index 0000000..0097b6d
--- /dev/null
+++ b/plugins/common/HostChannel.h
@@ -0,0 +1,139 @@
+#ifndef __H_HostChannel
+#define __H_HostChannel
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Debug.h"
+
+// Sun's cstdio doesn't define a bunch of stuff
+#include <stdio.h>
+#include <string>
+
+#include "ByteOrder.h"
+#include "Socket.h"
+#include "AllowedConnections.h"
+#include "Platform.h"
+#include "Message.h"
+#include "ReturnMessage.h"
+#include "Value.h"
+#include "SessionHandler.h"
+
+class HostChannel {
+ Socket sock;
+ AllowedConnections whitelist;
+ static ByteOrder byteOrder;
+
+public:
+ ~HostChannel() {
+ if (isConnected()) {
+ disconnectFromHost();
+ }
+ Debug::log(Debug::Debugging) << "HostChannel destroyed" << Debug::flush;
+ }
+
+ bool connectToHost(const char* host, unsigned port);
+ bool disconnectFromHost();
+
+ bool isConnected() const {
+ return sock.isConnected();
+ }
+
+ bool readBytes(void* data, size_t dataLen) {
+ char* ptr = static_cast<char*>(data);
+ while(dataLen > 0) {
+ if (!readByte(*ptr++)) {
+ return false;
+ }
+ --dataLen;
+ }
+ return true;
+ }
+
+ bool sendBytes(const void* data, size_t dataLen) {
+ const char* ptr = static_cast<const char*>(data);
+ while(dataLen > 0) {
+ if (!sendByte(*ptr++)) {
+ return false;
+ }
+ --dataLen;
+ }
+ return true;
+ }
+
+ // TODO: don't pass out-params by reference as it makes the call site misleading
+ bool readInt(int32_t& data);
+ bool sendInt(const int32_t data);
+
+ bool readShort(short& data);
+ bool sendShort(const short data);
+
+ bool readLong(int64_t& data);
+ bool sendLong(const int64_t data);
+
+ bool readFloat(float& data);
+ bool sendFloat(const float data);
+
+ bool readDouble(double& doubleRef);
+ bool sendDouble(const double data);
+
+ bool readByte(char& data) {
+ if (!isConnected()) {
+ return false;
+ }
+ int c = sock.readByte();
+ if (c < 0) {
+ return false;
+ }
+ data = static_cast<char>(c);
+ return true;
+ }
+
+ bool sendByte(const char data) {
+ if (!isConnected()) {
+ return false;
+ }
+ return sock.writeByte(data);
+ }
+
+ bool readStringLength(uint32_t& data);
+ bool readStringBytes(char* data, const uint32_t len);
+ bool readString(std::string& strRef);
+ bool sendString(const char* data, const uint32_t len) {
+ return sendInt(len) && sendBytes(data, len);
+ }
+
+ bool sendString(const std::string& str) {
+ return sendString(str.c_str(), static_cast<uint32_t>(str.length()));
+ }
+
+ bool readValue(Value& valueRef);
+ bool sendValue(const Value& value);
+
+ ReturnMessage* reactToMessages(SessionHandler* handler, bool expectReturn);
+
+ bool reactToMessages(SessionHandler* handler) {
+ return !reactToMessages(handler, false);
+ }
+
+ bool flush() {
+ return sock.flush();
+ }
+
+ ReturnMessage* reactToMessagesWhileWaitingForReturn(SessionHandler* handler) {
+ return reactToMessages(handler, true);
+ }
+};
+#endif
diff --git a/plugins/common/InvokeMessage.cpp b/plugins/common/InvokeMessage.cpp
new file mode 100644
index 0000000..90fc790
--- /dev/null
+++ b/plugins/common/InvokeMessage.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "InvokeMessage.h"
+#include "HostChannel.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+InvokeMessage::~InvokeMessage() {
+ delete[] args;
+}
+
+char InvokeMessage::getType() const {
+ return TYPE;
+}
+
+/**
+ * Receive an Invoke message from the channel (note that the message
+ * type has already been read). Caller is responsible for destroying
+ * returned message. Returns null on error.
+ */
+InvokeMessage* InvokeMessage::receive(HostChannel& channel) {
+ std::string methodName;
+ if (!channel.readString(methodName)) {
+ // TODO(jat): error handling
+ printf("Failed to read method name\n");
+ return 0;
+ }
+ Value thisRef;
+ if (!channel.readValue(thisRef)) {
+ // TODO(jat): error handling
+ printf("Failed to read thisRef\n");
+ return 0;
+ }
+ int numArgs;
+ if (!channel.readInt(numArgs)) {
+ // TODO(jat): error handling
+ printf("Failed to read #args\n");
+ return 0;
+ }
+ scoped_array<Value> args(new Value[numArgs]);
+ for (int i = 0; i < numArgs; ++i) {
+ if (!channel.readValue(args[i])) {
+ // TODO(jat): error handling
+ printf("Failed to read arg[%d]\n", i);
+ return 0;
+ }
+ }
+ return new InvokeMessage(thisRef, methodName, numArgs, args.release());
+}
+
+/**
+ * Request the server invoke a method on an object and return the result.
+ *
+ * Note that the method to be invoked is sent as an integer (a dispatch id) to the server.
+ */
+bool InvokeMessage::send(HostChannel& channel, const Value& thisRef, int methodDispatchId,
+ int numArgs, const Value* args) {
+ if (!channel.sendByte(TYPE)) return false;
+ if (!channel.sendInt(methodDispatchId)) return false;
+ if (!channel.sendValue(thisRef)) return false;
+ if (!channel.sendInt(numArgs)) return false;
+ for (int i = 0; i < numArgs; ++i) {
+ if (!channel.sendValue(args[i])) return false;
+ }
+ return true;
+}
diff --git a/plugins/common/InvokeMessage.h b/plugins/common/InvokeMessage.h
new file mode 100644
index 0000000..7d57e30
--- /dev/null
+++ b/plugins/common/InvokeMessage.h
@@ -0,0 +1,67 @@
+#ifndef __INVOKEMESSAGE_H
+#define __INVOKEMESSAGE_H
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+#include "Message.h"
+#include "BrowserChannel.h"
+#include "Value.h"
+
+class HostChannel;
+
+/**
+ * Class representing an InvokeMessage received from the server, and a way
+ * to send an invoke message to the server.
+ *
+ * Note that the wire protocol is different in the two directions, as the
+ * server sends a string for the method name and the client send an integer
+ * dispatchID.
+ */
+class InvokeMessage : public Message {
+public:
+ static const char TYPE = MESSAGE_TYPE_INVOKE;
+ static const int TOSTRING_DISP_ID = 0;
+private:
+ Value thisRef;
+ std::string methodName;
+ int methodDispatchId;
+ int numArgs;
+ const Value* args;
+
+protected:
+ /**
+ * @param args array of arguments -- InvokeMessage takes ownership and will
+ * destroy when it is destroyed.
+ */
+ InvokeMessage(const Value& thisRef, const std::string& methodName,
+ int numArgs, const Value* args) : thisRef(thisRef), methodName(methodName),
+ numArgs(numArgs), args(args) {}
+
+public:
+ ~InvokeMessage();
+ virtual char getType() const;
+
+ Value getThis() const { return thisRef; }
+ const std::string& getMethodName() const { return methodName; }
+ int getNumArgs() const { return numArgs; }
+ const Value* const getArgs() const { return args; }
+
+ static InvokeMessage* receive(HostChannel& channel);
+ static bool send(HostChannel& channel, const Value& thisRef, int methodDispatchId,
+ int numArgs, const Value* args);
+};
+#endif
diff --git a/plugins/common/InvokeSpecialMessage.cpp b/plugins/common/InvokeSpecialMessage.cpp
new file mode 100644
index 0000000..5fd1540
--- /dev/null
+++ b/plugins/common/InvokeSpecialMessage.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "InvokeSpecialMessage.h"
+#include "HostChannel.h"
+#include "SessionHandler.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+InvokeSpecialMessage::~InvokeSpecialMessage() {
+ delete[] args;
+}
+
+char InvokeSpecialMessage::getType() const {
+ return TYPE;
+}
+
+/**
+ * Receive an InvokeSpecial message from the channel (note that the message
+ * type has already been read). Caller is responsible for destroying
+ * returned message. Returns null on error.
+ */
+InvokeSpecialMessage* InvokeSpecialMessage::receive(HostChannel& channel) {
+ char dispatchId;
+ if (!channel.readByte(dispatchId)) {
+ // TODO(jat): error handling
+ printf("Failed to read method name\n");
+ return 0;
+ }
+ int numArgs;
+ if (!channel.readInt(numArgs)) {
+ // TODO(jat): error handling
+ printf("Failed to read #args\n");
+ return 0;
+ }
+ scoped_array<Value> args(new Value[numArgs]);
+ for (int i = 0; i < numArgs; ++i) {
+ if (!channel.readValue(args[i])) {
+ // TODO(jat): error handling
+ printf("Failed to read arg[%d]\n", i);
+ return 0;
+ }
+ }
+
+ SessionHandler::SpecialMethodId id =
+ static_cast<SessionHandler::SpecialMethodId>(dispatchId);
+ return new InvokeSpecialMessage(id, numArgs, args.release());
+}
+
+/**
+ * Request the server perform a special method and return the result.
+ */
+bool InvokeSpecialMessage::send(HostChannel& channel, int dispatchId,
+ int numArgs, const Value* args) {
+ if (!channel.sendByte(TYPE)) return false;
+ if (!channel.sendByte(dispatchId)) return false;
+ if (!channel.sendInt(numArgs)) return false;
+ for (int i = 0; i < numArgs; ++i) {
+ if (!channel.sendValue(args[i])) return false;
+ }
+ return true;
+}
diff --git a/plugins/common/InvokeSpecialMessage.h b/plugins/common/InvokeSpecialMessage.h
new file mode 100644
index 0000000..196baa5
--- /dev/null
+++ b/plugins/common/InvokeSpecialMessage.h
@@ -0,0 +1,59 @@
+#ifndef __INVOKESPECIALMESSAGE_H
+#define __INVOKESPECIALMESSAGE_H
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+#include "Message.h"
+#include "BrowserChannel.h"
+#include "SessionHandler.h"
+#include "Value.h"
+
+class HostChannel;
+
+/**
+ * Class representing an InvokeSpecialMessage received from the server, and a way
+ * to send an invoke message to the server.
+ */
+class InvokeSpecialMessage : public Message {
+public:
+ static const char TYPE = MESSAGE_TYPE_INVOKESPECIAL;
+private:
+ SessionHandler::SpecialMethodId dispatchId;
+ int numArgs;
+ const Value* args;
+
+protected:
+ /**
+ * @param args array of arguments -- InvokeMessage takes ownership and will
+ * destroy when it is destroyed.
+ */
+ InvokeSpecialMessage(SessionHandler::SpecialMethodId dispatchId, int numArgs, const Value* args) : dispatchId(dispatchId),
+ numArgs(numArgs), args(args) {}
+
+public:
+ ~InvokeSpecialMessage();
+ virtual char getType() const;
+
+ SessionHandler::SpecialMethodId getDispatchId() const { return dispatchId; }
+ int getNumArgs() const { return numArgs; }
+ const Value* const getArgs() const { return args; }
+
+ static InvokeSpecialMessage* receive(HostChannel& channel);
+ static bool send(HostChannel& channel, int dispatchId, int numArgs,
+ const Value* args);
+};
+#endif
diff --git a/plugins/common/LoadJsniMessage.cpp b/plugins/common/LoadJsniMessage.cpp
new file mode 100644
index 0000000..db8b943
--- /dev/null
+++ b/plugins/common/LoadJsniMessage.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "LoadJsniMessage.h"
+
+LoadJsniMessage* LoadJsniMessage::receive(HostChannel& channel) {
+ std::string js;
+ if (!channel.readString(js)) {
+ // TODO(jat): error handling
+ return 0;
+ }
+ return new LoadJsniMessage(js);
+}
diff --git a/plugins/common/LoadJsniMessage.h b/plugins/common/LoadJsniMessage.h
new file mode 100644
index 0000000..5b1f8d9
--- /dev/null
+++ b/plugins/common/LoadJsniMessage.h
@@ -0,0 +1,43 @@
+#ifndef __H_LoadJsniMessage
+#define __H_LoadJsniMessage
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+#include "Message.h"
+#include "BrowserChannel.h"
+#include "HostChannel.h"
+
+class LoadJsniMessage : public Message {
+public:
+ static const char TYPE = MESSAGE_TYPE_LOADJSNI;
+private:
+ const std::string js;
+
+ LoadJsniMessage(const std::string& js) : js(js) {}
+
+public:
+ virtual char getType() const {
+ return TYPE;
+ }
+
+ std::string getJs() const {
+ return js;
+ }
+
+ static LoadJsniMessage* receive(HostChannel& channel);
+};
+#endif
diff --git a/plugins/common/LoadModuleMessage.cpp b/plugins/common/LoadModuleMessage.cpp
new file mode 100644
index 0000000..a436961
--- /dev/null
+++ b/plugins/common/LoadModuleMessage.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Debug.h"
+
+#include <cstring>
+#include <string>
+
+#include "LoadModuleMessage.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+char LoadModuleMessage::getType() const {
+ return LoadModuleMessage::TYPE;
+}
+
+bool LoadModuleMessage::send(HostChannel& channel, uint32_t version, const char* moduleName,
+ const uint32_t moduleNameLen, const char* userAgent, SessionHandler* handler) {
+ Debug::log(Debug::Spam) << "LoadModule(module=\"" << moduleName << "\",vers="
+ << version << ")" << Debug::flush;
+ if (!channel.sendByte(TYPE) || !channel.sendInt(version)
+ || !channel.sendString(moduleName, moduleNameLen)
+ || !channel.sendString(userAgent, static_cast<uint32_t>(strlen(userAgent)))) {
+ return false;
+ }
+ scoped_ptr<ReturnMessage> ret(channel.reactToMessagesWhileWaitingForReturn(handler));
+ if (!ret.get()) {
+ return false;
+ }
+
+ return !ret.get()->isException();
+}
diff --git a/plugins/common/LoadModuleMessage.h b/plugins/common/LoadModuleMessage.h
new file mode 100644
index 0000000..3091c46
--- /dev/null
+++ b/plugins/common/LoadModuleMessage.h
@@ -0,0 +1,47 @@
+#ifndef __LOADMODULEMESSAGE_H
+#define __LOADMODULEMESSAGE_H
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+
+#include "Message.h"
+#include "BrowserChannel.h"
+#include "HostChannel.h"
+#include "SessionHandler.h"
+
+class HostChannel;
+
+class LoadModuleMessage : public Message {
+ static const char TYPE = MESSAGE_TYPE_LOAD_MODULE;
+
+public:
+ LoadModuleMessage(int version, std::string& moduleName, std::string& userAgent) :
+ version(version), moduleName(moduleName), userAgent(userAgent) { }
+
+ int getVersion() const { return version; }
+ const std::string& getModuleName() const { return moduleName; }
+ const std::string& getUserAgent() const { return userAgent; }
+ virtual char getType() const;
+
+ static bool send(HostChannel& channel, uint32_t version, const char* moduleName,
+ uint32_t moduleNameLen, const char* userAgent, SessionHandler* handler);
+private:
+ int version;
+ std::string moduleName;
+ std::string userAgent;
+};
+#endif
diff --git a/plugins/common/Makefile b/plugins/common/Makefile
new file mode 100644
index 0000000..b22fd27
--- /dev/null
+++ b/plugins/common/Makefile
@@ -0,0 +1,93 @@
+# Copyright 2009 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+include ../config.mk
+
+HDRS= HostChannel.h InvokeMessage.h LoadModuleMessage.h Message.h \
+ ReturnMessage.h Value.h BrowserChannel.h Debug.h DebugLevel.h \
+ SessionHandler.h ServerMethods.h Socket.h AllowedConnections.h \
+ LoadJsniMessage.h InvokeSpecialMessage.h FreeValueMessage.h \
+ ByteOrder.h
+
+SRCS= HostChannel.cpp LoadModuleMessage.cpp InvokeMessage.cpp \
+ ReturnMessage.cpp ServerMethods.cpp Debug.cpp Socket.cpp \
+ AllowedConnections.cpp LoadJsniMessage.cpp InvokeSpecialMessage.cpp \
+ FreeValueMessage.cpp
+
+LIBCOMMON= libcommon$(FLAG32BIT).a
+OBJDIR= obj$(FLAG32BIT)
+OBJS= $(patsubst %.cpp,$(OBJDIR)/%.o,$(SRCS))
+
+all:: $(OBJDIR) $(LIBCOMMON)
+
+$(OBJDIR):
+ -mkdir $@
+
+$(LIBCOMMON): $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+$(OBJDIR)/%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+.PHONY: clean depend testdebug
+
+testdebug:
+ (cd testing; CXX=$(CXX) CXXFLAGS="$(CFLAGS) -m32" ./testdebug)
+ (cd testing; CXX=$(CXX) CXXFLAGS="$(CFLAGS) -m64" ./testdebug)
+
+clean:
+ rm -rf obj32 obj64 libcommon32.a libcommon64.a
+
+depend:
+ g++ -MM $(CFLAGS) $(SRCS) >>Makefile
+# makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+HostChannel.o: HostChannel.cpp Debug.h Platform.h DebugLevel.h \
+ ByteOrder.h FreeValueMessage.h Message.h BrowserChannel.h HostChannel.h \
+ Socket.h AllowedConnections.h ReturnMessage.h Value.h SessionHandler.h \
+ LoadJsniMessage.h InvokeMessage.h InvokeSpecialMessage.h QuitMessage.h \
+ scoped_ptr/scoped_ptr.h
+LoadModuleMessage.o: LoadModuleMessage.cpp Debug.h Platform.h \
+ DebugLevel.h LoadModuleMessage.h Message.h BrowserChannel.h \
+ HostChannel.h ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h \
+ Value.h SessionHandler.h scoped_ptr/scoped_ptr.h
+InvokeMessage.o: InvokeMessage.cpp InvokeMessage.h Message.h \
+ BrowserChannel.h Value.h Debug.h Platform.h DebugLevel.h HostChannel.h \
+ ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h \
+ SessionHandler.h scoped_ptr/scoped_ptr.h
+ReturnMessage.o: ReturnMessage.cpp ReturnMessage.h Message.h \
+ BrowserChannel.h Value.h Debug.h Platform.h DebugLevel.h HostChannel.h \
+ ByteOrder.h Socket.h AllowedConnections.h SessionHandler.h
+ServerMethods.o: ServerMethods.cpp Debug.h Platform.h DebugLevel.h \
+ FreeValueMessage.h Message.h BrowserChannel.h HostChannel.h ByteOrder.h \
+ Socket.h AllowedConnections.h ReturnMessage.h Value.h SessionHandler.h \
+ InvokeMessage.h InvokeSpecialMessage.h ServerMethods.h \
+ scoped_ptr/scoped_ptr.h
+Debug.o: Debug.cpp Debug.h Platform.h DebugLevel.h
+Socket.o: Socket.cpp Platform.h Socket.h Debug.h DebugLevel.h
+AllowedConnections.o: AllowedConnections.cpp Debug.h Platform.h \
+ DebugLevel.h AllowedConnections.h
+LoadJsniMessage.o: LoadJsniMessage.cpp LoadJsniMessage.h Message.h \
+ BrowserChannel.h HostChannel.h Debug.h Platform.h DebugLevel.h \
+ ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h Value.h \
+ SessionHandler.h
+InvokeSpecialMessage.o: InvokeSpecialMessage.cpp InvokeSpecialMessage.h \
+ Message.h BrowserChannel.h SessionHandler.h Value.h Debug.h Platform.h \
+ DebugLevel.h HostChannel.h ByteOrder.h Socket.h AllowedConnections.h \
+ ReturnMessage.h scoped_ptr/scoped_ptr.h
+FreeValueMessage.o: FreeValueMessage.cpp FreeValueMessage.h Message.h \
+ BrowserChannel.h HostChannel.h Debug.h Platform.h DebugLevel.h \
+ ByteOrder.h Socket.h AllowedConnections.h ReturnMessage.h Value.h \
+ SessionHandler.h scoped_ptr/scoped_ptr.h
diff --git a/plugins/common/Makefile.sun b/plugins/common/Makefile.sun
new file mode 100644
index 0000000..2043187
--- /dev/null
+++ b/plugins/common/Makefile.sun
@@ -0,0 +1,115 @@
+# Set to classpath value to get GWT classes from
+#GWTDEV=../build/staging/gwt-linux-0.0.0/gwt-dev-linux.jar
+GWTDEV=../eclipse/dev/linux/bin
+
+INC=-I..
+#CFLAGS=-fast -g0 -Kpic $(INC) -Bdynamic -noex
+# SunC appears to miscompile Socket::writeByte by not incrementing the
+# buffer pointer, so no optimization for now
+#CFLAGS=-g -Kpic $(INC) -Bdynamic -noex
+CFLAGS=-g0 -Kpic -noex -xO1 -xlibmil -xlibmopt -features=tmplife -xbuiltin=%all -mt $(INC)
+CXXFLAGS=$(CFLAGS)
+CXX=CC
+
+HDRS= HostChannel.h InvokeMessage.h LoadModuleMessage.h Message.h \
+ ReturnMessage.h Value.h BrowserChannel.h Debug.h DebugLevel.h \
+ SessionHandler.h ServerMethods.h Socket.h AllowedConnections.h \
+ LoadJsniMessage.h InvokeSpecialMessage.h FreeValueMessage.h
+
+OBJS= HostChannel.o LoadModuleMessage.o InvokeMessage.o \
+ ReturnMessage.o ServerMethods.o Debug.o Socket.o \
+ AllowedConnections.o LoadJsniMessage.o InvokeSpecialMessage.o \
+ FreeValueMessage.o
+
+SRCS= HostChannel.cpp LoadModuleMessage.cpp InvokeMessage.cpp \
+ ReturnMessage.cpp ServerMethods.cpp Debug.cpp Socket.cpp \
+ AllowedConnections.cpp LoadJsniMessage.cpp InvokeSpecialMessage.cpp \
+ FreeValueMessage.cpp
+
+OBJ32= $(patsubst %.cpp,obj32/%.o,$(SRCS))
+OBJ64= $(patsubst %.cpp,obj64/%.o,$(SRCS))
+
+all:: libcommon32.a libcommon64.a
+
+libcommon32.a: $(OBJ32) obj32.dir
+ ar -rv $@ $(OBJ32)
+
+libcommon64.a: $(OBJ64) obj64.dir
+ ar -rv $@ $(OBJ64)
+
+obj32.dir:
+ -mkdir obj32
+ touch obj32.dir
+
+obj64.dir:
+ -mkdir obj64
+ touch obj64.dir
+
+obj32/%.o: %.cpp obj32.dir
+ $(CXX) $(CXXFLAGS) -m32 -c $< -o $@
+
+obj64/%.o: %.cpp obj64.dir
+ $(CXX) $(CXXFLAGS) -m64 -c $< -o $@
+
+.PHONY: all clean depend
+
+clean:
+ -rm $(OBJ32) $(OBJ64) libcommon32.a libcommon64.a
+
+depend:
+ $(CXX) -xMMF $(CFLAGS) $(SRCS) >>Makefile.sun
+# makedepend -- $(CFLAGS) -- $(SRCS)
+
+# DO NOT DELETE
+obj32/HostChannel.o obj64/HostChannel.o: Makefile.sun \
+ HostChannel.cpp HostChannel.h Platform.h Message.h \
+ ReturnMessage.h BrowserChannel.h Value.h SessionHandler.h \
+ InvokeMessage.h QuitMessage.h scoped_ptr/scoped_ptr.h
+obj32/LoadModuleMessage.o obj64/LoadModuleMessage.o: Makefile.sun \
+ LoadModuleMessage.cpp LoadModuleMessage.h Message.h \
+ BrowserChannel.h HostChannel.h Platform.h ReturnMessage.h Value.h \
+ SessionHandler.h scoped_ptr/scoped_ptr.h
+obj32/InvokeMessage.o obj64/InvokeMessage.o: Makefile.sun \
+ InvokeMessage.cpp InvokeMessage.h Message.h \
+ BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+ SessionHandler.h
+obj32/ReturnMessage.o obj64/ReturnMessage.o: Makefile.sun \
+ ReturnMessage.cpp ReturnMessage.h Message.h \
+ BrowserChannel.h Value.h HostChannel.h Platform.h SessionHandler.h
+obj32/ServerMethods.o obj64/ServerMethods.o: Makefile.sun \
+ ServerMethods.cpp ServerMethods.h Value.h \
+ BrowserChannel.h HostChannel.h Platform.h Message.h ReturnMessage.h \
+ SessionHandler.h InvokeMessage.h scoped_ptr/scoped_ptr.h
+obj32/HostChannel.o obj64/HostChannel.o: Makefile.sun \
+ HostChannel.cpp HostChannel.h Platform.h Message.h \
+ ReturnMessage.h BrowserChannel.h Value.h SessionHandler.h \
+ InvokeMessage.h QuitMessage.h scoped_ptr/scoped_ptr.h
+obj32/LoadModuleMessage.o obj64/LoadModuleMessage.o: Makefile.sun \
+ LoadModuleMessage.cpp LoadModuleMessage.h Message.h \
+ BrowserChannel.h HostChannel.h Platform.h ReturnMessage.h Value.h \
+ SessionHandler.h scoped_ptr/scoped_ptr.h
+obj32/InvokeMessage.o obj64/InvokeMessage.o: Makefile.sun \
+ InvokeMessage.cpp InvokeMessage.h Message.h \
+ BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+ SessionHandler.h
+obj32/InvokeSpecialMessage.o obj64/InvokeSpecialMessage.o: Makefile.sun \
+ InvokeSpecialMessage.cpp InvokeSpecialMessage.h Message.h \
+ BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+ SessionHandler.h
+obj32/FreeValueMesssage.o obj64/FreeValueMesssage.o: Makefile.sun \
+ FreeValueMesssage.cpp FreeValueMesssage.h Message.h \
+ BrowserChannel.h Value.h HostChannel.h Platform.h ReturnMessage.h \
+ SessionHandler.h
+obj32/ReturnMessage.o obj64/ReturnMessage.o: Makefile.sun \
+ ReturnMessage.cpp ReturnMessage.h Message.h \
+ BrowserChannel.h Value.h HostChannel.h Platform.h SessionHandler.h
+obj32/ServerMethods.o obj64/ServerMethods.o: Makefile.sun \
+ ServerMethods.cpp ServerMethods.h Value.h \
+ BrowserChannel.h HostChannel.h Platform.h Message.h ReturnMessage.h \
+ SessionHandler.h InvokeMessage.h scoped_ptr/scoped_ptr.h
+obj32/Debug.o obj64/Debug.o: Makefile.sun \
+ Debug.cpp Debug.h DebugLevel.h
+obj32/Socket.o obj64/Socket.o: Makefile.sun \
+ Socket.cpp Socket.h Debug.h DebugLevel.h
+obj32/AllowedConnections.o obj64/AllowedConnections.o: Makefile.sun \
+ AllowedConnections.cpp AllowedConnections.h Debug.h DebugLevel.h
diff --git a/plugins/common/Message.h b/plugins/common/Message.h
new file mode 100644
index 0000000..a244e0b
--- /dev/null
+++ b/plugins/common/Message.h
@@ -0,0 +1,28 @@
+#ifndef __MESSAGE_H
+#define __MESSAGE_H
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+class Message {
+public:
+ virtual char getType() const = 0;
+ virtual bool isAsynchronous() const {
+ return false;
+ }
+ virtual ~Message() {}
+};
+
+#endif
diff --git a/plugins/common/Platform.h b/plugins/common/Platform.h
new file mode 100644
index 0000000..bbc0334
--- /dev/null
+++ b/plugins/common/Platform.h
@@ -0,0 +1,46 @@
+#ifndef _H_Platform
+#define _H_Platform
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+// Platform-specific hacks to enable more shared code elsewhere
+#ifdef _WINDOWS
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+typedef long ssize_t;
+
+#define snprintf sprintf_s
+#define SOCKETTYPE SOCKET
+// Bogus conversion from size_t -> unsigned int warnings.
+#pragma warning(disable:4267)
+#else
+#define SOCKETTYPE int
+#endif
+
+// Set the float byte-order if we know it -- see ByteOrder.h FloatByteOrder
+#if defined(i386) || defined(i586) || defined(i686) || defined(_x86)
+#define PLATFORM_FLOAT_ENDIANESS FLOAT_LITTLE_ENDIAN
+#endif
+
+#if defined(__sparc)
+#define PLATFORM_FLOAT_ENDIANESS FLOAT_BIG_ENDIAN
+#endif
+
+#endif
diff --git a/plugins/common/QuitMessage.h b/plugins/common/QuitMessage.h
new file mode 100644
index 0000000..344612f
--- /dev/null
+++ b/plugins/common/QuitMessage.h
@@ -0,0 +1,38 @@
+#ifndef __H_QuitMessage
+#define __H_QuitMessage
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+#include "Message.h"
+#include "BrowserChannel.h"
+
+class QuitMessage : public Message {
+public:
+ static const char TYPE = MESSAGE_TYPE_QUIT;
+private:
+ QuitMessage() {}
+
+public:
+ virtual char getType() const {
+ return TYPE;
+ }
+
+ static bool send(HostChannel& channel) {
+ return channel.sendByte(TYPE);
+ }
+};
+#endif
diff --git a/plugins/common/ReturnMessage.cpp b/plugins/common/ReturnMessage.cpp
new file mode 100644
index 0000000..0149c1f
--- /dev/null
+++ b/plugins/common/ReturnMessage.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "ReturnMessage.h"
+#include "HostChannel.h"
+
+char ReturnMessage::getType() const {
+ return TYPE;
+}
+
+ReturnMessage* ReturnMessage::receive(HostChannel& channel) {
+ char isException;
+ if (!channel.readByte(isException)) {
+ // TODO(jat): error handling
+ return 0;
+ }
+ Value retval;
+ if (!channel.readValue(retval)) {
+ // TODO(jat): error handling
+ return 0;
+ }
+ return new ReturnMessage(isException != 0, retval);
+}
+
+bool ReturnMessage::send(HostChannel& channel, bool isException, const Value& retval) {
+ if (!channel.sendByte(TYPE)) return false;
+ if (!channel.sendByte(isException ? 1 : 0)) return false;
+ return channel.sendValue(retval);
+}
diff --git a/plugins/common/ReturnMessage.h b/plugins/common/ReturnMessage.h
new file mode 100644
index 0000000..fddf9ec
--- /dev/null
+++ b/plugins/common/ReturnMessage.h
@@ -0,0 +1,43 @@
+#ifndef __RETURNMESSAGE_H
+#define __RETURNMESSAGE_H
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+#include "Message.h"
+#include "BrowserChannel.h"
+#include "Value.h"
+
+class HostChannel;
+
+class ReturnMessage : public Message {
+ static const char TYPE = MESSAGE_TYPE_RETURN;
+private:
+ bool bisException;
+ Value retval;
+
+public:
+ ReturnMessage(bool isException, const Value& retValue) : bisException(isException),
+ retval(retValue) {}
+
+ bool isException() const { return bisException; }
+ const Value& getReturnValue() const { return retval; }
+ virtual char getType() const;
+
+ static ReturnMessage* receive(HostChannel& channel);
+ static bool send(HostChannel& channel, bool isException, const Value& retValue);
+};
+#endif
diff --git a/plugins/common/ServerMethods.cpp b/plugins/common/ServerMethods.cpp
new file mode 100644
index 0000000..5a18bcb
--- /dev/null
+++ b/plugins/common/ServerMethods.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include <string>
+
+#include "Debug.h"
+#include "FreeValueMessage.h"
+#include "HostChannel.h"
+#include "InvokeMessage.h"
+#include "InvokeSpecialMessage.h"
+#include "ReturnMessage.h"
+#include "ServerMethods.h"
+#include "scoped_ptr/scoped_ptr.h"
+
+using std::string;
+
+Value ServerMethods::getProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+ int dispatchId) {
+ Value args[2];
+ args[0].setInt(objectRef);
+ args[1].setInt(dispatchId);
+ if (!InvokeSpecialMessage::send(channel, SPECIAL_GET_PROPERTY, 2, args)) {
+ Debug::log(Debug::Error) << " failed to send invoke of GetProperty(disp=" << dispatchId
+ << ", obj=" << objectRef << ")" << Debug::flush;
+ return Value();
+ }
+ scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+ if (!retMsg.get()) {
+ Debug::log(Debug::Error) << "getProperty: get return value failed for GetProperty(disp="
+ << dispatchId << ", obj=" << objectRef << ")" << Debug::flush;
+ return Value();
+ }
+ return retMsg->getReturnValue();
+}
+
+int ServerMethods::hasMethod(HostChannel& channel, SessionHandler* handler, int classId,
+ const std::string& name) {
+ if (name != "toString" && name.find("::") == string::npos) {
+ // only JSNI-style names and toString are valid
+ return -1;
+ }
+ Value arg;
+ arg.setString(name);
+ if (!InvokeSpecialMessage::send(channel, SPECIAL_HAS_METHOD, 1, &arg)) {
+ Debug::log(Debug::Error) << "hasMethod: invoke(hasMethod) failed" << Debug::flush;
+ return -2;
+ }
+ scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+ if (!retMsg.get()) {
+ Debug::log(Debug::Error) << "hasMethod: get return value failed" << Debug::flush;
+ return -2;
+ }
+ Value retval = retMsg->getReturnValue();
+ // TODO(jat): better error handling?
+ return retval.isInt() ? retval.getInt() : -2;
+}
+
+int ServerMethods::hasProperty(HostChannel& channel, SessionHandler* handler, int classId,
+ const std::string& name) {
+ if (name != "toString" && name.find("::") == string::npos) {
+ // only JSNI-style names and toString are valid
+ return -1;
+ }
+ Value arg;
+ arg.setString(name);
+ if (!InvokeSpecialMessage::send(channel, SPECIAL_HAS_PROPERTY, 1, &arg)) {
+ Debug::log(Debug::Error) << "hasProperty: invoke(hasProperty) failed" << Debug::flush;
+ return -2;
+ }
+ scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+ if (!retMsg.get()) {
+ Debug::log(Debug::Error) << "hasProperty: get return value failed" << Debug::flush;
+ return -2;
+ }
+ Value retval = retMsg->getReturnValue();
+ // TODO(jat): better error handling?
+ return retval.isInt() ? retval.getInt() : -2;
+}
+
+bool ServerMethods::setProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+ int dispatchId, const Value& value) {
+ // TODO(jat): error handling?
+ Value args[3];
+ args[0].setInt(objectRef);
+ args[1].setInt(dispatchId);
+ args[2] = value;
+ if (!InvokeSpecialMessage::send(channel, SPECIAL_SET_PROPERTY, 3, args)) {
+ Debug::log(Debug::Error) << " failed to send invoke of SetProperty(disp=" << dispatchId
+ << ", obj=" << objectRef << ")" << Debug::flush;
+ return false;
+ }
+ scoped_ptr<ReturnMessage> retMsg(channel.reactToMessagesWhileWaitingForReturn(handler));
+ if (!retMsg.get()) {
+ Debug::log(Debug::Error) << "setProperty: get return value failed for SetProperty(disp="
+ << dispatchId << ", obj=" << objectRef << ")" << Debug::flush;
+ return false;
+ }
+ // TODO: use the returned exception?
+ return !retMsg.get()->isException();
+}
+
+bool ServerMethods::freeJava(HostChannel& channel, SessionHandler* handler, int idCount,
+ const int* ids) {
+ // If we are disconnected, assume the server will free all of these anyway.
+ // This deals with the problem of getting finalizers called after the channel is dropped.
+ if (!channel.isConnected()) {
+ Debug::log(Debug::Debugging) << "Ignoring freeJava after disconnect"
+ << Debug::flush;
+ return true;
+ }
+ if (!FreeValueMessage::send(channel, idCount, ids)) {
+ Debug::log(Debug::Error) << " failed to send FreeValues message" << Debug::flush;
+ return false;
+ }
+ return true;
+}
diff --git a/plugins/common/ServerMethods.h b/plugins/common/ServerMethods.h
new file mode 100644
index 0000000..3ff0134
--- /dev/null
+++ b/plugins/common/ServerMethods.h
@@ -0,0 +1,78 @@
+#ifndef _H_ServerMethods
+#define _H_ServerMethods
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Value.h"
+
+class HostChannel;
+class SessionHandler;
+
+/**
+ * Encapsulates the methods defined on the special server object.
+ */
+class ServerMethods {
+public:
+ /**
+ * Get the value of a property on an object.
+ *
+ * @param objectRef ID of object to fetch field on
+ * @param dispatchID dispatch ID of field
+ * @return the value of the property, undef if none (or on error)
+ */
+ static Value getProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+ int dispatchId);
+
+ /**
+ * Lookup the named method on the specified class.
+ *
+ * @return the dispatch ID (non-negative) of the method if present, or -1 if not.
+ * If an error is encountered, -2 is returned.
+ */
+ static int hasMethod(HostChannel& channel, SessionHandler* handler, int classId,
+ const std::string& name);
+
+ /**
+ * Lookup the named property on the specified class.
+ *
+ * @return the dispatch ID (non-negative) of the property if present, or -1 if not.
+ * If an error is encountered, -2 is returned.
+ */
+ static int hasProperty(HostChannel& channel, SessionHandler* handler, int classId,
+ const std::string& name);
+
+ /**
+ * Set the value of a property on an object.
+ *
+ * @param objectRef ID of object to fetch field on
+ * @param dispatchID dispatch ID of field
+ * @param value value to store in the property
+ * @return false if an error occurred
+ */
+ static bool setProperty(HostChannel& channel, SessionHandler* handler, int objectRef,
+ int dispatchId, const Value& value);
+
+ /**
+ * Tell the server that the client no longer has any references to the specified
+ * Java object.
+ *
+ * @param objcetRef ID of object to free
+ * @return false if an error occurred
+ */
+ static bool freeJava(HostChannel& channel, SessionHandler* handler, int idCount, const int* ids);
+};
+
+#endif
diff --git a/plugins/common/SessionHandler.h b/plugins/common/SessionHandler.h
new file mode 100644
index 0000000..217dce4
--- /dev/null
+++ b/plugins/common/SessionHandler.h
@@ -0,0 +1,82 @@
+#ifndef _H_SessionHandler
+#define _H_SessionHandler
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "BrowserChannel.h"
+#include "Value.h"
+
+class HostChannel;
+
+/**
+ * Interface for session-handling needs.
+ *
+ * Note that if this is being "added" onto a class which extends a C structure, the inheritance
+ * chain leading to the plain C object must be first in the inheritance list.
+ *
+ * For example:
+ *
+ * extern "C" {
+ * typedef struct PlainCstruct {
+ * ... data only members here
+ * } PlainCstruct;
+ * };
+ *
+ * class MyWrapper: public PlainCstruct, SessionHandler {
+ * ... virtual functions ok here
+ * };
+ */
+class SessionHandler {
+ friend class HostChannel;
+public:
+ enum SpecialMethodId {
+ HasMethod = SPECIAL_HAS_METHOD,
+ HasProperty = SPECIAL_HAS_PROPERTY,
+ GetProperty = SPECIAL_GET_PROPERTY,
+ SetProperty = SPECIAL_SET_PROPERTY
+ };
+protected:
+ virtual void freeValue(HostChannel& channel, int idCount, const int* ids) = 0;
+
+ virtual void loadJsni(HostChannel& channel, const std::string& js) = 0;
+
+ /**
+ * Does not own any of its args -- must copy them if it wants them and should not free the
+ * ones passed in.
+ *
+ * Returns true if an exception occurred.
+ */
+ virtual bool invoke(HostChannel& channel, const Value& thisObj, const std::string& methodName,
+ int numArgs, const Value* const args, Value* returnValue)=0;
+
+ /**
+ * Invoke a plugin-provided method with the given args. As above, this method does not own
+ * any of its args.
+ *
+ * Returns true if an exception occurred.
+ */
+ virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+ const Value* const args, Value* returnValue) = 0;
+
+ /**
+ * Send any queued up free values back to the server.
+ */
+ virtual void sendFreeValues(HostChannel& channel) = 0;
+
+ virtual ~SessionHandler() {}
+};
+
+#endif
diff --git a/plugins/common/Socket.cpp b/plugins/common/Socket.cpp
new file mode 100644
index 0000000..0d6fae5
--- /dev/null
+++ b/plugins/common/Socket.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Platform.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+#include "Socket.h"
+
+void Socket::init() {
+#ifdef _WINDOWS
+ // version 2.2 supported on Win95OSR2/WinNT4 and up
+ WORD winsockVers = MAKEWORD(2, 2);
+ WSADATA wsaData;
+ int err = WSAStartup(winsockVers, &wsaData);
+ if (err) {
+ // TODO(jat): report error
+ Debug::log(Debug::Error) << "WSAStartup(vers=2.2): err=" << err << Debug::flush;
+ }
+#endif
+}
+
+bool Socket::connect(const char* host, int port) {
+ Debug::log(Debug::Debugging) << "Socket::connect(host=" << host << ",port=" << port << ")"
+ << Debug::flush;
+ if (isConnected()) {
+ Debug::log(Debug::Error) << "Socket::connect - already connected" << Debug::flush;
+ return false;
+ }
+
+ SOCKETTYPE fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0) {
+ Debug::log(Debug::Error) << "Socket::connect - can't get socket" << Debug::flush;
+ return false;
+ }
+#ifdef SO_NOSIGPIPE
+ // On BSD, we need to suppress the SIGPIPE if the remote end disconnects.
+ int option_value = 1;
+ if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &option_value, sizeof(int))) {
+ Debug::log(Debug::Error) << "Socket::connect - can't set NOSIGPIPE option" << Debug::flush;
+ return false;
+ }
+#endif
+
+ struct sockaddr_in sockAddr;
+ memset(&sockAddr, 0, static_cast<int>(sizeof(sockAddr)));
+ // check for numeric IP4 addresses first
+ // TODO(jat): handle IPv6 addresses
+ unsigned long numericAddr = inet_addr(host);
+ if (numericAddr != 0xFFFFFFFF) {
+ sockAddr.sin_addr.s_addr = numericAddr;
+ sockAddr.sin_family = AF_INET;
+ } else {
+ struct hostent* hent = gethostbyname(host);
+ if (!hent || !hent->h_addr_list[0]) {
+ Debug::log(Debug::Error) << "Unable to get address for " << host << Debug::flush;
+ return false;
+ }
+ memcpy(&(sockAddr.sin_addr), hent->h_addr_list[0], hent->h_length);
+ sockAddr.sin_family = hent->h_addrtype;
+ }
+ sockAddr.sin_port = htons(port);
+
+ if (::connect(fd, (struct sockaddr*) &sockAddr, sizeof(sockAddr)) < 0) {
+#ifdef _WINDOWS
+ char buf[256];
+ strerror_s(buf, sizeof(buf), errno);
+ Debug::log(Debug::Error) << "Can't connect to " << host << ":" << port << " -- "
+ << buf << Debug::flush;
+ closesocket(fd);
+#else
+ Debug::log(Debug::Error) << "Can't connect to " << host << ":" << port << " -- "
+ << strerror(errno) << Debug::flush;
+ close(fd);
+#endif
+ return false;
+ }
+ sock = fd;
+ connected = true;
+ readBufPtr = readValid = readBuf;
+ writeBufPtr = writeBuf;
+#ifdef _WINDOWS
+ Debug::log(Debug::Spam) << " connected" << Debug::flush;
+#else
+ Debug::log(Debug::Spam) << " connected, fd=" << fd << Debug::flush;
+#endif
+ return true;
+}
+
+bool Socket::disconnect(bool doFlush) {
+ if (connected) {
+ Debug::log(Debug::Debugging) << "Disconnecting socket" << Debug::flush;
+ if (doFlush) {
+ flush();
+ }
+ connected = false;
+#ifdef _WINDOWS
+ closesocket(sock);
+#else
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+#endif
+ }
+ return true;
+}
+
+bool Socket::emptyWriteBuf() {
+ size_t len = writeBufPtr - writeBuf;
+ Debug::log(Debug::Spam) << "Socket::emptyWriteBuf: len=" << len << Debug::flush;
+ ++numWrites;
+ totWriteBytes += len;
+ if (len > maxWriteBytes) {
+ maxWriteBytes = len;
+ }
+ for (char* ptr = writeBuf; len > 0; ) {
+ ssize_t n = send(sock, ptr, len, 0);
+ if (n <= 0) {
+ if (errno == EPIPE) {
+ Debug::log(Debug::Warning) << "Other end of socket disconnected" << Debug::flush;
+ disconnect(false);
+ return false;
+ }
+ Debug::log(Debug::Error) << "Error " << errno << " writing " << len << " bytes to socket"
+ << Debug::flush;
+ return false;
+ }
+ ptr += n;
+ len -= n;
+ }
+ writeBufPtr = writeBuf;
+ return true;
+}
+
+bool Socket::fillReadBuf() {
+ readBufPtr = readBuf;
+ errno = 0;
+ ssize_t n = recv(sock, readBuf, BUF_SIZE, 0);
+ if (n <= 0) {
+ // EOF results in no error
+ if (!errno || errno == EPIPE) {
+ Debug::log(Debug::Warning) << "Other end of socket disconnected" << Debug::flush;
+ disconnect(false);
+ return false;
+ }
+ Debug::log(Debug::Error) << "Error " << errno << " reading " << BUF_SIZE << " bytes from socket"
+ << Debug::flush;
+ return false;
+ }
+ ++numReads;
+ totReadBytes += n;
+ if (static_cast<size_t>(n) > maxReadBytes) {
+ maxReadBytes = n;
+ }
+ readValid = readBuf + n;
+ return true;
+}
diff --git a/plugins/common/Socket.h b/plugins/common/Socket.h
new file mode 100644
index 0000000..90298f6
--- /dev/null
+++ b/plugins/common/Socket.h
@@ -0,0 +1,170 @@
+#ifndef _H_Socket
+#define _H_Socket
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Platform.h"
+#include "Debug.h"
+
+#include <string>
+
+#ifdef _WINDOWS
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+/**
+ * Encapsulates platform dependencies regarding buffered sockets.
+ */
+class Socket {
+private:
+ // Buffer size, chosen to fit in a single packet after TCP/IP overhead.
+ static const int BUF_SIZE = 1400;
+
+ // Can't rely on a sentinel value for the socket descriptor
+ bool connected;
+
+ SOCKETTYPE sock;
+
+ // Read buffer
+ char* readBuf;
+
+ // One bye past end of valid data in readBuf
+ char* readValid;
+
+ // Current read pointer
+ char* readBufPtr;
+
+ // Write buffer
+ char* writeBuf;
+
+ // Current write pointer
+ char* writeBufPtr;
+
+ // Stats
+ unsigned long numReads;
+ unsigned long long totReadBytes;
+ size_t maxReadBytes;
+
+ unsigned long numWrites;
+ unsigned long long totWriteBytes;
+ size_t maxWriteBytes;
+
+private:
+ void init();
+ bool fillReadBuf();
+ bool emptyWriteBuf();
+
+public:
+ Socket() : connected(false), readBuf(new char[BUF_SIZE]), writeBuf(new char[BUF_SIZE]) {
+ readBufPtr = readValid = readBuf;
+ writeBufPtr = writeBuf;
+ numReads = numWrites = 0;
+ maxReadBytes = maxWriteBytes = 0;
+ totReadBytes = totWriteBytes = 0;
+ init();
+ }
+
+ ~Socket() {
+ disconnect();
+#ifdef _WINDOWS
+ if (0) WSACleanup();
+#endif
+ // TODO(jat): LEAK LEAK LEAK
+ // delete[] readBuf;
+ // delete[] writeBuf;
+ Debug::log(Debug::Debugging) << "Socket: #r=" << numReads << ", bytes/read="
+ << (numReads ? totReadBytes / numReads : 0) << ", maxr=" << maxReadBytes << "; #w="
+ << numWrites << ", bytes/write=" << (numWrites ? totWriteBytes / numWrites : 0) << ", maxw="
+ << maxWriteBytes << Debug::flush;
+ }
+
+ /**
+ * Connects this socket to a specified port on a host.
+ *
+ * @param host host name or IP address to connect to
+ * @param port TCP port to connect to
+ * @return true if the connection succeeds
+ */
+ bool connect(const char* host, int port);
+
+ /**
+ * Returns true if the socket is connected.
+ */
+ bool isConnected() const {
+ return connected;
+ }
+
+ /**
+ * Disconnect this socket.
+ *
+ * @param doFlush true (the default value) if the socket should be flushed.
+ * @return true if disconnect succeeds
+ */
+ bool disconnect(bool doFlush = true);
+
+ /**
+ * Read a single byte from the socket.
+ *
+ * @return -1 on error, otherwise unsigned byte read.
+ */
+ int readByte() {
+ if (readBufPtr >= readValid) {
+ if (!fillReadBuf()) {
+ return -1;
+ }
+ }
+ return static_cast<unsigned char>(*readBufPtr++);
+ }
+
+ /**
+ * Write a single byte to the socket.
+ *
+ * @return true on success.
+ */
+ bool writeByte(char c) {
+ if (writeBufPtr >= writeBuf + BUF_SIZE) {
+ if (!emptyWriteBuf()) {
+ return false;
+ }
+ }
+ *writeBufPtr++ = c;
+ return true;
+ }
+
+ /**
+ * Flush any pending writes on the socket.
+ *
+ * @return true on success
+ */
+ bool flush() {
+ if (writeBufPtr > writeBuf) {
+ if (!emptyWriteBuf()) {
+ return false;
+ }
+ }
+ return true;
+ }
+};
+
+#endif
diff --git a/plugins/common/Value.h b/plugins/common/Value.h
new file mode 100644
index 0000000..4401893
--- /dev/null
+++ b/plugins/common/Value.h
@@ -0,0 +1,387 @@
+#ifndef _H_Value
+#define _H_Value
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#ifndef _WINDOWS
+// TODO(jat): remove; for abort() which should probably go away
+#include <stdlib.h>
+#endif
+
+#include <string>
+
+#include "Debug.h"
+
+#include "BrowserChannel.h"
+
+class Value {
+public:
+ enum ValueType {
+ NULL_TYPE = VALUE_TYPE_NULL,
+ BOOLEAN = VALUE_TYPE_BOOLEAN,
+ BYTE = VALUE_TYPE_BYTE,
+ CHAR = VALUE_TYPE_CHAR,
+ SHORT = VALUE_TYPE_SHORT,
+ INT = VALUE_TYPE_INT,
+ LONG = VALUE_TYPE_LONG,
+ FLOAT = VALUE_TYPE_FLOAT,
+ DOUBLE = VALUE_TYPE_DOUBLE,
+ STRING = VALUE_TYPE_STRING,
+ JAVA_OBJECT = VALUE_TYPE_JAVA_OBJECT,
+ JS_OBJECT = VALUE_TYPE_JS_OBJECT,
+ UNDEFINED = VALUE_TYPE_UNDEFINED
+ };
+
+private:
+ ValueType type;
+ union {
+ bool boolValue;
+ unsigned char byteValue;
+ unsigned short charValue;
+ double doubleValue;
+ float floatValue;
+ int32_t intValue;
+ int64_t longValue;
+ short shortValue;
+ std::string* stringValue;
+ } value;
+
+public:
+ Value() {
+ type = UNDEFINED;
+ }
+
+ Value(const Value& other) {
+ copyValue(other);
+ }
+
+ Value& operator=(const Value& other) {
+ clearOldValue();
+ copyValue(other);
+ return *this;
+ }
+
+ ~Value() {
+ clearOldValue();
+ }
+
+ bool getBoolean() const {
+ assertType(BOOLEAN);
+ return value.boolValue;
+ }
+
+ unsigned char getByte() const {
+ assertType(BYTE);
+ return value.byteValue;
+ }
+
+ unsigned short getChar() const {
+ assertType(CHAR);
+ return value.charValue;
+ }
+
+ double getDouble() const {
+ assertType(DOUBLE);
+ return value.doubleValue;
+ }
+
+ float getFloat() const {
+ assertType(FLOAT);
+ return value.floatValue;
+ }
+
+ int getInt() const {
+ assertType(INT);
+ return value.intValue;
+ }
+
+ int getJavaObjectId() const {
+ assertType(JAVA_OBJECT);
+ return value.intValue;
+ }
+
+ int getJsObjectId() const {
+ assertType(JS_OBJECT);
+ return value.intValue;
+ }
+
+ int64_t getLong() const {
+ assertType(LONG);
+ return value.longValue;
+ }
+
+ short getShort() const {
+ assertType(SHORT);
+ return value.shortValue;
+ }
+
+ const std::string getString() const {
+ assertType(STRING);
+ return std::string(*value.stringValue);
+ }
+
+ ValueType getType() const {
+ return type;
+ }
+
+ bool isBoolean() const {
+ return type == BOOLEAN;
+ }
+
+ bool isByte() const {
+ return type == BYTE;
+ }
+
+ bool isChar() const {
+ return type == CHAR;
+ }
+
+ bool isDouble() const {
+ return type == DOUBLE;
+ }
+
+ bool isFloat() const {
+ return type == FLOAT;
+ }
+
+ bool isInt() const {
+ return type == INT;
+ }
+
+ bool isJavaObject() const {
+ return type == JAVA_OBJECT;
+ }
+
+ bool isJsObject() const {
+ return type == JS_OBJECT;
+ }
+
+ bool isLong() const {
+ return type == LONG;
+ }
+
+ bool isNull() const {
+ return type == NULL_TYPE;
+ }
+
+ bool isNumber() const {
+ switch (type) {
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isPrimitive() const {
+ switch (type) {
+ case BOOLEAN:
+ case BYTE:
+ case CHAR:
+ case DOUBLE:
+ case FLOAT:
+ case INT:
+ case LONG:
+ case SHORT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isShort() const {
+ return type == SHORT;
+ }
+
+ bool isString() const {
+ return type == STRING;
+ }
+
+ bool isUndefined() const {
+ return type == UNDEFINED;
+ }
+
+ void setBoolean(bool val) {
+ clearOldValue();
+ type = BOOLEAN;
+ value.boolValue = val;
+ }
+
+ void setByte(unsigned char val) {
+ clearOldValue();
+ type = BYTE;
+ value.byteValue = val;
+ }
+
+ void setChar(unsigned short val) {
+ clearOldValue();
+ type = CHAR;
+ value.charValue = val;
+ }
+
+ void setDouble(double val) {
+ clearOldValue();
+ type = DOUBLE;
+ value.doubleValue = val;
+ }
+
+ void setFloat(float val) {
+ clearOldValue();
+ type = FLOAT;
+ value.floatValue = val;
+ }
+
+ void setInt(int val) {
+ clearOldValue();
+ type = INT;
+ value.intValue = val;
+ }
+
+ void setJavaObject(int objectId) {
+ clearOldValue();
+ type = JAVA_OBJECT;
+ value.intValue = objectId;
+ }
+
+ void setJsObjectId(int val) {
+ clearOldValue();
+ type = JS_OBJECT;
+ value.intValue = val;
+ }
+
+ void setLong(int64_t val) {
+ clearOldValue();
+ type = LONG;
+ value.longValue = val;
+ }
+
+ void setNull() {
+ clearOldValue();
+ type = NULL_TYPE;
+ }
+
+ void setShort(short val) {
+ clearOldValue();
+ type = SHORT;
+ value.shortValue = val;
+ }
+
+ void setString(const char* chars, int len) {
+ setString(std::string(chars, len));
+ }
+
+ void setString(const std::string& val) {
+ clearOldValue();
+ type = STRING;
+ value.stringValue = new std::string(val);
+ }
+
+ void setUndefined() {
+ clearOldValue();
+ type = UNDEFINED;
+ }
+
+ std::string toString() const {
+ char buf[30];
+ switch (type) {
+ case NULL_TYPE:
+ return "null";
+ case BOOLEAN:
+ snprintf(buf, sizeof(buf), "boolean(%s)", getBoolean() ? "true"
+ : "false");
+ return std::string(buf);
+ case BYTE:
+ snprintf(buf, sizeof(buf), "byte(%d)", getByte());
+ return std::string(buf);
+ case CHAR:
+ snprintf(buf, sizeof(buf), "char(%d)", getChar());
+ return std::string(buf);
+ case SHORT:
+ snprintf(buf, sizeof(buf), "short(%d)", getShort());
+ return std::string(buf);
+ case INT:
+ snprintf(buf, sizeof(buf), "int(%d)", getInt());
+ return std::string(buf);
+ case LONG:
+ snprintf(buf, sizeof(buf), "long(%lld)",
+ static_cast<long long>(getLong()));
+ return std::string(buf);
+ case FLOAT:
+ snprintf(buf, sizeof(buf), "float(%f)", getFloat());
+ return std::string(buf);
+ case DOUBLE:
+ snprintf(buf, sizeof(buf), "double(%lf)", getDouble());
+ return std::string(buf);
+ case STRING:
+ snprintf(buf, sizeof(buf), "string(%.20s)", getString().c_str());
+ return std::string(buf);
+ case JAVA_OBJECT:
+ snprintf(buf, sizeof(buf), "JavaObj(%d)", getJavaObjectId());
+ return std::string(buf);
+ case JS_OBJECT:
+ snprintf(buf, sizeof(buf), "JsObj(%d)", getJsObjectId());
+ return std::string(buf);
+ case UNDEFINED:
+ return "undefined";
+ default:
+ return "Unknown type";
+ }
+ }
+
+private:
+ void assertType(ValueType reqType) const {
+ if (type != reqType) {
+ Debug::log(Debug::Error) << "Value::assertType - expecting type "
+ << int(reqType) << ", was " << int(type) << Debug::flush;
+ // TODO(jat): is this portable? Should we do something else here?
+ abort();
+ }
+ }
+
+ void clearOldValue() {
+ if (type == STRING) {
+ delete value.stringValue;
+ type = UNDEFINED;
+ }
+ }
+
+ // Precondition: existing value, if any, has been cleared
+ void copyValue(const Value& other) {
+ type = other.type;
+ value = other.value;
+ // handle deep copies of value types that need it
+ switch (type) {
+ case STRING:
+ value.stringValue = new std::string(*value.stringValue);
+ break;
+ default:
+ // no other values need deep copies
+ break;
+ }
+ }
+};
+
+inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const Value& val) {
+ return dbg << val.toString();
+}
+
+#endif
diff --git a/plugins/common/scoped_ptr/README.google b/plugins/common/scoped_ptr/README.google
new file mode 100644
index 0000000..d513e21
--- /dev/null
+++ b/plugins/common/scoped_ptr/README.google
@@ -0,0 +1,27 @@
+Description
+===========
+
+This is the scoped_ptr from Boost with some additions by Google.
+
+Homepage
+========
+
+http://www.boost.org/
+http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
+
+License
+=======
+
+http://boost.org/LICENSE_1_0.txt
+
+Source files and modifications
+==============================
+
+scoped_ptr_malloc added in by Ray Sidney of Google. When one of these goes
+out of scope, instead of doing a delete or delete[], it calls free().
+scoped_ptr_malloc<char> is likely to see much more use than any other
+specializations.
+
+release() added in by Spencer Kimball of Google. Use this to conditionally
+transfer ownership of a heap-allocated object to the caller, usually on
+method success.
diff --git a/plugins/common/scoped_ptr/scoped_ptr.h b/plugins/common/scoped_ptr/scoped_ptr.h
new file mode 100644
index 0000000..1ae1b96
--- /dev/null
+++ b/plugins/common/scoped_ptr/scoped_ptr.h
@@ -0,0 +1,364 @@
+#ifndef SCOPED_PTR_H
+#define SCOPED_PTR_H
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 Peter Dimov
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
+//
+//
+// scoped_ptr mimics a built-in pointer except that it guarantees deletion
+// of the object pointed to, either on destruction of the scoped_ptr or via
+// an explicit reset(). scoped_ptr is a simple solution for simple needs;
+// use shared_ptr if your needs are more complex.
+//
+// *** NOTE ***
+// If your scoped_ptr is a class member of class FOO pointing to a
+// forward declared type BAR (as shown below), then at creation (and
+// destruction) of an object of type FOO, BAR must be complete. You can do
+// this by either:
+// - Making all FOO constructors and destructors non-inlined to FOO's class
+// definition, instead placing them in foo.cc below an include of bar.h
+// - Including bar.h before any creation or destruction of any object of
+// type FOO
+// The former is probably the less error-prone method, as shown below.
+//
+// Example:
+//
+// -- foo.h --
+// class BAR;
+//
+// class FOO {
+// public:
+// FOO(); // Required for sources that instantiate class FOO to compile!
+// ~FOO(); // Required for sources that instantiate class FOO to compile!
+//
+// private:
+// scoped_ptr<BAR> bar_;
+// };
+//
+// -- foo.cc --
+// #include "bar.h"
+// #include "foo.h"
+// FOO::FOO() {} // Empty, but must be non-inlined to FOO's class definition.
+// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition.
+//
+// scoped_ptr_malloc added in by Ray Sidney of Google. When one of
+// these goes out of scope, instead of doing a delete or delete[], it
+// calls free(). scoped_ptr_malloc<char> is likely to see much more
+// use than any other specializations.
+//
+// release() added in by Spencer Kimball of Google. Use this to conditionally
+// transfer ownership of a heap-allocated object to the caller, usually on
+// method success.
+
+#include <cstddef> // for std::ptrdiff_t
+#include <assert.h> // for assert
+#include <stdlib.h> // for free() decl
+
+template <typename T>
+class scoped_ptr;
+
+template <typename T>
+class scoped_ptr {
+ private:
+
+ T* ptr;
+
+ // scoped_ptr's must not be copied. We make sure of that by making the
+ // copy constructor prototype private. At the same time, there is no body
+ // for this constructor. Thus, if anything that has access to private
+ // members of scoped_ptr ever (inadvertently) copies a scoped_ptr, the
+ // linker will complain about missing symbols. This is a good thing!
+ scoped_ptr(scoped_ptr const &);
+ scoped_ptr & operator=(scoped_ptr const &);
+
+ public:
+
+ typedef T element_type;
+
+ explicit scoped_ptr(T* p = 0): ptr(p) {}
+
+ ~scoped_ptr() {
+ typedef char type_must_be_complete[sizeof(T)];
+ delete ptr;
+ }
+
+ void reset(T* p = 0) {
+ typedef char type_must_be_complete[sizeof(T)];
+
+ if (ptr != p) {
+ delete ptr;
+ ptr = p;
+ }
+ }
+
+ T& operator*() const {
+ assert(ptr != 0);
+ return *ptr;
+ }
+
+ T* operator->() const {
+ assert(ptr != 0);
+ return ptr;
+ }
+
+ bool operator==(T* p) const {
+ return ptr == p;
+ }
+
+ bool operator!=(T* p) const {
+ return ptr != p;
+ }
+
+ T* get() const {
+ return ptr;
+ }
+
+ void swap(scoped_ptr & b) {
+ T* tmp = b.ptr;
+ b.ptr = ptr;
+ ptr = tmp;
+ }
+
+ T* release() {
+ T* tmp = ptr;
+ ptr = 0;
+ return tmp;
+ }
+
+ private:
+
+ // no reason to use these: each scoped_ptr should have its own object
+ template <typename U> bool operator==(scoped_ptr<U> const& p) const;
+ template <typename U> bool operator!=(scoped_ptr<U> const& p) const;
+};
+
+template<typename T> inline
+void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
+ a.swap(b);
+}
+
+template<typename T> inline
+bool operator==(T* p, const scoped_ptr<T>& b) {
+ return p == b.get();
+}
+
+template<typename T> inline
+bool operator!=(T* p, const scoped_ptr<T>& b) {
+ return p != b.get();
+}
+
+// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
+// is guaranteed, either on destruction of the scoped_array or via an explicit
+// reset(). Use shared_array or std::vector if your needs are more complex.
+
+template<typename T>
+class scoped_array {
+ private:
+
+ T* ptr;
+
+ scoped_array(scoped_array const &);
+ scoped_array & operator=(scoped_array const &);
+
+ public:
+
+ typedef T element_type;
+
+ explicit scoped_array(T* p = 0) : ptr(p) {}
+
+ ~scoped_array() {
+ typedef char type_must_be_complete[sizeof(T)];
+ delete[] ptr;
+ }
+
+ void reset(T* p = 0) {
+ typedef char type_must_be_complete[sizeof(T)];
+
+ if (ptr != p) {
+ delete [] ptr;
+ ptr = p;
+ }
+ }
+
+ T& operator[](std::ptrdiff_t i) const {
+ assert(ptr != 0);
+ assert(i >= 0);
+ return ptr[i];
+ }
+
+ bool operator==(T* p) const {
+ return ptr == p;
+ }
+
+ bool operator!=(T* p) const {
+ return ptr != p;
+ }
+
+ T* get() const {
+ return ptr;
+ }
+
+ void swap(scoped_array & b) {
+ T* tmp = b.ptr;
+ b.ptr = ptr;
+ ptr = tmp;
+ }
+
+ T* release() {
+ T* tmp = ptr;
+ ptr = 0;
+ return tmp;
+ }
+
+ private:
+
+ // no reason to use these: each scoped_array should have its own object
+ template <typename U> bool operator==(scoped_array<U> const& p) const;
+ template <typename U> bool operator!=(scoped_array<U> const& p) const;
+};
+
+template<class T> inline
+void swap(scoped_array<T>& a, scoped_array<T>& b) {
+ a.swap(b);
+}
+
+template<typename T> inline
+bool operator==(T* p, const scoped_array<T>& b) {
+ return p == b.get();
+}
+
+template<typename T> inline
+bool operator!=(T* p, const scoped_array<T>& b) {
+ return p != b.get();
+}
+
+
+// This class wraps the c library function free() in a class that can be
+// passed as a template argument to scoped_ptr_malloc below.
+class ScopedPtrMallocFree {
+ public:
+ inline void operator()(void* x) const {
+ free(x);
+ }
+};
+
+// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
+// second template argument, the functor used to free the object.
+
+template<typename T, typename FreeProc = ScopedPtrMallocFree>
+class scoped_ptr_malloc {
+ private:
+
+ T* ptr;
+
+ scoped_ptr_malloc(scoped_ptr_malloc const &);
+ scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
+
+ public:
+
+ typedef T element_type;
+
+ explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
+
+ ~scoped_ptr_malloc() {
+ typedef char type_must_be_complete[sizeof(T)];
+ free_((void*) ptr);
+ }
+
+ void reset(T* p = 0) {
+ typedef char type_must_be_complete[sizeof(T)];
+
+ if (ptr != p) {
+ free_((void*) ptr);
+ ptr = p;
+ }
+ }
+
+ T& operator*() const {
+ assert(ptr != 0);
+ return *ptr;
+ }
+
+ T* operator->() const {
+ assert(ptr != 0);
+ return ptr;
+ }
+
+ bool operator==(T* p) const {
+ return ptr == p;
+ }
+
+ bool operator!=(T* p) const {
+ return ptr != p;
+ }
+
+ T* get() const {
+ return ptr;
+ }
+
+ void swap(scoped_ptr_malloc & b) {
+ T* tmp = b.ptr;
+ b.ptr = ptr;
+ ptr = tmp;
+ }
+
+ T* release() {
+ T* tmp = ptr;
+ ptr = 0;
+ return tmp;
+ }
+
+ private:
+
+ // no reason to use these: each scoped_ptr_malloc should have its own object
+ template <typename U, typename GP>
+ bool operator==(scoped_ptr_malloc<U, GP> const& p) const;
+ template <typename U, typename GP>
+ bool operator!=(scoped_ptr_malloc<U, GP> const& p) const;
+
+ static FreeProc const free_;
+};
+
+template<typename T, typename FP>
+FP const scoped_ptr_malloc<T,FP>::free_ = FP();
+
+template<typename T, typename FP> inline
+void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) {
+ a.swap(b);
+}
+
+template<typename T, typename FP> inline
+bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) {
+ return p == b.get();
+}
+
+template<typename T, typename FP> inline
+bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) {
+ return p != b.get();
+}
+
+#endif // #ifndef SCOPED_PTR_H
diff --git a/plugins/common/testing/DebugTest.cpp b/plugins/common/testing/DebugTest.cpp
new file mode 100644
index 0000000..add1357
--- /dev/null
+++ b/plugins/common/testing/DebugTest.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+// This file exists to verify that the debugging code leaves nothing
+// behind when disabled or at an appropriate level.
+//
+// Compile with, for example, g++ -O3 -D* -S DebugTest.cpp and inspect the DebugTest.s file.
+// where * is GWT_DEBUGDISABLE or GWT_DEBUGLEVEL=Spam (etc)
+//
+// testdebug is a shell script to automate this test
+
+// #define GWT_DEBUGDISABLE
+// #define GWT_DEBUGLEVEL Info
+
+#include "../Debug.h"
+
+void foo(int i) {
+ Debug::log(Debug::Error) << "Error GarbalDeGook" << i << Debug::flush;
+ Debug::log(Debug::Warning) << "Warning GarbalDeGook" << i << Debug::flush;
+ Debug::log(Debug::Info) << "Info GarbalDeGook" << i << Debug::flush;
+ Debug::log(Debug::Debugging) << "Debugging GarbalDeGook" << i << Debug::flush;
+ Debug::log(Debug::Spam) << "Spam GarbalDeGook" << i << Debug::flush;
+ if (Debug::level(Debug::Spam)) {
+ extern int ExpensiveCall();
+ Debug::log(Debug::Spam) << "Filtered spam GarbalDeGook" << ExpensiveCall() << Debug::flush;
+ }
+}
diff --git a/plugins/common/testing/testdebug b/plugins/common/testing/testdebug
new file mode 100755
index 0000000..e2e8ea4
--- /dev/null
+++ b/plugins/common/testing/testdebug
@@ -0,0 +1,61 @@
+#!/bin/sh
+# Copyright 2008 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+# this verifies that debug code is elided if it is not needed
+
+# The C++ compiler is specified in CXX, and its flags in CXXFLAGS
+# Defaults for GCC are used if not supplied. Note that CXXFLAGS should
+# include optimizations intended to be used. It is assumed that the
+# compiler uses -S to produce assembly output and -o - works to get that
+# output on stdout, and -Dsym=val is used to define preprocessor symbols.
+#
+# Note that debugging symbols should not be included as generally the
+# debugging info contains references to elided calls etc.
+if [ "x$CXX" == "x" ]
+then
+ CXX=g++
+fi
+
+if [ "x$CXXFLAGS" == "x" ]
+then
+ CXXFLAGS=-O3
+else
+ # remove -g if supplied
+ CXXFLAGS=`echo $CXXFLAGS | sed 's/-g\S*//'`
+fi
+
+CMD="$CXX $CXXFLAGS -S -o -"
+
+err=0
+$CMD -DGWT_DEBUGDISABLE DebugTest.cpp | egrep '(GarbalDeGook|ExpensiveCall)' >/dev/null
+if [ $? -eq 0 ]
+then
+ echo "Debug disabled leaves debug code around"
+ err=1
+fi
+$CMD -DGWT_DEBUGLEVEL=Error DebugTest.cpp | egrep '(Warning|ExpensiveCall)' >/dev/null
+if [ $? -eq 0 ]
+then
+ echo "Debug level Error leaves lower-level debug code around"
+ err=1
+fi
+$CMD -DGWT_DEBUGLEVEL=Spam DebugTest.cpp | grep 'ExpensiveCall' >/dev/null
+if [ $? -eq 1 ]
+then
+ echo "Debug level Spam does not include code that should be included"
+ err=1
+fi
+
+exit $err