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/webkit/Browser/AppController.h b/plugins/webkit/Browser/AppController.h
new file mode 100644
index 0000000..2d4747f
--- /dev/null
+++ b/plugins/webkit/Browser/AppController.h
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+
+@interface AppController : NSObject
+{
+    IBOutlet WebView *webview;
+}
+- (IBAction)newWindow:(id)sender;
+@end
diff --git a/plugins/webkit/Browser/AppController.m b/plugins/webkit/Browser/AppController.m
new file mode 100644
index 0000000..046a507
--- /dev/null
+++ b/plugins/webkit/Browser/AppController.m
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#import "AppController.h"
+#import "BrowserWindow.h"
+
+@implementation AppController
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+  NSLog(@"%s", __PRETTY_FUNCTION__);
+  
+  if (![WebView canShowMIMEType:@"application/x-gwt-hosted-mode"]) {
+    NSLog(@"plugin not available");
+    exit(-1);
+  }
+  NSString* str = @"http://localhost:8888/com.google.gwt.dev.jjs.CompilerSuite.JUnit/junit.html?gwt.hosted=localhost:9997";
+//  NSString* str = @"http://localhost:8888/com.google.gwt.user.RPCSuite.JUnit/junit.html?gwt.hosted=localhost:9997";
+//  NSString* str = @"http://localhost:8888/com.google.gwt.user.User.JUnit/junit.html?gwt.hosted=localhost:9997";
+  [webview setUIDelegate:self];
+  [webview setShouldCloseWithWindow: YES];
+  [[webview mainFrame] loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
+}
+
+- (IBAction)newWindow:(id)sender {
+  NSLog(@"Action received");
+  NSRect r;
+  r.origin.x = 100;
+  r.origin.y = 100;
+  r.size.height = 500;
+  r.size.width = 500;
+  
+  WebView* webView = [[WebView alloc] initWithFrame:r];
+  NSString* str = @"http://localhost:8888/com.google.gwt.sample.kitchensink.KitchenSink/KitchenSink.html?gwt.hosted=localhost:9997";
+  [webView setUIDelegate:self];
+  [webView setShouldCloseWithWindow: YES];
+  [[webView mainFrame] loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
+  
+  NSWindow* wnd = [[BrowserWindow alloc] initWithContentRect:r styleMask:NSResizableWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO];
+  [wnd setContentView:webView];
+  [wnd makeKeyAndOrderFront:self];
+}
+
+- (void)webView:(WebView *)sender windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject {
+  NSLog(@"%s", __PRETTY_FUNCTION__);
+}
+
+@end
diff --git a/plugins/webkit/Browser/Browser-Info.plist b/plugins/webkit/Browser/Browser-Info.plist
new file mode 100644
index 0000000..c597e30
--- /dev/null
+++ b/plugins/webkit/Browser/Browser-Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>gwtlogo</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gwt.oophm.browser</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>NSMainNibFile</key>
+	<string>browser.nib</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Browser/BrowserWindow.h b/plugins/webkit/Browser/BrowserWindow.h
new file mode 100644
index 0000000..18664ed
--- /dev/null
+++ b/plugins/webkit/Browser/BrowserWindow.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+@interface BrowserWindow : NSWindow {
+
+}
+
+@end
diff --git a/plugins/webkit/Browser/BrowserWindow.m b/plugins/webkit/Browser/BrowserWindow.m
new file mode 100644
index 0000000..c822886
--- /dev/null
+++ b/plugins/webkit/Browser/BrowserWindow.m
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+#import "BrowserWindow.h"
+
+@implementation BrowserWindow
+
+@end
diff --git a/plugins/webkit/Browser/browser.nib/classes.nib b/plugins/webkit/Browser/browser.nib/classes.nib
new file mode 100644
index 0000000..af71aad
--- /dev/null
+++ b/plugins/webkit/Browser/browser.nib/classes.nib
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBClasses</key>
+	<array>
+		<dict>
+			<key>CLASS</key>
+			<string>BrowserWindow</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSWindow</string>
+		</dict>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>toggleAutomaticLinkDetection</key>
+				<string>id</string>
+				<key>toggleAutomaticQuoteSubstitution</key>
+				<string>id</string>
+				<key>toggleGrammarChecking</key>
+				<string>id</string>
+				<key>toggleSmartInsertDelete</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>FirstResponder</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+		<dict>
+			<key>ACTIONS</key>
+			<dict>
+				<key>newWindow</key>
+				<string>id</string>
+			</dict>
+			<key>CLASS</key>
+			<string>AppController</string>
+			<key>LANGUAGE</key>
+			<string>ObjC</string>
+			<key>OUTLETS</key>
+			<dict>
+				<key>webview</key>
+				<string>WebView</string>
+			</dict>
+			<key>SUPERCLASS</key>
+			<string>NSObject</string>
+		</dict>
+	</array>
+	<key>IBVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Browser/browser.nib/info.nib b/plugins/webkit/Browser/browser.nib/info.nib
new file mode 100644
index 0000000..6271e8e
--- /dev/null
+++ b/plugins/webkit/Browser/browser.nib/info.nib
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IBFramework Version</key>
+	<string>629</string>
+	<key>IBLastKnownRelativeProjectPath</key>
+	<string>../../oophm.xcodeproj</string>
+	<key>IBOldestOS</key>
+	<integer>5</integer>
+	<key>IBOpenObjects</key>
+	<array/>
+	<key>IBSystem Version</key>
+	<string>9C7010</string>
+	<key>targetFramework</key>
+	<string>IBCocoaFramework</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Browser/browser.nib/keyedobjects.nib b/plugins/webkit/Browser/browser.nib/keyedobjects.nib
new file mode 100644
index 0000000..7691b0d
--- /dev/null
+++ b/plugins/webkit/Browser/browser.nib/keyedobjects.nib
Binary files differ
diff --git a/plugins/webkit/Browser/main.m b/plugins/webkit/Browser/main.m
new file mode 100644
index 0000000..f1a7cba
--- /dev/null
+++ b/plugins/webkit/Browser/main.m
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+    return NSApplicationMain(argc,  (const char **) argv);
+}
diff --git a/plugins/webkit/Core/ObjectFunctions.cpp b/plugins/webkit/Core/ObjectFunctions.cpp
new file mode 100644
index 0000000..a0a4a73
--- /dev/null
+++ b/plugins/webkit/Core/ObjectFunctions.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 "ObjectFunctions.h"
+#include "WebScriptSessionHandler.h"
+#include "scoped_ptr.h"
+
+JSValueRef JavaObjectCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
+                                            size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(function));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  
+  *exception = NULL;
+  int dispatchId = JSValueToNumber(ctx, arguments[0], exception);
+  if (*exception) {
+    return JSValueMakeUndefined(ctx);
+  }
+  
+  bool explicitThis = JSValueToBoolean(ctx, arguments[1]);
+  if (explicitThis) {
+    thisObject = JSValueToObject(ctx, arguments[1], exception);
+    if (*exception) {
+      return JSValueMakeUndefined(ctx);
+    }
+  } else {
+    thisObject = function;
+  }
+  
+  return sessionHandler->javaFunctionCallbackImpl(dispatchId, thisObject,
+                                                  argumentCount - 2, &arguments[2], exception);  
+}
+
+/*
+ * Static-dispatch function to clean up a Java object proxy.  This will
+ * deallocate the TrackingData as well as remove the objectId mapping.  This
+ * function is called from JavaScriptCore as well as ~WebScriptSessionHandler.
+ *
+ * The JavaScriptCore documentation indicates that finalizers may be called
+ * from any thread, so we can't see javaFree messages directly from this
+ * method.  Instead, we'll accumulate a list of ids to free. 
+ */
+void JavaObjectFinalize (JSObjectRef object) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  if (!tracker) {
+    // The tracker may have already been deleted in ~WebScriptSessionHandler()
+    return;
+  }
+  Debug::log(Debug::Spam) << "Finalizing Java object " << tracker->getObjectId() << Debug::flush;
+  JSObjectSetPrivate(object, NULL);
+  int id = tracker->getObjectId();  
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  delete tracker;
+  sessionHandler->javaObjectFinalizeImpl(id);
+}
+
+/*
+ * Static-dispatch function to check for the presence of a property on a Java
+ * object proxy.
+ */
+bool JavaObjectHasProperty (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  return sessionHandler->javaObjectHasPropertyImpl(tracker, object, propertyName);
+}
+
+/*
+ * Static-dispatch function to retrieve the value of a property on a Java
+ * object proxy.
+ */
+JSValueRef JavaObjectGetProperty (JSContextRef ctx, JSObjectRef object,
+                                         JSStringRef propertyName, JSValueRef* exception) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  return sessionHandler->javaObjectGetPropertyImpl(tracker, object, propertyName, exception);
+}
+
+/*
+ * Static-dispatch function to set the value of a property an a Java object
+ * proxy.
+ */
+bool JavaObjectSetProperty (JSContextRef ctx, JSObjectRef object,
+                                   JSStringRef propertyName, JSValueRef value,
+                                   JSValueRef* exception) {
+  TrackingDataRef tracker = static_cast<TrackingDataRef>(JSObjectGetPrivate(object));
+  WebScriptSessionHandler* sessionHandler = static_cast<WebScriptSessionHandler*>(tracker->getSessionData());
+  return sessionHandler->javaObjectSetPropertyImpl(tracker, object, propertyName, value, exception);
+}
diff --git a/plugins/webkit/Core/ObjectFunctions.h b/plugins/webkit/Core/ObjectFunctions.h
new file mode 100644
index 0000000..176218e
--- /dev/null
+++ b/plugins/webkit/Core/ObjectFunctions.h
@@ -0,0 +1,55 @@
+/*
+ * 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 "JavaScriptCore/JavaScriptCore.h"
+
+/*
+ * Handle JSNI function invocations.
+ */
+JSValueRef JavaObjectCallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
+                                    size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+/*
+ * Static-dispatch function to clean up a Java object proxy.  This will
+ * deallocate the TrackingData as well as remove the objectId mapping.  This
+ * function is called from JavaScriptCore as well as ~WebScriptSessionHandler.
+ *
+ * The JavaScriptCore documentation indicates that finalizers may be called
+ * from any thread, so we can't see javaFree messages directly from this
+ * method.  Instead, we'll accumulate a list of ids to free. 
+ */
+void JavaObjectFinalize (JSObjectRef object);
+
+/*
+ * Static-dispatch function to check for the presence of a property on a Java
+ * object proxy.
+ */
+bool JavaObjectHasProperty (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);
+
+/*
+ * Static-dispatch function to retrieve the value of a property on a Java
+ * object proxy.
+ */
+JSValueRef JavaObjectGetProperty (JSContextRef ctx, JSObjectRef object,
+                                         JSStringRef propertyName, JSValueRef* exception);
+
+/*
+ * Static-dispatch function to set the value of a property an a Java object
+ * proxy.
+ */
+bool JavaObjectSetProperty (JSContextRef ctx, JSObjectRef object,
+                                   JSStringRef propertyName, JSValueRef value,
+                                   JSValueRef* exception);
\ No newline at end of file
diff --git a/plugins/webkit/Core/SessionData.h b/plugins/webkit/Core/SessionData.h
new file mode 100644
index 0000000..9f60ddf
--- /dev/null
+++ b/plugins/webkit/Core/SessionData.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#import "HostChannel.h"
+#import "JavaScriptCore/JavaScriptCore.h"
+#import "SessionHandler.h"
+
+/*
+ * Encapsules per-OOPHM-session data.
+ */
+class SessionData {
+public:
+  SessionData(HostChannel* channel, JSGlobalContextRef contextRef, 
+              SessionHandler* sessionHandler) : channel(channel),
+                                                contextRef(contextRef),
+                                                sessionHandler(sessionHandler) {
+  }
+  
+  JSGlobalContextRef getContext() const {
+    return contextRef;
+  }
+  
+  HostChannel* getHostChannel() const {
+    return channel;
+  }
+  
+  SessionHandler* getSessionHandler() const {
+    return sessionHandler;
+  }
+
+protected:
+  /*
+   * The communication channel used for the OOPHM session.
+   */
+  HostChannel* const channel;
+  
+  /*
+   * The JavaScriptCore interpreter instance.
+   */
+  JSGlobalContextRef const contextRef;
+  
+  /*
+   * A reference to the SessionHandler being used in the OOPHM session.
+   */
+  SessionHandler* const sessionHandler;
+};
+typedef SessionData* SessionDataRef;
\ No newline at end of file
diff --git a/plugins/webkit/Core/TrackingData.h b/plugins/webkit/Core/TrackingData.h
new file mode 100644
index 0000000..de19f00
--- /dev/null
+++ b/plugins/webkit/Core/TrackingData.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#import "SessionData.h"
+
+/*
+ * This class encapsulates per-object information to determine how to dispatch
+ * a given JSObjectRef that is a Java object proxy. Instances of
+ * this class are intended to be stored in the private data area provided
+ * by JSObjectRef.
+ */
+class TrackingData {
+public:
+  /*
+   * Constructor for Java object proxies.
+   */
+  TrackingData(const SessionDataRef sessionData, const unsigned objId) :
+  objId(objId), sessionData(sessionData) {
+  }
+  
+  const unsigned getObjectId() const {
+    return objId;
+  }
+  
+  SessionDataRef getSessionData() const {
+    return sessionData;
+  }
+  
+private:
+  /*
+   * The tracking number assigned to the object.
+   */
+  const unsigned objId;
+  
+  /*
+   * A reference to the per-OOPHM-session data.
+   */
+  SessionDataRef const sessionData;  
+};
+typedef const TrackingData* TrackingDataRef;
diff --git a/plugins/webkit/Core/WebScriptSessionHandler.cpp b/plugins/webkit/Core/WebScriptSessionHandler.cpp
new file mode 100644
index 0000000..95caff5
--- /dev/null
+++ b/plugins/webkit/Core/WebScriptSessionHandler.cpp
@@ -0,0 +1,696 @@
+/*
+ * 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.
+ */
+
+#import "WebScriptSessionHandler.h"
+#import "InvokeMessage.h"
+#import "ObjectFunctions.h"
+#import "ServerMethods.h"
+#import "TrackingData.h"
+#import "scoped_ptr.h"
+
+
+WebScriptSessionHandler::WebScriptSessionHandler(HostChannel* channel,
+                                                 JSGlobalContextRef contextRef,
+                                                 CrashHandlerRef crashHandler) : 
+SessionData(channel, contextRef, this), jsObjectId(1), crashHandler(crashHandler) {
+
+  JSClassDefinition def = kJSClassDefinitionEmpty;
+  def.className = "JavaObject";
+  def.hasProperty = JavaObjectHasProperty;
+  def.callAsFunction = JavaObjectCallAsFunction;
+  def.finalize = JavaObjectFinalize;
+  def.getProperty = JavaObjectGetProperty;
+  def.setProperty = JavaObjectSetProperty;
+  javaObjectWrapperClass = JSClassCreate(&def);
+  JSClassRetain(javaObjectWrapperClass);
+  
+  // Get the String constructor function to tell Strings from other Objects
+  JSStringRef stringString = JSStringCreateWithUTF8CString("String");
+  JSValueRef stringConstructorValue = JSObjectGetProperty(contextRef,
+                                                          JSContextGetGlobalObject(contextRef),
+                                                          stringString, NULL);
+  stringConstructor = JSValueToObject(contextRef, stringConstructorValue, NULL);
+  JSValueProtect(contextRef, stringConstructor);
+  JSStringRelease(stringString);
+  
+  // Call out to the utility __gwt_makeResult function to create the return array
+  JSStringRef makeResultString = JSStringCreateWithUTF8CString("__gwt_makeResult");
+  JSValueRef makeResultValue = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), makeResultString, NULL);
+  JSStringRelease(makeResultString);
+  
+  if (!JSValueIsObject(contextRef, makeResultValue)) {
+    crashHandler->crash(__PRETTY_FUNCTION__, "Could not find __gwt_makeResult");
+  } else {
+    makeResultFunction = JSValueToObject(contextRef, makeResultValue, NULL);
+    JSValueProtect(contextRef, makeResultFunction);
+  }
+  
+  pthread_mutexattr_t mutexAttrs;
+  pthread_mutexattr_init(&mutexAttrs);
+  // This behaves basically like the Java synchronized keyword
+  pthread_mutexattr_settype(&mutexAttrs, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init(&javaObjectsLock, &mutexAttrs);
+  pthread_mutexattr_destroy(&mutexAttrs);
+}
+
+WebScriptSessionHandler::~WebScriptSessionHandler() {
+  std::map<int, JSObjectRef>::iterator i;
+  
+  pthread_mutex_lock(&javaObjectsLock);
+  while ((i = javaObjectsById.begin()) != javaObjectsById.end()) {
+    JavaObjectFinalize(i->second);
+  }
+  pthread_mutex_unlock(&javaObjectsLock);
+  
+  for (i = jsObjectsById.begin(); i != jsObjectsById.end(); i++) {
+    JSObjectRef ref = i->second;
+    delete static_cast<TrackingDataRef>(JSObjectGetPrivate(ref));
+    JSObjectSetPrivate(ref, NULL);
+    JSValueUnprotect(contextRef, i->second);
+  }
+  
+  JSClassRelease(javaObjectWrapperClass);
+  
+  JSValueUnprotect(contextRef, stringConstructor);
+  JSValueUnprotect(contextRef, makeResultFunction);
+  
+  JSGarbageCollect(contextRef);
+  pthread_mutex_destroy(&javaObjectsLock);
+}
+
+void WebScriptSessionHandler::freeJavaObjects() {
+  pthread_mutex_lock(&javaObjectsLock);
+  int idCount = javaObjectsToFree.size();
+  if (idCount == 0) {
+    pthread_mutex_unlock(&javaObjectsLock);
+    return;
+  }
+  
+  int ids[idCount];
+  std::set<int>::iterator it = javaObjectsToFree.begin();
+  for (int i = 0; i < idCount; it++) {
+    ids[i++] = *it;
+  }
+  if (!ServerMethods::freeJava(*channel, this, idCount, ids)) {
+    Debug::log(Debug::Error) << "Unable to free Java ids" << Debug::flush;
+  } else {
+    Debug::log(Debug::Debugging) << "Freed " << idCount << " Java ids" << Debug::flush;
+  }
+  javaObjectsToFree.clear();
+  pthread_mutex_unlock(&javaObjectsLock);
+}
+
+void WebScriptSessionHandler::freeValue(HostChannel& channel, int idCount, const int* ids) {
+  Debug::log(Debug::Spam) << "freeValue freeing " << idCount << " js objects" << Debug::flush;
+  if (idCount == 0) {
+    return;
+  }
+  
+  for (int i = 0; i < idCount; i++) {
+    int objId = ids[i];
+    
+    std::map<int, JSObjectRef>::iterator i = jsObjectsById.find(objId);
+    if (i == jsObjectsById.end()) {
+      Debug::log(Debug::Error) << "Unknown object id " << objId << Debug::flush;
+      continue;
+    }
+    
+    JSObjectRef ref = i->second;
+    jsObjectsById.erase(objId);
+    jsIdsByObject.erase(ref);
+    JSValueUnprotect(contextRef, ref);
+  }
+  Debug::log(Debug::Debugging) << "Freed " << idCount << " JS objects" << Debug::flush;
+}
+
+void WebScriptSessionHandler::initiateAutodestructSequence(const char* functionName, const char* message) {
+  crashHandler->crash(functionName, message);
+}
+
+bool WebScriptSessionHandler::invoke(HostChannel& channel, const Value& thisObj,
+                                    const std::string& methodName,
+                                    int numArgs, const Value* args, Value* returnValue) {
+  Debug::log(Debug::Spam) << "invoke " << methodName << Debug::flush;
+
+  JSValueRef argsJS[numArgs];
+  JSValueRef localException = NULL;
+  JSStringRef methodNameJS = JSStringCreateWithUTF8CString(methodName.c_str());    
+  JSObjectRef thisObjJs;
+  
+  if (thisObj.isNull()) {
+    thisObjJs = JSContextGetGlobalObject(contextRef);
+  } else {
+    thisObjJs = (JSObjectRef) makeValueRef(thisObj);
+  }
+  
+  JSValueRef functionValueJS = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef),
+                                                   methodNameJS, &localException);
+  JSStringRelease(methodNameJS);
+  
+  if (!JSValueIsObject(contextRef, functionValueJS)) {
+    char message[512];
+    snprintf(message, sizeof(message), "Could not find method for property name %s on %s", methodName.c_str(), thisObj.toString().c_str());
+    makeExceptionValue(*returnValue, message);
+    return true;
+  }
+  
+  JSObjectRef functionJS = JSValueToObject(contextRef, functionValueJS,
+                                           &localException);
+  if (localException) {
+    makeValue(*returnValue, localException);
+    return true;
+  }
+  
+  // Convert the arguments
+  for (int i = 0; i < numArgs; i++) {
+    argsJS[i] = makeValueRef(args[i]);
+  }
+  
+  JSValueRef retVal = JSObjectCallAsFunction(contextRef, functionJS,
+                                             thisObjJs, numArgs, argsJS,
+                                             &localException);
+  
+  // It's safe to free remote objects before sending an Invoke or a Return message
+  freeJavaObjects();
+  
+  if (localException) {
+    Debug::log(Debug::Spam) << "Returning exception to server" << Debug::flush;
+    makeValue(*returnValue, localException);
+    return true;
+  } else {
+    makeValue(*returnValue, retVal);
+    return false;
+  }
+}
+
+bool WebScriptSessionHandler::invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+                                            const Value* const args, Value* returnValue) {
+  Debug::log(Debug::Spam) << "invokeSpecial " << method << Debug::flush;
+  switch (method) {
+    case GetProperty:
+    {
+      int objId = args[0].getInt();
+      std::map<int, JSObjectRef>::iterator i = jsObjectsById.find(objId);
+      if (i == jsObjectsById.end()) {
+        char message[50];
+        snprintf(message, sizeof(message), "Unknown object id %i", objId);
+        makeExceptionValue(*returnValue, message);
+        return true;
+      }
+      
+      JSObjectRef jsObj = i->second;
+      if (args[1].isString()) {
+        JSStringRef asString = JSValueToStringCopy(contextRef, jsObj, NULL);
+        int maxLength = JSStringGetMaximumUTF8CStringSize(asString);
+        scoped_array<char> asChars(new char[maxLength]);
+        JSStringGetUTF8CString(asString, asChars.get(), maxLength);
+        
+        JSValueRef localException = NULL;
+        JSStringRef str = JSStringCreateWithUTF8CString(args[1].getString().c_str());
+        JSValueRef value = JSObjectGetProperty(contextRef, jsObj, str, &localException);
+        JSStringRelease(str);
+        if (localException) {
+          makeValue(*returnValue, localException);
+          return true;
+        } else {
+          makeValue(*returnValue, value);
+          return false;
+        }
+      } else if (args[1].isInt()) {
+        JSValueRef localException = NULL;
+        JSValueRef value = JSObjectGetPropertyAtIndex(contextRef, jsObj, args[1].getInt(), &localException);
+        
+        if (localException) {
+          makeValue(*returnValue, localException);
+          return true;
+        } else {
+          makeValue(*returnValue, value);
+          return false;
+        }
+      } else {
+        char message[50];
+        snprintf(message, sizeof(message), "Unhandled argument type %s for getProperty", args[1].toString().c_str());
+        makeExceptionValue(*returnValue, message);
+        return true;
+      }
+    }
+    default:
+      Debug::log(Debug::Error) << "Unhandled invokeSpecial " << method << Debug::flush;
+      makeExceptionValue(*returnValue, "Unhandled invokeSpecial");
+      return true;
+  }  
+}
+
+JSValueRef WebScriptSessionHandler::javaFunctionCallbackImpl (int dispatchId,
+                                                              JSObjectRef thisObject,
+                                                              size_t argumentCount,
+                                                              const JSValueRef arguments[],
+                                                              JSValueRef* exception){
+  /*
+   * NB: Because throwing exceptions in JavaScriptCore is trivial, we don't rely
+   * on any special return values to indicate that an exception is thrown, we'll simply
+   * throw the exception.
+   */
+  Debug::log(Debug::Debugging) << "Java method " << dispatchId << " invoked" << Debug::flush;
+  
+  /*
+   * If a JS function is evaluated without an meaningful this object or the global
+   * object is implicitly used as the this object, we'll assume that the
+   * Java-derived method is static, and send a null this object to the server
+   */
+  Value thisValue;
+  if (JSValueIsEqual(contextRef, thisObject, JSContextGetGlobalObject(contextRef), NULL)) {
+    thisValue = Value();
+    thisValue.setNull();
+  } else {
+    makeValue(thisValue, thisObject);
+  }
+  
+  // Argument conversion is straightforward
+  Value args[argumentCount];
+  for (int i = 0; i < argumentCount; i++) {
+    makeValue(args[i], arguments[i]);
+  }
+  
+  if (!InvokeMessage::send(*channel, thisValue, dispatchId,
+                           argumentCount, args)) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to send invocation message");
+    *exception = makeException("Unable to send invocation message");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  scoped_ptr<ReturnMessage> ret(channel->reactToMessagesWhileWaitingForReturn(sessionHandler));
+  
+  if (!ret.get()) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to receive return message");
+    *exception = makeException("Unable to receive return message");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  Value v = ret->getReturnValue();
+  
+  JSValueRef toReturn;
+  if (ret->isException()) {
+    *exception = makeValueRef(v);
+    toReturn = JSValueMakeUndefined(contextRef);
+  } else {
+    toReturn = makeValueRef(v);
+  }
+  
+  JSValueRef makeResultArguments[] = {JSValueMakeBoolean(contextRef, false), toReturn};
+  return JSObjectCallAsFunction(contextRef, makeResultFunction, NULL, 2, makeResultArguments, exception);
+}
+
+void WebScriptSessionHandler::javaObjectFinalizeImpl(int objId) {
+  if (pthread_mutex_lock(&javaObjectsLock)) {
+    Debug::log(Debug::Error) << "Unable to acquire javaObjectsLock in thread " << pthread_self() << " " << __PRETTY_FUNCTION__ << Debug::flush;
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to acquire javaObjectsLock");
+    return;
+  }
+  javaObjectsById.erase(objId);
+  javaObjectsToFree.insert(objId);
+  if (pthread_mutex_unlock(&javaObjectsLock)) {
+    Debug::log(Debug::Error) << "Unable to release javaObjectsLock in thread " << pthread_self() << " " << __PRETTY_FUNCTION__ << Debug::flush;
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Unable to release javaObjectsLock");
+  }
+}
+
+JSValueRef WebScriptSessionHandler::javaObjectGetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
+                                                               JSStringRef propertyName, JSValueRef* exception) {
+  *exception = NULL;
+  
+  // Convert the name
+  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
+  scoped_array<char> propertyNameChars(new char[maxLength]);
+  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
+  JSValueRef toReturn;  
+  
+  if (!strcmp(propertyNameChars.get(), "toString")) {
+    // We'll call out to the JSNI tear-off support function
+    JSStringRef tearOffName =JSStringCreateWithUTF8CString("__gwt_makeTearOff");
+    JSValueRef makeTearOffValue = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), tearOffName, exception);
+    JSStringRelease(tearOffName);
+    if (*exception) {
+      return JSValueMakeUndefined(contextRef);
+    }    
+    
+    JSObjectRef makeTearOff = JSValueToObject(contextRef, makeTearOffValue, exception);
+    if (*exception) {
+      return JSValueMakeUndefined(contextRef);
+    }
+    
+    JSValueRef arguments[3];
+    arguments[0] = object;
+    arguments[1] = JSValueMakeNumber(contextRef, 0);
+    arguments[2] = JSValueMakeNumber(contextRef, 0);
+    toReturn = JSObjectCallAsFunction(contextRef, makeTearOff, JSContextGetGlobalObject(contextRef), 3, arguments, exception);
+  } else {
+    char* endptr;
+    int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
+    
+    if (*endptr != '\0') {
+      Debug::log(Debug::Error) << "Unable to parse dispatch id " << propertyNameChars.get() << Debug::flush;
+      *exception = makeException("Unable to parse dispatch id");
+    } else if (dispatchId < 0) {
+      Debug::log(Debug::Error) << "Dispatch ids may not be negative" << Debug::flush;
+      *exception = makeException("Dispatch ids may not be negative");
+    } else {
+      Value v = ServerMethods::getProperty(*channel, this, tracker->getObjectId(), dispatchId);
+      toReturn = makeValueRef(v);
+    }
+  }
+  
+  return toReturn;
+}
+
+bool WebScriptSessionHandler::javaObjectHasPropertyImpl (TrackingDataRef tracker, JSObjectRef object, JSStringRef propertyName) {
+  // The property name must either be "toString" or a number
+  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
+  scoped_array<char> propertyNameChars(new char[maxLength]);
+  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
+  if (!strcmp(propertyNameChars.get(), "toString")) {
+    return true;
+  }
+  
+  char* endptr;
+  int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
+  
+  if (*endptr != '\0') {
+    return false;
+  } else if (dispatchId < 0) {
+    return false;
+  } else {
+    return true;
+  }
+}
+
+bool WebScriptSessionHandler::javaObjectSetPropertyImpl (TrackingDataRef tracker, JSObjectRef object,
+                                                         JSStringRef propertyName, JSValueRef jsValue,
+                                                         JSValueRef* exception) {
+  int maxLength = JSStringGetMaximumUTF8CStringSize(propertyName);
+  scoped_array<char> propertyNameChars(new char[maxLength]);
+  JSStringGetUTF8CString(propertyName, propertyNameChars.get(), maxLength);
+  Value value;
+  
+  char* endptr;
+  int dispatchId = strtol(propertyNameChars.get(), &endptr, 10);
+  
+  if (*endptr != '\0') {
+    // TODO Figure out the right policy here; when we throw a Java object, JSCore wants to
+    // add expandos to record stack information.  It would be possible to map the limited
+    // number of properties into a synthetic causal exception in the exception being thrown.
+  } else if (dispatchId < 0) {
+    // Do nothing.
+    Debug::log(Debug::Error) << "Dispatch ids may not be negative" << Debug::flush;
+    *exception = makeException("Dispatch ids may not be negative");
+  } else {
+  
+    makeValue(value, jsValue);
+    
+    if (!ServerMethods::setProperty(*channel, this, tracker->getObjectId(), dispatchId, value)) {
+      char message[50];
+      snprintf(message, sizeof(message), "Unable to set value object %i dispatchId %i", tracker->getObjectId(), dispatchId);
+      *exception = makeException(message);
+    }
+  }
+  
+  // true means to not try to follow the prototype chain; not an indication of success
+  return true;
+}
+
+void WebScriptSessionHandler::loadJsni(HostChannel& channel, const std::string& js) {
+  Debug::log(Debug::Spam) << "loadJsni " << js << Debug::flush;
+  JSValueRef localException = NULL;
+  
+  JSStringRef script = JSStringCreateWithUTF8CString(js.c_str());
+  JSEvaluateScript(contextRef, script, NULL, NULL, NULL, &localException);
+  JSStringRelease(script);
+  
+  if (localException) {
+    // TODO Exception handling
+    Debug::log(Debug::Error) << "Exception thrown during loadJsni" << Debug::flush;
+  } else {
+    Debug::log(Debug::Spam) << "Success" << Debug::flush;
+  }
+}
+
+JSValueRef WebScriptSessionHandler::makeException(const char* message) {
+  JSValueRef localException = NULL;
+  JSObjectRef global = JSContextGetGlobalObject(contextRef);
+  
+  JSStringRef errorName = JSStringCreateWithUTF8CString("Error");
+  JSValueRef errorValue = JSObjectGetProperty(contextRef, global, errorName, &localException);
+  JSStringRelease(errorName);
+  
+  if (!JSValueIsObject(contextRef, errorValue)) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Could not get reference to Error");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  JSObjectRef errorObject = (JSObjectRef) errorValue;
+  
+  if (!JSObjectIsFunction(contextRef, errorObject)) {
+    initiateAutodestructSequence(__PRETTY_FUNCTION__, "Error was not a function");
+    return JSValueMakeUndefined(contextRef);
+  }
+  
+  JSValueRef args[1];
+  JSStringRef messageJs = JSStringCreateWithUTF8CString(message);
+  args[0] = JSValueMakeString(contextRef, messageJs);
+  JSStringRelease(messageJs);
+  
+  return JSObjectCallAsConstructor(contextRef, errorObject, 1, args, &localException);
+}
+
+void WebScriptSessionHandler::makeExceptionValue(Value& value, const char* message) {
+  makeValue(value, makeException(message));
+}
+
+JSObjectRef WebScriptSessionHandler::makeJavaWrapper(int objId) {
+  Debug::log(Debug::Spam) << "Creating wrapper for Java object " << objId << Debug::flush;
+  
+  TrackingDataRef data = new TrackingData(this, objId);
+  return JSObjectMake(contextRef, javaObjectWrapperClass,
+                      const_cast<TrackingData*>(data));
+}
+
+JSValueRef WebScriptSessionHandler::makeValueRef(const Value& v) {
+  std::map<int, JSObjectRef>::iterator i;
+  switch (v.getType()) {
+    case Value::NULL_TYPE:
+      return JSValueMakeNull(contextRef);
+      
+    case Value::BOOLEAN:
+      return JSValueMakeBoolean(contextRef, v.getBoolean());
+      
+    case Value::BYTE:
+      return JSValueMakeNumber(contextRef, v.getByte());
+      
+    case Value::CHAR:
+      return JSValueMakeNumber(contextRef, v.getChar());
+      
+    case Value::SHORT:
+      return JSValueMakeNumber(contextRef, v.getShort());
+      
+    case Value::INT:
+      return JSValueMakeNumber(contextRef, v.getInt());
+      
+    case Value::LONG:
+      return JSValueMakeNumber(contextRef, v.getLong());
+      
+    case Value::FLOAT:
+      return JSValueMakeNumber(contextRef, v.getFloat());
+      
+    case Value::DOUBLE:
+      return JSValueMakeNumber(contextRef, v.getDouble());
+      
+    case Value::STRING:
+    {
+      std::string stringValue = v.getString();
+      
+      // We need to handle the conversion ourselves to be able to get both
+      // UTF8 encoding as well as explicit control over the length of the string
+      // due to the possibility of null characters being part of the data
+      CFStringRef cfString = CFStringCreateWithBytesNoCopy(NULL, (UInt8*)stringValue.data(),
+                                                           stringValue.length(), kCFStringEncodingUTF8,
+                                                           false, kCFAllocatorNull);
+      JSStringRef stringRef = JSStringCreateWithCFString(cfString);
+      JSValueRef toReturn = JSValueMakeString(contextRef, stringRef);
+      JSStringRelease(stringRef);
+      CFRelease(cfString);
+      return toReturn;
+    }
+      
+    case Value::JAVA_OBJECT:
+      unsigned javaId = v.getJavaObjectId();
+      JSObjectRef ref;
+      
+      pthread_mutex_lock(&javaObjectsLock);
+      i = javaObjectsById.find(javaId);
+      
+      /*
+       * It's possible that we've already finalized the JsObjectRef that
+       * represented the object with the given id.  If so, we must remove it
+       * from the list of finalized object ids to avoid prematurely freeing
+       * the object on the server.
+       */
+      javaObjectsToFree.erase(javaId);
+      
+      if (i == javaObjectsById.end()) {
+        /*
+         * We don't call JSValueProtect so that the JavaObject peer can be
+         * garbage-collected during the lifetime of the program.  Object
+         * identity is maintained as long as the object hasn't been finalized.
+         * If it had been finalized, then there wouldn't be an object to use
+         * as a basis for identity comparison.
+         *
+         * NB: The act of creating the wrapper may trigger a GC.
+         */
+        ref = makeJavaWrapper(javaId);
+        
+        javaObjectsById[javaId] = ref;
+        
+      } else {
+        ref = i->second;
+      }
+      pthread_mutex_unlock(&javaObjectsLock);
+      
+      
+      return ref;
+      
+      case Value::JS_OBJECT:
+      int jsId = v.getJsObjectId();
+      
+      i = jsObjectsById.find(jsId);
+      if (i == jsObjectsById.end()) {
+        char errMsg[50];
+        snprintf(errMsg, sizeof(errMsg), "Missing JsObject with id %i", jsId);
+        return makeException(errMsg);
+        
+      } else {
+        return i->second;
+      }
+      
+      case Value::UNDEFINED:
+      return JSValueMakeUndefined(contextRef);
+      
+      default:
+      char message[50];
+      snprintf(message, sizeof(message), "Could not convert %s", v.toString().c_str());
+      initiateAutodestructSequence(__PRETTY_FUNCTION__, message);
+      return makeException(message);
+  }
+}
+
+bool WebScriptSessionHandler::makeValue(Value& ret, JSValueRef v) {
+  JSValueRef localException = NULL;
+  
+  if (JSValueIsNull(contextRef, v)) {
+    ret.setNull();
+    
+  } else if (JSValueIsUndefined(contextRef, v)) {
+    ret.setUndefined();
+    
+  } else if (JSValueIsBoolean(contextRef, v)) {
+    ret.setBoolean(JSValueToBoolean(contextRef, v));
+    
+  } else if (JSValueIsNumber(contextRef, v)) {
+    double d = JSValueToNumber(contextRef, v, &localException);
+    int i = round(d);
+    if (i == d) {
+      ret.setInt(i);
+    } else {
+      ret.setDouble(d);
+    }
+    
+  } else if (JSValueIsString(contextRef, v) ||
+             JSValueIsInstanceOfConstructor(contextRef, v, stringConstructor, &localException)) {
+    return makeValueFromString(ret, v);
+    
+  } else if (JSValueIsObjectOfClass(contextRef, v, javaObjectWrapperClass)) {
+    // It's one of our Java object proxies
+    JSObjectRef objectRef = JSValueToObject(contextRef, v, &localException);
+    
+    if (!localException) {
+      TrackingDataRef tracker = (TrackingDataRef) JSObjectGetPrivate(objectRef);
+      int objId = tracker->getObjectId();
+      ret.setJavaObject(objId);
+      Debug::log(Debug::Spam) << "Made a Java object Value " << objId << Debug::flush;
+    }
+    
+  } else if (JSValueIsObject(contextRef, v)) {
+    JSObjectRef objectRef = JSValueToObject(contextRef, v, &localException);
+    if (!localException) {
+      /*
+       * Then this is just a plain-old JavaScript Object.  Because JSCore
+       * doesn't retain private data for objects derived from the built-in
+       * Object type, we'll simply revert to using a pair of maps to provide
+       * a 1:1 mapping of JSObjectRefs and ints.
+       */
+      std::map<JSObjectRef, int>::iterator i = jsIdsByObject.find(objectRef);
+      if (i != jsIdsByObject.end()) {
+        // We've seen the object before
+        ret.setJsObjectId(i->second);
+      } else {
+        // Allocate a new id
+        int objId = ++jsObjectId;
+        JSValueProtect(contextRef, objectRef);
+        
+        jsObjectsById[objId] = objectRef;
+        jsIdsByObject[objectRef] = objId;
+        
+        ret.setJsObjectId(objId);
+        Debug::log(Debug::Spam) << "Made JS Value " << objId << Debug::flush;
+      }
+    }
+  } else {
+    Debug::log(Debug::Error) << "Unhandled JSValueRef -> Value conversion in plugin" << Debug::flush;
+    ret.setString("Unhandled JSValueRef -> Value conversion in plugin");
+  }
+  
+  if (localException) {
+    makeValue(ret, localException);
+    return true;
+  } else {
+    return false;
+  }
+}
+
+bool WebScriptSessionHandler::makeValueFromString(Value& ret, JSValueRef value) {
+  JSValueRef localException = NULL;
+  
+  JSStringRef jsString = JSValueToStringCopy(contextRef, value, &localException);
+  if (localException) {
+    makeValue(ret, localException);
+    return true;
+  }
+  
+  CFStringRef cfString = JSStringCopyCFString(NULL, jsString);
+  JSStringRelease(jsString);
+  
+  CFIndex cfLength = CFStringGetLength(cfString);
+  CFIndex maxLength = CFStringGetMaximumSizeForEncoding(cfLength, kCFStringEncodingUTF8);
+  scoped_array<char> utf8(new char[maxLength]);
+  
+  CFIndex numBytes;
+  CFStringGetBytes(cfString, CFRangeMake(0, cfLength), kCFStringEncodingUTF8,
+                   0, false, (UInt8*) utf8.get(), maxLength, &numBytes);    
+  CFRelease(cfString);
+  
+  ret.setString(utf8.get(), numBytes);
+  Debug::log(Debug::Spam) << "Made a string Value " << ret.getString() << Debug::flush;
+  return false;
+}
diff --git a/plugins/webkit/Core/WebScriptSessionHandler.h b/plugins/webkit/Core/WebScriptSessionHandler.h
new file mode 100644
index 0000000..fc9795d
--- /dev/null
+++ b/plugins/webkit/Core/WebScriptSessionHandler.h
@@ -0,0 +1,153 @@
+/*
+ * 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 <map>
+#include <set>
+#import "Debug.h"
+#import "HostChannel.h"
+#import "JavaScriptCore/JavaScriptCore.h"
+#import "pthread.h"
+#import "TrackingData.h"
+
+class CrashHandler {
+public:
+  virtual void crash(const char* functionName, const char* message) = 0;
+};
+typedef CrashHandler* CrashHandlerRef;
+
+/*
+ * This comprises the guts of the JavaScriptCore-specific code and is
+ * responsible for message dispatch and value conversion.  This class should
+ * be portable to any runtime that uses JavaScriptCore.
+ */
+class WebScriptSessionHandler : public SessionHandler, public SessionData  {
+public:
+  WebScriptSessionHandler(HostChannel* channel, JSGlobalContextRef contextRef,
+                          CrashHandler* crashHandler);
+  
+  /*
+   * Invoking the destructor will perform a clean shutdown of the OOPHM session.
+   */
+  ~WebScriptSessionHandler();
+  
+  /*
+   * This is a panic method for shutting down the OOPHM debugging session due
+   * to unrecoverable errors.
+   */
+  void initiateAutodestructSequence(const char* functionName, const char* message);
+
+  /*
+   * Invoke a Java method.
+   */
+  JSValueRef javaFunctionCallbackImpl(int dispatchId,
+                                      JSObjectRef thisObject,
+                                      size_t argumentCount,
+                                      const JSValueRef arguments[],
+                                      JSValueRef* exception);
+  
+  /*
+   * Finalize a Javo object proxy.
+   */
+  void javaObjectFinalizeImpl(int objId);
+  
+  /*
+   * Determine if a Java class has a named property.
+   */
+  bool javaObjectHasPropertyImpl(TrackingDataRef tracker, JSObjectRef object,
+                                JSStringRef propertyName);
+  
+  /*
+   * Obtain the value of named property of an object.
+   */
+  JSValueRef javaObjectGetPropertyImpl(TrackingDataRef tracker, JSObjectRef object,
+                                       JSStringRef propertyName, JSValueRef* exception);
+  
+  /*
+   * Set the value of a named property on a Java object.
+   */
+  bool javaObjectSetPropertyImpl(TrackingDataRef tracker, JSObjectRef object,
+                                 JSStringRef propertyName, JSValueRef value,
+                                 JSValueRef* exception);
+  
+  /*
+   * Create a JavaScript Error object with the given message.
+   */
+  JSValueRef makeException(const char* message);
+  
+protected:
+  virtual void freeValue(HostChannel& channel, int idCount, const int* ids);
+  virtual void loadJsni(HostChannel& channel, const std::string& js);
+  virtual bool invoke(HostChannel& channel, const Value& thisObj, const std::string& methodName,
+                      int numArgs, const Value* const args, Value* returnValue);
+  virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method, int numArgs,
+                             const Value* const args, Value* returnValue);
+  
+private:
+  CrashHandlerRef const crashHandler;
+  int jsObjectId;
+  std::map<int, JSObjectRef> javaObjectsById;
+  std::set<int> javaObjectsToFree;
+  pthread_mutex_t javaObjectsLock;
+  std::map<int, JSObjectRef> jsObjectsById;
+  std::map<JSObjectRef, int> jsIdsByObject;
+  JSClassRef javaObjectWrapperClass;
+  
+  /* A reference to __gwt_makeResult, which we use constantly */
+  JSObjectRef makeResultFunction;
+  
+  /* The String() function */
+  JSObjectRef stringConstructor;
+   
+  /*
+   * Free server-side references.
+   */
+  void freeJavaObjects();
+  
+  /*
+   * Create a exception Value that contains the given message.
+   */
+  void makeExceptionValue(Value& value, const char* message);
+  
+  /*
+   * Create a Java object proxy to be passed into the JavaScript execution
+   * environment.
+   */
+  JSObjectRef makeJavaWrapper(int objId);
+  
+  /*
+   * Convert a value from the JavaScript into something that can be sent back
+   * to the OOPHM host.
+   *
+   * Returns true if an exception was encountered.
+   */
+  bool makeValue(Value& ret, JSValueRef value);
+  
+  /*
+   * Convert a string-like object to something that can be sent back to the OOPHM
+   * host.
+   *
+   * Returns true if an exception was encountered.
+   */
+  bool makeValueFromString(Value& ret, JSValueRef value);
+  
+  /*
+   * Convert a value from the OOPHM host into something that can be passed into
+   * the JavaScript execution environment.
+   */
+  JSValueRef makeValueRef(const Value& value);
+};
+typedef WebScriptSessionHandler* WebScriptSessionHandlerRef;
+
diff --git a/plugins/webkit/English.lproj/InfoPlist.strings b/plugins/webkit/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..6260754
--- /dev/null
+++ b/plugins/webkit/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/plugins/webkit/Info.plist b/plugins/webkit/Info.plist
new file mode 100644
index 0000000..7b8e8a0
--- /dev/null
+++ b/plugins/webkit/Info.plist
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>gwtlogo</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.google.gwt.oophm</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>WBPL</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>0.1</string>
+	<key>NSPrincipalClass</key>
+	<string>OophmPlugin</string>
+	<key>WebPluginDescription</key>
+	<string>Google Web Toolkit Out-Of-Process Hosted Mode plugin</string>
+	<key>WebPluginMIMETypes</key>
+	<dict>
+		<key>application/x-gwt-hosted-mode</key>
+		<dict>
+			<key>WebPluginTypeDescription</key>
+			<string>Google Web Toolkit Out-of-Process hosted mode.</string>
+		</dict>
+	</dict>
+	<key>WebPluginName</key>
+	<string>GWT OOPHM</string>
+</dict>
+</plist>
diff --git a/plugins/webkit/Plugin/Debug.mm b/plugins/webkit/Plugin/Debug.mm
new file mode 100644
index 0000000..6cc8edf
--- /dev/null
+++ b/plugins/webkit/Plugin/Debug.mm
@@ -0,0 +1,36 @@
+/*
+ * 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>
+
+static NSMutableString* const buffer = [[NSMutableString alloc] initWithCapacity:1024];
+
+Debug::DebugStream& Debug::flush(Debug::DebugStream& dbg) {
+  Debug::logFinish();
+  return dbg;
+}
+
+void Debug::logStart(Debug::LogLevel level) {
+}
+
+void Debug::logFinish() {
+  NSLog(buffer);
+  [buffer setString:@""];
+}
+
+void Debug::logString(const char* str) {
+  [buffer appendString:[NSString stringWithUTF8String:str]];
+}
diff --git a/plugins/webkit/Plugin/English.lproj/crash.html b/plugins/webkit/Plugin/English.lproj/crash.html
new file mode 100644
index 0000000..040d2f0
--- /dev/null
+++ b/plugins/webkit/Plugin/English.lproj/crash.html
@@ -0,0 +1,27 @@
+<html>
+<head>
+<title>Hosted Mode failure</title>
+<style>
+* {font-family: monospace;}
+h1 {background: blue; color: white;}
+#r {border: thin solid silver; width:100%; height: 50em; white-space: pre; overflow: scroll;}
+</style>
+</head>
+<body>
+<h1>STOP</h1>
+<p>The hosted mode plugin encountered a fatal error and was unable to continue.  Ensure
+that the hosted mode server is running.  You can attempt to restart the module
+by reloading the current page.</p>
+<textarea id="r" wrap="off">
+__MESSAGE__
+
+System version: __SYSTEM_VERSION__
+
+__USER_AGENT__
+
+Compilation time: __DATE__ __TIME__
+
+__BACKTRACE__
+</textarea>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.h b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.h
new file mode 100644
index 0000000..57da6e3
--- /dev/null
+++ b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.h
@@ -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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "GTMNSString+HTML.h"
+
+/*
+ * This adds a convenience method to add HTML-escaped text to an NSMutableString.
+ */
+@interface NSMutableString (NSMutableStringWithHtmlReplacement)
+- (void)replacePattern:(NSString*)pattern
+     withStringLiteral:(NSString*)replacement;
+@end
diff --git a/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.m b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.m
new file mode 100644
index 0000000..ed0f62b
--- /dev/null
+++ b/plugins/webkit/Plugin/NSMutableString+HtmlReplacement.m
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#import "NSMutableString+HtmlReplacement.h"
+
+@implementation NSMutableString (NSMutableStringWithHtmlReplacement)
+- (void)replacePattern:(NSString*)pattern
+     withStringLiteral:(NSString*)replacement {
+  [self replaceOccurrencesOfString:pattern
+                        withString:[replacement gtm_stringByEscapingForHTML]
+                           options:NSLiteralSearch
+                             range:NSMakeRange(0, [self length])];
+}
+@end
diff --git a/plugins/webkit/Plugin/OophmPlugin.h b/plugins/webkit/Plugin/OophmPlugin.h
new file mode 100644
index 0000000..96d0ed3
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmPlugin.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/WebPlugin.h>
+#import "Debug.h"
+#import "OophmWebScriptObject.h"
+#import "SlowScriptProxy.h"
+#import "WebFrameNonTigerHeaders.h"
+
+/*
+ * This provides the entrypoint for the WebKit plugin.  This class performs
+ * any necessary environmental configuration and provides the scripting object
+ * that represents the plugin in the JavaScript environment.
+ */
+@interface OophmPlugin : NSView <WebPlugInViewFactory> {
+@private
+  OophmWebScriptObject* _scriptObject;
+  id _slowScriptProxy;
+}
+
+/*
+ * Defined by the WebPlugInViewFactory protocol to construct an instance of
+ * the plugin.
+ */
++ (NSView *)plugInViewWithArguments:(NSDictionary *)arguments;
+- (void)dealloc;
+
+/*
+ * Called by plugInViewWithArguments to initialize the instance of the plugin.
+ */
+- (id)initWithArguments:(NSDictionary *)arguments;
+
+/*
+ * Specified by the WebPlugIn informal protocol to obtain an object whose
+ * methods will be exposed to the scripting environment.
+ */
+- (id)objectForWebScript;
+
+/*
+ * Defined by WebPlugIn and called when the plugin should shut down.
+ */
+- (void)webPlugInDestroy;
+@end
diff --git a/plugins/webkit/Plugin/OophmPlugin.mm b/plugins/webkit/Plugin/OophmPlugin.mm
new file mode 100644
index 0000000..02552d1
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmPlugin.mm
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#import "OophmPlugin.h"
+#import "OophmWebScriptObject.h"
+#import "SlowScriptProxy.h"
+
+@implementation OophmPlugin
++ (NSView *)plugInViewWithArguments:(NSDictionary *)arguments {
+  return [[[OophmPlugin alloc] initWithArguments: arguments] autorelease];
+}
+
+- (void)dealloc {
+  Debug::log(Debug::Info) << "Plugin deallocated" << Debug::flush;
+  [super dealloc];
+}
+
+- (id)initWithArguments:(NSDictionary *)arguments {
+  Debug::log(Debug::Info) << "Plugin starting" << Debug::flush;
+  self = [super initWithFrame: NSZeroRect];
+  if (!self) {
+    return nil;
+  }
+
+  id container = [[arguments objectForKey:WebPlugInContainerKey] retain];
+  WebFrame* frame = [container webFrame];
+  JSGlobalContextRef contextRef = [frame globalContext];
+  _scriptObject = [[OophmWebScriptObject scriptObjectWithContext:contextRef withWebView:[frame webView]] retain];
+
+  /*
+   * Install a proxy to prevent slow script warnings from being shown by hijacking
+   * the message sent to the original UIDelegate.  We could also use this to prevent
+   * window.alert and window.prompt from blocking test code.
+   */
+  WebView* view = [frame webView];
+  _slowScriptProxy = [[SlowScriptProxy alloc] initWithWebView: view];
+  if ([_slowScriptProxy respondsToSelector:@selector(webView:setStatusText:)]) {
+    [_slowScriptProxy webView:view setStatusText:@"GWT OOPHM Plugin Active"];
+  }
+  
+  return self;
+}
+
+- (id)objectForWebScript {
+  return _scriptObject;
+}
+
+- (void)webPlugInDestroy {
+  Debug::log(Debug::Info) << "Destroying plugin" << Debug::flush;
+  [_scriptObject release];
+  _scriptObject = nil;
+  
+  if ([_slowScriptProxy respondsToSelector:@selector(webView:setStatusText:)]) {
+    [_slowScriptProxy webView:[_slowScriptProxy webView] 
+                      setStatusText:@"GWT OOPHM Session Ended"];
+  }
+  [_slowScriptProxy release];
+  _slowScriptProxy = nil;
+}
+@end
diff --git a/plugins/webkit/Plugin/OophmWebScriptObject.h b/plugins/webkit/Plugin/OophmWebScriptObject.h
new file mode 100644
index 0000000..28f52ce
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmWebScriptObject.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#import <JavaScriptCore/JavaScriptCore.h>
+#import "HostChannel.h"
+#import "WebScriptSessionHandler.h"
+
+@interface OophmWebScriptObject : NSObject {
+@private
+  JSGlobalContextRef _contextRef;
+  CrashHandlerRef _crashHandler;
+  HostChannel* _hostChannel;
+  WebScriptSessionHandlerRef _sessionHandler;
+  WebView* _webView;
+}
++ (void)initialize;
++ (BOOL)isSelectorExcludedFromWebScript: (SEL)selector;
++ (OophmWebScriptObject*)scriptObjectWithContext: (JSGlobalContextRef)context
+                                     withWebView: (WebView*) webView;
++ (NSString*)webScriptNameForSelector: (SEL)selector;
+- (BOOL)connectWithHost: (NSString*) host
+         withModuleName: (NSString*) moduleName
+        withJsniContext: (WebScriptObject*) jsniContext;
+- (void)crashWithMessage: (NSString*)message;
+- (void)dealloc;
+- (void)finalizeForWebScript;
+@end
+
diff --git a/plugins/webkit/Plugin/OophmWebScriptObject.mm b/plugins/webkit/Plugin/OophmWebScriptObject.mm
new file mode 100644
index 0000000..f737fd8
--- /dev/null
+++ b/plugins/webkit/Plugin/OophmWebScriptObject.mm
@@ -0,0 +1,302 @@
+/*
+ * 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 <map>
+#import <JavaScriptCore/JavaScriptCore.h>
+#import <WebKit/WebKit.h>
+#import "BrowserChannel.h"
+#import "Debug.h"
+#import "GTMStackTrace.h"
+#import "GTMSystemVersion.h"
+#import "NSMutableString+HtmlReplacement.h"
+#import "LoadModuleMessage.h"
+#import "OophmWebScriptObject.h"
+#import "SessionHandler.h"
+
+/*
+ * This is a helper shim to bridge crash events from the core cpp code to the
+ * objc plugin and UI layer.
+ */
+class PluginCrashHandler : public CrashHandler {
+public:
+  PluginCrashHandler(OophmWebScriptObject* obj) : obj(obj) {
+  }
+  
+  virtual void crash(const char* functionName, const char* message) {
+    Debug::log(Debug::Error) << "Crashing with message: "<< message << Debug::flush;
+    NSString* str = [NSString stringWithFormat:@"%s\n\n%s", message, functionName];
+    [obj crashWithMessage:str];
+  }
+private:
+  OophmWebScriptObject* const obj;
+};
+
+@interface OophmWebScriptObject (Private)
++ (void)logAndThrowString: (NSString*)message;
+- (void)addAllowedHost: (NSString*)host;
+- (void)connectAlertDidEnd: (NSAlert*)alert
+                returnCode: (int)returnCode
+               contextInfo: (void*)contextInfo;
+- (BOOL)doConnectWithHost: (NSString*) host
+               withModule: (NSString*) moduleName;
+@end
+
+@implementation OophmWebScriptObject
++ (void)initialize {
+  // Add the plugin's bundle name to the user defaults search path
+  NSBundle* pluginBundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
+  NSString* bundleIdentifier = [pluginBundle bundleIdentifier];
+  NSUserDefaults* shared = [NSUserDefaults standardUserDefaults];
+  [shared addSuiteNamed:bundleIdentifier];
+}
+
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector {
+  if (selector == @selector(connectWithHost:withModuleName:withJsniContext:)) {
+    return NO;
+  } else if (selector == @selector(crashWithMessage:)) {
+    return NO;
+  }
+
+  return YES;
+}
+
++ (OophmWebScriptObject*)scriptObjectWithContext: (JSGlobalContextRef) context
+                                     withWebView: (WebView*) webView {
+  JSGlobalContextRetain(context);
+  OophmWebScriptObject* obj = [[[OophmWebScriptObject alloc] init] autorelease];
+  obj->_contextRef = context;
+  obj->_webView = [webView retain];
+  return obj;
+}
+
++ (NSString*)webScriptNameForSelector: (SEL)selector {
+  if (selector == @selector(connectWithHost:withModuleName:withJsniContext:)) {
+    return @"connect";
+  } else if (selector == @selector(crashWithMessage:)) {
+    return @"crash";
+  }
+  return nil;
+}
+
+- (BOOL)connectWithHost: (NSString*) host
+         withModuleName: (NSString*) moduleName
+        withJsniContext: (WebScriptObject*) jsniContext {
+  
+  // TODO remove this for production builds
+  Debug::log(Debug::Warning) << "ACLs are currently disabled" << Debug::flush;
+  return [self doConnectWithHost:host withModule:moduleName];
+
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+
+  // See if authentication has been bypassed
+  if ([defaults boolForKey:@"allowAll"]) {
+    return [self doConnectWithHost:host withModule:moduleName];
+  }
+  
+  // Otherwise, check for an explicit entry
+  NSArray* allowedHosts = [defaults arrayForKey:@"allowedHosts"];
+  if (allowedHosts != nil) {
+    NSArray* hostParts = [host componentsSeparatedByString:@":"];
+    if ([allowedHosts containsObject:[hostParts objectAtIndex:0]]) {
+      return [self doConnectWithHost:host withModule:moduleName];
+    }
+  }
+  
+  // Otherwise, bring up an alert dialog
+  NSAlert* alert = [NSAlert alertWithMessageText:@"Initiate hosted-mode session"
+                                   defaultButton:@"Deny"
+                                 alternateButton:nil
+                                     otherButton:@"Allow"
+                       informativeTextWithFormat:@"The current web-page would like to initiate a hosted-mode connection to %@", host];
+  
+  if ([alert respondsToSelector:@selector(setShowsSuppressionButton:)]) {
+    [alert setShowsSuppressionButton:YES];
+    [[alert suppressionButton] setTitle:@"Always allow connections to this host"];
+  } else {
+    [[alert addButtonWithTitle:@"Always allow"] setTag:NSAlertAlternateReturn];
+  }
+  
+  NSBundle* bundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
+  NSArray* contextArray = [[NSArray arrayWithObjects:[host retain],
+                            [moduleName retain], nil] retain];
+  NSString* imagePath = [bundle pathForImageResource:@"gwtlogo"];
+  if (imagePath != nil) {
+    NSImage* img = [[[NSImage alloc] initByReferencingFile:imagePath] autorelease];
+    [alert setIcon:img];
+  }
+  
+  [alert beginSheetModalForWindow:[_webView hostWindow]
+                    modalDelegate:self
+                   didEndSelector:@selector(connectAlertDidEnd:returnCode:contextInfo:)
+                      contextInfo:contextArray];
+  return YES;
+}
+
+- (void)crashWithMessage: (NSString*)message {
+  NSBundle* oophmBundle = [NSBundle bundleForClass:[self class]];
+  NSString* path = [oophmBundle pathForResource:@"crash" ofType:@"html"];
+  NSMutableString* crashPage = [NSMutableString stringWithContentsOfFile:path];
+  [crashPage replacePattern:@"__MESSAGE__" withStringLiteral:message];
+  
+  long major, minor, bugFix;
+  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
+  NSString* systemVersion = [NSString stringWithFormat:@"%i.%i.%i", major, minor, bugFix];
+  [crashPage replacePattern:@"__SYSTEM_VERSION__" withStringLiteral:systemVersion];
+  
+  NSString* ua = [_webView userAgentForURL:[NSURL URLWithString:@"about:blank"]];
+  [crashPage replacePattern:@"__USER_AGENT__" withStringLiteral:ua];
+  
+  [crashPage replacePattern:@"__DATE__"
+          withStringLiteral:[NSString stringWithUTF8String:__DATE__]];
+  [crashPage replacePattern:@"__TIME__"
+          withStringLiteral:[NSString stringWithUTF8String:__TIME__]];  
+  
+  NSString* trace = GTMStackTrace();
+  [crashPage replacePattern:@"__BACKTRACE__" withStringLiteral:trace];
+  
+
+  NSURL* currentUrl = [[[[_webView mainFrame] dataSource] response] URL];
+  
+  [[_webView mainFrame] loadAlternateHTMLString:crashPage
+                                        baseURL:[NSURL fileURLWithPath:path]
+                              forUnreachableURL:currentUrl];
+}
+
+- (void)dealloc {
+  [_webView release];  
+  delete _crashHandler;
+  [super dealloc];
+}
+
+- (void)finalizeForWebScript {
+  Debug::log(Debug::Info) << "Finalizing OophmWebScriptObject" << Debug::flush;
+  
+  // Free memory
+  delete _sessionHandler;
+  
+  if (_hostChannel) {
+    _hostChannel->disconnectFromHost();
+    delete _hostChannel;
+    _hostChannel = NULL;
+  }
+
+  if (_contextRef) {
+    JSGlobalContextRelease(_contextRef);
+    _contextRef = NULL;
+  }
+}
+@end
+
+@implementation OophmWebScriptObject (Private)
++ (void)logAndThrowString:(NSString*)message {
+  Debug::log(Debug::Info) << "Throwing exception from WSO: " << message << Debug::flush;
+  [WebScriptObject throwException:message];
+}
+
+- (void)addAllowedHost:(NSString*)host {
+  /*
+   * This is more complicated than usual because we're not using the
+   * application's default persestent domain.  Instead, we use a plugin-specific
+   * domain.
+   */
+  NSBundle* pluginBundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
+  NSString* bundleIdentifier = [pluginBundle bundleIdentifier];
+  
+  NSUserDefaults* shared = [NSUserDefaults standardUserDefaults];
+  NSDictionary* pluginDict = [shared persistentDomainForName:bundleIdentifier];
+  NSArray* allowedHosts = [pluginDict objectForKey:@"allowedHosts"];
+  
+  NSMutableArray* mutableHosts = [NSMutableArray arrayWithArray:allowedHosts];
+  NSMutableDictionary* mutableDict = [NSMutableDictionary dictionaryWithDictionary:pluginDict];
+  [mutableHosts addObject:host];
+  [mutableDict setObject:mutableHosts forKey:@"allowedHosts"];
+  [shared setPersistentDomain:mutableDict forName:bundleIdentifier];
+  [shared synchronize];
+}
+
+- (void)connectAlertDidEnd:(NSAlert *)alert
+                returnCode:(int)returnCode
+               contextInfo:(void *)contextInfo {
+  NSArray* contextArray = (NSArray*) contextInfo;
+  NSString* host = [[contextArray objectAtIndex:0] autorelease];
+  NSString* moduleName = [[contextArray objectAtIndex:1] autorelease];
+  [contextArray release];
+  
+  if (returnCode == NSAlertDefaultReturn) {
+    return;
+  } else if (returnCode == NSAlertAlternateReturn ||
+             [alert respondsToSelector:@selector(suppressionButton)] &&
+             [[alert suppressionButton] state] == NSOnState) {
+    NSArray* hostParts = [host componentsSeparatedByString:@":"];
+    [self addAllowedHost:[hostParts objectAtIndex:0]];
+  }
+
+  [self doConnectWithHost:host withModule:moduleName];
+}
+
+- (BOOL)doConnectWithHost:(NSString*) host
+               withModule:(NSString*) moduleName {
+  Debug::log(Debug::Debugging) << "connect : " << [host UTF8String] << " " <<
+      [moduleName UTF8String] << Debug::flush;
+  
+  if (_hostChannel != NULL) {
+    [OophmWebScriptObject logAndThrowString:@"Already connected"];
+    return NO;
+  }
+  
+  NSArray *parts = [host componentsSeparatedByString:@":"];
+  if ([parts count] != 2) {
+    [OophmWebScriptObject logAndThrowString:
+     [NSString stringWithFormat:@"Incorrect format for host string %i",
+      [parts count]]];
+    return NO;
+  }
+  
+  NSString *hostPart = [parts objectAtIndex:0];
+  NSString *portPart = [parts objectAtIndex:1];
+  
+  Debug::log(Debug::Debugging) << "Extracted host: " << [hostPart UTF8String] <<
+      " and port: " << [portPart UTF8String] << Debug::flush;
+  
+  char *hostAsChars = const_cast<char*>([hostPart UTF8String]);
+  unsigned portAsInt = [portPart intValue];
+  
+  _hostChannel = new HostChannel();
+  if (!_hostChannel->connectToHost(hostAsChars, portAsInt)) {
+    [OophmWebScriptObject logAndThrowString:@"HostChannel failed to connect"];
+    delete _hostChannel;
+    _hostChannel = NULL;
+    return NO;
+  }
+  
+  const char *moduleNameChars = [moduleName UTF8String];
+  
+  _crashHandler = new PluginCrashHandler(self);
+  _sessionHandler = new WebScriptSessionHandler(_hostChannel, _contextRef, _crashHandler);
+  
+  if (!LoadModuleMessage::send(*_hostChannel, BROWSERCHANNEL_PROTOCOL_VERSION,
+                               moduleNameChars, strlen(moduleNameChars),
+                               "Safari OOPHM", _sessionHandler)) {
+    _hostChannel->disconnectFromHost();
+    delete _hostChannel;
+    _hostChannel = NULL;
+    [OophmWebScriptObject logAndThrowString:@"Unable to load module"];
+    return NO;
+  }  
+  
+  return YES;
+}
+@end
diff --git a/plugins/webkit/Plugin/SlowScriptProxy.h b/plugins/webkit/Plugin/SlowScriptProxy.h
new file mode 100644
index 0000000..f46ab94
--- /dev/null
+++ b/plugins/webkit/Plugin/SlowScriptProxy.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <WebKit/WebKit.h>
+
+/*
+ * This NSProxy is used to prevent slow-script warnings from surfacing in the
+ * web browser.  This is something of a hack since the message that we want
+ * to override isn't public, but there's no way to directly reset the slow-scipt
+ * timer either.
+ */
+@interface SlowScriptProxy : NSProxy {
+@private
+  id _target;
+  WebView* _webView;
+}
+
+/*
+ * This will restore the original UIDelegate.
+ */
+- (void)dealloc;
+
+/*
+ * The proxy object will install itself as the UIDelegate on the given webView.
+ */
+- (id)initWithWebView: (WebView*)webView;
+
+/*
+ * Just delegates the invocation to the original UIDelegate.
+ */
+- (void)forwardInvocation:(NSInvocation *)anInvocation;
+
+/*
+ * Just delegates the invocation to the original UIDelegate.
+ */
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
+
+/*
+ * The WebView to which the proxy object has attached itself.
+ */
+- (WebView*)webView;
+
+/*
+ * This is the message that we want to intercept.
+ */
+- (BOOL)webViewShouldInterruptJavaScript:(WebView *)sender;
+@end
diff --git a/plugins/webkit/Plugin/SlowScriptProxy.m b/plugins/webkit/Plugin/SlowScriptProxy.m
new file mode 100644
index 0000000..8798ada
--- /dev/null
+++ b/plugins/webkit/Plugin/SlowScriptProxy.m
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#import "SlowScriptProxy.h"
+
+@implementation SlowScriptProxy
+- (id)initWithWebView:(WebView*)webView {
+  _target = [[webView UIDelegate] retain];
+  _webView = [webView retain];
+  [_webView setUIDelegate:self];
+  return self;
+}
+
+- (void)dealloc {
+  // Restore the original delegate
+  [_webView setUIDelegate:_target];
+  [_webView release];
+  [_target release];
+  [super dealloc];
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+  [anInvocation setTarget:_target];
+  [anInvocation invoke];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
+  return [_target methodSignatureForSelector:aSelector];
+}
+
+- (WebView*)webView {
+  return _webView;
+}
+
+- (BOOL)webViewShouldInterruptJavaScript:(WebView *)sender {
+  // TODO: (robertvawter) What do we want to do with repeated invocations?
+  return NO;
+}
+
+@end
diff --git a/plugins/webkit/Plugin/WebFrameNonTigerHeaders.h b/plugins/webkit/Plugin/WebFrameNonTigerHeaders.h
new file mode 100644
index 0000000..975ea6d
--- /dev/null
+++ b/plugins/webkit/Plugin/WebFrameNonTigerHeaders.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+#import <JavaScriptCore/JavaScriptCore.h>
+
+/*!
+ * The headers in Tiger don't include the globalContext method.
+ */
+@interface WebFrame (NonTigerHeaders)
+- (JSGlobalContextRef) globalContext;
+@end
\ No newline at end of file
diff --git a/plugins/webkit/build.xml b/plugins/webkit/build.xml
new file mode 100755
index 0000000..34fee9e
--- /dev/null
+++ b/plugins/webkit/build.xml
@@ -0,0 +1,18 @@
+<project name="webkit" default="build" basedir=".">
+	<property name="plugin.root" value="webkit" />
+	<import file="../common.ant.xml" />
+
+	<target name="build" description="Copy compiled plugin to the output folder">
+		<mkdir dir="${gwt.build.out}/plugins" />
+		<mkdir dir="${gwt.build.out}/plugins/webkit" />
+		<copy todir="${gwt.build.out}/plugins/webkit">
+			<fileset file="prebuilt/oophm.dmg" />
+		</copy>
+	</target>
+
+	<target name="test" description="Run any tests">
+	</target>
+
+	<target name="checkstyle" description="Static style analysis">
+	</target>
+</project>
diff --git a/plugins/webkit/gwtlogo.icns b/plugins/webkit/gwtlogo.icns
new file mode 100644
index 0000000..531d676
--- /dev/null
+++ b/plugins/webkit/gwtlogo.icns
Binary files differ
diff --git a/plugins/webkit/oophm.pmdoc/01oophm-contents.xml b/plugins/webkit/oophm.pmdoc/01oophm-contents.xml
new file mode 100644
index 0000000..5c9517c
--- /dev/null
+++ b/plugins/webkit/oophm.pmdoc/01oophm-contents.xml
@@ -0,0 +1 @@
+<pkg-contents spec="1.12"><f n="oophm.webplugin" o="root" g="admin" p="16893" pt="/Users/robertvawter/gwt/oophm/plugins/webkit/build/Release/oophm.webplugin" m="true" t="file"><f n="Contents" o="root" g="admin" p="16893"><f n="Info.plist" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="MacOS" o="root" g="admin" p="16893"><f n="oophm" o="root" g="admin" p="33277"><mod>mode</mod></f><mod>mode</mod></f><f n="Resources" o="root" g="admin" p="16893"><f n="English.lproj" o="root" g="admin" p="16893"><f n="crash.html" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="InfoPlist.strings" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><f n="gwtlogo.icns" o="root" g="admin" p="33204"><mod>mode</mod></f><f n="README.google" o="root" g="admin" p="33204"><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f><mod>mode</mod></f></pkg-contents>
\ No newline at end of file
diff --git a/plugins/webkit/oophm.pmdoc/01oophm.xml b/plugins/webkit/oophm.pmdoc/01oophm.xml
new file mode 100644
index 0000000..ca52096
--- /dev/null
+++ b/plugins/webkit/oophm.pmdoc/01oophm.xml
@@ -0,0 +1 @@
+<pkgref spec="1.12" uuid="417BF300-1147-478E-9359-100836B507EE"><config><identifier>com.google.gwt.oophm.pkg</identifier><version>1</version><description></description><post-install type="none"/><requireAuthorization/><installFrom relative="true" mod="true" includeRoot="true">build/Release/oophm.webplugin</installFrom><installTo mod="true">/Library/Internet Plug-Ins</installTo><flags><followSymbolicLinks/><mod>overwriteDirectoryPermissions</mod></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>installTo</mod><mod>requireAuthorization</mod><mod>installFrom.isRelativeType</mod><mod>installTo.path</mod><mod>installFrom.path</mod><mod>identifier</mod><mod>includeRoot</mod></config><contents><file-list>01oophm-contents.xml</file-list><component id="com.google.gwt.oophm" path="/Users/robertvawter/gwt/oophm/plugins/webkit/build/Release/oophm.webplugin" version="0.1"/><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>
\ No newline at end of file
diff --git a/plugins/webkit/oophm.pmdoc/index.xml b/plugins/webkit/oophm.pmdoc/index.xml
new file mode 100644
index 0000000..872d10b
--- /dev/null
+++ b/plugins/webkit/oophm.pmdoc/index.xml
@@ -0,0 +1,15 @@
+<pkmkdoc spec="1.12"><properties><title>GWT Out-of-Process Hosted Mode Plugins</title><build>/Users/robertvawter/Desktop/GWT Out-of-Process Hosted Mode Plugin.mpkg</build><organization>com.google.gwt</organization><userSees ui="custom"/><min-target os="2"/><domain system="true"/></properties><distribution><versions min-spec="1.000000"/><scripts></scripts></distribution><contents><choice title="WebKit Plugin" id="webkit" description="This plugin support WebKit-based browsers, such as Safari and Shiira.  Any other application that makes use of WebKit will also be able to load this plugin." starts_selected="true" starts_enabled="true" starts_hidden="false"><pkgref id="com.google.gwt.oophm.pkg"/></choice></contents><resources bg-scale="none" bg-align="bottomleft"><locale lang="en"><resource relative="true" mod="true" type="background">gwtlogo.icns</resource><resource relative="true" mod="true" type="license">../../distro-source/core/src/COPYING.html</resource><resource relative="true" mod="true" type="readme">../../distro-source/core/src/index.html</resource><resource mime-type="text/rtf" kind="embedded" type="welcome"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf270
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f0\fs26 \cf0 This package contains browser plugins that allow the Google Web Toolkit hosted-mode system to interact with various browsers installed on your computer.\
+\
+These plugins 
+\b are not required
+\b0  to view web pages with GWT modules; they are only necessary if you are writing GWT applications and wish to debug them.}]]></resource><resource mime-type="text/rtf" kind="embedded" type="conclusion"><![CDATA[{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf270
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f0\fs26 \cf0 Restart any WebKit-based browsers in order to use the plugin.}]]></resource></locale></resources><flags/><item type="file">01oophm.xml</item><mod>properties.customizeOption</mod><mod>properties.userDomain</mod><mod>properties.title</mod><mod>description</mod><mod>properties.systemDomain</mod><mod>properties.anywhereDomain</mod></pkmkdoc>
\ No newline at end of file
diff --git a/plugins/webkit/oophm.xcodeproj/project.pbxproj b/plugins/webkit/oophm.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..d788230
--- /dev/null
+++ b/plugins/webkit/oophm.xcodeproj/project.pbxproj
@@ -0,0 +1,833 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 42;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		48420E420DD52761001F3839 /* oophm.dmg */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 48420E5A0DD527AD001F3839 /* Build configuration list for PBXAggregateTarget "oophm.dmg" */;
+			buildPhases = (
+				48420E460DD52768001F3839 /* ShellScript */,
+			);
+			dependencies = (
+				48420E480DD5278D001F3839 /* PBXTargetDependency */,
+			);
+			name = oophm.dmg;
+			productName = oophm_package;
+		};
+		48547E030DD882170047AC8A /* symlinks */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = 48547E080DD8823B0047AC8A /* Build configuration list for PBXAggregateTarget "symlinks" */;
+			buildPhases = (
+				48547E020DD882170047AC8A /* Make symlink */,
+			);
+			comments = "This will create a symlink in ~/Library/Internet Plug-Ins to the plugin";
+			dependencies = (
+				48547E070DD8821D0047AC8A /* PBXTargetDependency */,
+			);
+			name = symlinks;
+			productName = oophm.symlink;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		480DDCAA0E381E22000711F4 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A23BB50DD0E688004EF5CA /* AppController.m */; };
+		480DDCAB0E381E23000711F4 /* BrowserWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A23C770DD0F545004EF5CA /* BrowserWindow.m */; };
+		480DDCAC0E381E28000711F4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 48A23BB60DD0E688004EF5CA /* main.m */; };
+		48108DDF0E2C15BD007FA76C /* AllowedConnections.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48108DDB0E2C15BD007FA76C /* AllowedConnections.cpp */; };
+		48108DE00E2C15BD007FA76C /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48108DDD0E2C15BD007FA76C /* Socket.cpp */; };
+		48338DDF0E4A2CA7008ACF0F /* oophm_bypass.plist in Resources */ = {isa = PBXBuildFile; fileRef = 48338DDB0E4A2C49008ACF0F /* oophm_bypass.plist */; };
+		48420D410DD51A3D001F3839 /* GTMNSString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 48420D3E0DD51A3D001F3839 /* GTMNSString+HTML.m */; };
+		48420D420DD51A3D001F3839 /* GTMStackTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 48420D3F0DD51A3D001F3839 /* GTMStackTrace.c */; };
+		4851A9D50DD1198300C577B2 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */; };
+		48547F000DD889DA0047AC8A /* GTMSystemVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 48547EFF0DD889DA0047AC8A /* GTMSystemVersion.m */; };
+		48547F4B0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m in Sources */ = {isa = PBXBuildFile; fileRef = 48547F4A0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m */; };
+		485505ED0DCD475C0009536F /* SlowScriptProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 485505EC0DCD475C0009536F /* SlowScriptProxy.m */; };
+		4856DF890DCF95B8000BF47C /* HostChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF750DCF95B8000BF47C /* HostChannel.cpp */; };
+		4856DF8A0DCF95B8000BF47C /* InvokeMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF770DCF95B8000BF47C /* InvokeMessage.cpp */; };
+		4856DF8B0DCF95B8000BF47C /* LoadModuleMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF790DCF95B8000BF47C /* LoadModuleMessage.cpp */; };
+		4856DF8E0DCF95B8000BF47C /* ReturnMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF7F0DCF95B8000BF47C /* ReturnMessage.cpp */; };
+		4856DF8F0DCF95B8000BF47C /* README.google in Resources */ = {isa = PBXBuildFile; fileRef = 4856DF820DCF95B8000BF47C /* README.google */; };
+		4856DF900DCF95B8000BF47C /* ServerMethods.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4856DF840DCF95B8000BF47C /* ServerMethods.cpp */; };
+		485CCFF00DDDDEA400AEE666 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 485CCFEF0DDDDEA400AEE666 /* CoreFoundation.framework */; };
+		485CD0AA0DDDEAF300AEE666 /* Debug.mm in Sources */ = {isa = PBXBuildFile; fileRef = 485CD0A90DDDEAF300AEE666 /* Debug.mm */; };
+		486DA8F50DD22BD50065980B /* crash.html in Resources */ = {isa = PBXBuildFile; fileRef = 486DA8F40DD22BD50065980B /* crash.html */; };
+		48A237D10DCFB46D004EF5CA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
+		48A23BC60DD0E6EE004EF5CA /* browser.nib in Resources */ = {isa = PBXBuildFile; fileRef = 48A23BC50DD0E6EE004EF5CA /* browser.nib */; };
+		48A23BE00DD0E8B1004EF5CA /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A10DC62FD800E011A2 /* WebKit.framework */; };
+		48A23BE10DD0E8B6004EF5CA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
+		48A23C510DD0F2D6004EF5CA /* Browser-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 48A23C500DD0F2D6004EF5CA /* Browser-Info.plist */; };
+		48A23C530DD0F302004EF5CA /* gwtlogo.icns in Resources */ = {isa = PBXBuildFile; fileRef = 48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */; };
+		48ABDDC50DCBA04800B0159A /* WebScriptSessionHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48ABDDC40DCBA04800B0159A /* WebScriptSessionHandler.cpp */; };
+		48C4D72E0DCA2B6900C34919 /* gwtlogo.icns in Resources */ = {isa = PBXBuildFile; fileRef = 48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */; };
+		48C9EA4A0E37863700E691C6 /* FreeValueMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48C9EA440E37863700E691C6 /* FreeValueMessage.cpp */; };
+		48C9EA4B0E37863700E691C6 /* InvokeSpecialMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48C9EA460E37863700E691C6 /* InvokeSpecialMessage.cpp */; };
+		48C9EA4C0E37863700E691C6 /* LoadJsniMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48C9EA480E37863700E691C6 /* LoadJsniMessage.cpp */; };
+		48EF692D0E318E200050F5D6 /* ObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 48EF692C0E318E200050F5D6 /* ObjectFunctions.cpp */; };
+		48FD98900DC62E7400E011A2 /* OophmPlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 48FD988F0DC62E7400E011A2 /* OophmPlugin.mm */; };
+		48FD98A20DC62FD800E011A2 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */; };
+		48FD98A30DC62FD800E011A2 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48FD98A10DC62FD800E011A2 /* WebKit.framework */; };
+		48FD99540DC6349F00E011A2 /* OophmWebScriptObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 48FD99530DC6349F00E011A2 /* OophmWebScriptObject.mm */; };
+		8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		48420E470DD5278D001F3839 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
+			remoteInfo = oophm;
+		};
+		48547E060DD8821D0047AC8A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
+			remoteInfo = oophm;
+		};
+		485CD0C40DDDED1700AEE666 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 48547E030DD882170047AC8A;
+			remoteInfo = symlinks;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+		32DBCF630370AF2F00C91783 /* oophm_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oophm_Prefix.pch; sourceTree = "<group>"; };
+		48108DDB0E2C15BD007FA76C /* AllowedConnections.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AllowedConnections.cpp; sourceTree = "<group>"; };
+		48108DDC0E2C15BD007FA76C /* AllowedConnections.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllowedConnections.h; sourceTree = "<group>"; };
+		48108DDD0E2C15BD007FA76C /* Socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Socket.cpp; sourceTree = "<group>"; };
+		48108DDE0E2C15BD007FA76C /* Socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Socket.h; sourceTree = "<group>"; };
+		48338DDB0E4A2C49008ACF0F /* oophm_bypass.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = oophm_bypass.plist; sourceTree = "<group>"; };
+		48420D3C0DD51A23001F3839 /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMDefines.h; path = GTM/GTMDefines.h; sourceTree = "<group>"; };
+		48420D3D0DD51A3D001F3839 /* GTMNSString+HTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GTMNSString+HTML.h"; path = "GTM/Foundation/GTMNSString+HTML.h"; sourceTree = "<group>"; };
+		48420D3E0DD51A3D001F3839 /* GTMNSString+HTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "GTMNSString+HTML.m"; path = "GTM/Foundation/GTMNSString+HTML.m"; sourceTree = "<group>"; };
+		48420D3F0DD51A3D001F3839 /* GTMStackTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GTMStackTrace.c; path = GTM/Foundation/GTMStackTrace.c; sourceTree = "<group>"; };
+		48420D400DD51A3D001F3839 /* GTMStackTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMStackTrace.h; path = GTM/Foundation/GTMStackTrace.h; sourceTree = "<group>"; };
+		48547EFE0DD889DA0047AC8A /* GTMSystemVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMSystemVersion.h; path = GTM/Foundation/GTMSystemVersion.h; sourceTree = "<group>"; };
+		48547EFF0DD889DA0047AC8A /* GTMSystemVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMSystemVersion.m; path = GTM/Foundation/GTMSystemVersion.m; sourceTree = "<group>"; };
+		48547F490DD88D110047AC8A /* NSMutableString+HtmlReplacement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableString+HtmlReplacement.h"; sourceTree = "<group>"; };
+		48547F4A0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableString+HtmlReplacement.m"; sourceTree = "<group>"; };
+		485505EB0DCD475C0009536F /* SlowScriptProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlowScriptProxy.h; sourceTree = "<group>"; };
+		485505EC0DCD475C0009536F /* SlowScriptProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SlowScriptProxy.m; sourceTree = "<group>"; };
+		4856DF740DCF95B8000BF47C /* BrowserChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrowserChannel.h; path = ../common/BrowserChannel.h; sourceTree = SOURCE_ROOT; };
+		4856DF750DCF95B8000BF47C /* HostChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HostChannel.cpp; path = ../common/HostChannel.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF760DCF95B8000BF47C /* HostChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostChannel.h; path = ../common/HostChannel.h; sourceTree = SOURCE_ROOT; };
+		4856DF770DCF95B8000BF47C /* InvokeMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InvokeMessage.cpp; path = ../common/InvokeMessage.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF780DCF95B8000BF47C /* InvokeMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InvokeMessage.h; path = ../common/InvokeMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF790DCF95B8000BF47C /* LoadModuleMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LoadModuleMessage.cpp; path = ../common/LoadModuleMessage.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF7A0DCF95B8000BF47C /* LoadModuleMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LoadModuleMessage.h; path = ../common/LoadModuleMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF7D0DCF95B8000BF47C /* Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Message.h; path = ../common/Message.h; sourceTree = SOURCE_ROOT; };
+		4856DF7E0DCF95B8000BF47C /* QuitMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuitMessage.h; path = ../common/QuitMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF7F0DCF95B8000BF47C /* ReturnMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ReturnMessage.cpp; path = ../common/ReturnMessage.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF800DCF95B8000BF47C /* ReturnMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReturnMessage.h; path = ../common/ReturnMessage.h; sourceTree = SOURCE_ROOT; };
+		4856DF820DCF95B8000BF47C /* README.google */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.google; path = ../common/scoped_ptr/README.google; sourceTree = SOURCE_ROOT; };
+		4856DF830DCF95B8000BF47C /* scoped_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scoped_ptr.h; path = ../common/scoped_ptr/scoped_ptr.h; sourceTree = SOURCE_ROOT; };
+		4856DF840DCF95B8000BF47C /* ServerMethods.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ServerMethods.cpp; path = ../common/ServerMethods.cpp; sourceTree = SOURCE_ROOT; };
+		4856DF850DCF95B8000BF47C /* ServerMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ServerMethods.h; path = ../common/ServerMethods.h; sourceTree = SOURCE_ROOT; };
+		4856DF860DCF95B8000BF47C /* SessionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SessionHandler.h; path = ../common/SessionHandler.h; sourceTree = SOURCE_ROOT; };
+		4856DF880DCF95B8000BF47C /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = ../common/Value.h; sourceTree = SOURCE_ROOT; };
+		485CCE650DDDC5E900AEE666 /* HashMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashMap.h; sourceTree = "<group>"; };
+		485CCFEF0DDDDEA400AEE666 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+		485CD0A90DDDEAF300AEE666 /* Debug.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Debug.mm; sourceTree = "<group>"; };
+		486DA8ED0DD22B850065980B /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = English; path = English.lproj/crash.html; sourceTree = "<group>"; wrapsLines = 0; };
+		48A23BA20DD0E5B4004EF5CA /* Browser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Browser.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		48A23BB40DD0E688004EF5CA /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = "<group>"; };
+		48A23BB50DD0E688004EF5CA /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = "<group>"; };
+		48A23BB60DD0E688004EF5CA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		48A23BC50DD0E6EE004EF5CA /* browser.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = browser.nib; sourceTree = "<group>"; };
+		48A23C500DD0F2D6004EF5CA /* Browser-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Browser-Info.plist"; sourceTree = "<group>"; };
+		48A23C760DD0F545004EF5CA /* BrowserWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BrowserWindow.h; sourceTree = "<group>"; };
+		48A23C770DD0F545004EF5CA /* BrowserWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BrowserWindow.m; sourceTree = "<group>"; };
+		48ABDDC30DCBA04800B0159A /* WebScriptSessionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptSessionHandler.h; sourceTree = "<group>"; };
+		48ABDDC40DCBA04800B0159A /* WebScriptSessionHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebScriptSessionHandler.cpp; sourceTree = "<group>"; };
+		48ABDDC80DCBA09D00B0159A /* TrackingData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackingData.h; sourceTree = "<group>"; };
+		48ABE1050DCBB67600B0159A /* SessionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SessionData.h; sourceTree = "<group>"; };
+		48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = gwtlogo.icns; sourceTree = "<group>"; };
+		48C9EA440E37863700E691C6 /* FreeValueMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FreeValueMessage.cpp; sourceTree = "<group>"; };
+		48C9EA450E37863700E691C6 /* FreeValueMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FreeValueMessage.h; sourceTree = "<group>"; };
+		48C9EA460E37863700E691C6 /* InvokeSpecialMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InvokeSpecialMessage.cpp; sourceTree = "<group>"; };
+		48C9EA470E37863700E691C6 /* InvokeSpecialMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InvokeSpecialMessage.h; sourceTree = "<group>"; };
+		48C9EA480E37863700E691C6 /* LoadJsniMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadJsniMessage.cpp; sourceTree = "<group>"; };
+		48C9EA490E37863700E691C6 /* LoadJsniMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadJsniMessage.h; sourceTree = "<group>"; };
+		48D5795D0DDB8C03005A3498 /* Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Debug.h; sourceTree = "<group>"; };
+		48D5795E0DDB8C03005A3498 /* DebugLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugLevel.h; sourceTree = "<group>"; };
+		48EF692B0E318E200050F5D6 /* ObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFunctions.h; sourceTree = "<group>"; };
+		48EF692C0E318E200050F5D6 /* ObjectFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFunctions.cpp; sourceTree = "<group>"; };
+		48FD988E0DC62E7400E011A2 /* OophmPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OophmPlugin.h; sourceTree = "<group>"; };
+		48FD988F0DC62E7400E011A2 /* OophmPlugin.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OophmPlugin.mm; sourceTree = "<group>"; };
+		48FD989B0DC62F8800E011A2 /* WebFrameNonTigerHeaders.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebFrameNonTigerHeaders.h; sourceTree = "<group>"; };
+		48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = /System/Library/Frameworks/JavaScriptCore.framework; sourceTree = "<absolute>"; };
+		48FD98A10DC62FD800E011A2 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = /System/Library/Frameworks/WebKit.framework; sourceTree = "<absolute>"; };
+		48FD99520DC6349F00E011A2 /* OophmWebScriptObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OophmWebScriptObject.h; sourceTree = "<group>"; };
+		48FD99530DC6349F00E011A2 /* OophmWebScriptObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OophmWebScriptObject.mm; sourceTree = "<group>"; };
+		48FFCFC80DD35DA900805659 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Platform.h; sourceTree = "<group>"; };
+		8D5B49B6048680CD000E48DA /* oophm.webplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = oophm.webplugin; sourceTree = BUILT_PRODUCTS_DIR; };
+		8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
+		D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		48A23BA00DD0E5B4004EF5CA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48A23BE00DD0E8B1004EF5CA /* WebKit.framework in Frameworks */,
+				48A23BE10DD0E8B6004EF5CA /* Cocoa.framework in Frameworks */,
+				4851A9D50DD1198300C577B2 /* JavaScriptCore.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D5B49B3048680CD000E48DA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48FD98A20DC62FD800E011A2 /* JavaScriptCore.framework in Frameworks */,
+				48FD98A30DC62FD800E011A2 /* WebKit.framework in Frameworks */,
+				48A237D10DCFB46D004EF5CA /* Cocoa.framework in Frameworks */,
+				485CCFF00DDDDEA400AEE666 /* CoreFoundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		089C166AFE841209C02AAC07 /* oophm */ = {
+			isa = PBXGroup;
+			children = (
+				485506C90DCD54180009536F /* Classes */,
+				48420D3B0DD51A0F001F3839 /* GTM */,
+				32C88E010371C26100C91783 /* Other Sources */,
+				089C167CFE841241C02AAC07 /* Resources */,
+				089C1671FE841209C02AAC07 /* Frameworks and Libraries */,
+				19C28FB8FE9D52D311CA2CBB /* Products */,
+			);
+			comments = "/*\n * Copyright 2008 Google Inc.\n * \n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n * use this file except in compliance with the License. You may obtain a copy of\n * the License at\n * \n * http://www.apache.org/licenses/LICENSE-2.0\n * \n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n * License for the specific language governing permissions and limitations under\n * the License.\n */\n";
+			name = oophm;
+			sourceTree = "<group>";
+		};
+		089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */,
+				1058C7AEFEA557BF11CA2CBB /* Other Frameworks */,
+			);
+			name = "Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		089C167CFE841241C02AAC07 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				48338DDB0E4A2C49008ACF0F /* oophm_bypass.plist */,
+				486DA8F40DD22BD50065980B /* crash.html */,
+				48C4D72D0DCA2B6900C34919 /* gwtlogo.icns */,
+				8D5B49B7048680CD000E48DA /* Info.plist */,
+				089C167DFE841241C02AAC07 /* InfoPlist.strings */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				485CCFEF0DDDDEA400AEE666 /* CoreFoundation.framework */,
+				48FD98A00DC62FD800E011A2 /* JavaScriptCore.framework */,
+				48FD98A10DC62FD800E011A2 /* WebKit.framework */,
+				1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */,
+			);
+			name = "Linked Frameworks";
+			sourceTree = "<group>";
+		};
+		1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				089C167FFE841241C02AAC07 /* AppKit.framework */,
+				D2F7E65807B2D6F200F64583 /* CoreData.framework */,
+				089C1672FE841209C02AAC07 /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		19C28FB8FE9D52D311CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8D5B49B6048680CD000E48DA /* oophm.webplugin */,
+				48A23BA20DD0E5B4004EF5CA /* Browser.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		32C88E010371C26100C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				4856DF730DCF95B8000BF47C /* common */,
+				32DBCF630370AF2F00C91783 /* oophm_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		48420D3B0DD51A0F001F3839 /* GTM */ = {
+			isa = PBXGroup;
+			children = (
+				48547EFE0DD889DA0047AC8A /* GTMSystemVersion.h */,
+				48547EFF0DD889DA0047AC8A /* GTMSystemVersion.m */,
+				48420D3D0DD51A3D001F3839 /* GTMNSString+HTML.h */,
+				48420D3E0DD51A3D001F3839 /* GTMNSString+HTML.m */,
+				48420D3F0DD51A3D001F3839 /* GTMStackTrace.c */,
+				48420D400DD51A3D001F3839 /* GTMStackTrace.h */,
+				48420D3C0DD51A23001F3839 /* GTMDefines.h */,
+			);
+			comments = "We just need a subset of the functionality available in GTM, so we'll pull in only the files we need as opposed to creating a cross-project dependency and having to package the framework in the plugin.";
+			name = GTM;
+			sourceTree = "<group>";
+		};
+		485506C90DCD54180009536F /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				48A23B9D0DD0E57E004EF5CA /* Browser */,
+				4856DFFB0DCFAEFD000BF47C /* Plugin */,
+				4856DFFA0DCFAEBC000BF47C /* Core */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		4856DF730DCF95B8000BF47C /* common */ = {
+			isa = PBXGroup;
+			children = (
+				48C9EA440E37863700E691C6 /* FreeValueMessage.cpp */,
+				48C9EA450E37863700E691C6 /* FreeValueMessage.h */,
+				48C9EA460E37863700E691C6 /* InvokeSpecialMessage.cpp */,
+				48C9EA470E37863700E691C6 /* InvokeSpecialMessage.h */,
+				48C9EA480E37863700E691C6 /* LoadJsniMessage.cpp */,
+				48C9EA490E37863700E691C6 /* LoadJsniMessage.h */,
+				48108DDB0E2C15BD007FA76C /* AllowedConnections.cpp */,
+				48108DDC0E2C15BD007FA76C /* AllowedConnections.h */,
+				48108DDD0E2C15BD007FA76C /* Socket.cpp */,
+				48108DDE0E2C15BD007FA76C /* Socket.h */,
+				485CCE650DDDC5E900AEE666 /* HashMap.h */,
+				48D5795D0DDB8C03005A3498 /* Debug.h */,
+				48D5795E0DDB8C03005A3498 /* DebugLevel.h */,
+				48FFCFC80DD35DA900805659 /* Platform.h */,
+				4856DF740DCF95B8000BF47C /* BrowserChannel.h */,
+				4856DF750DCF95B8000BF47C /* HostChannel.cpp */,
+				4856DF760DCF95B8000BF47C /* HostChannel.h */,
+				4856DF770DCF95B8000BF47C /* InvokeMessage.cpp */,
+				4856DF780DCF95B8000BF47C /* InvokeMessage.h */,
+				4856DF790DCF95B8000BF47C /* LoadModuleMessage.cpp */,
+				4856DF7A0DCF95B8000BF47C /* LoadModuleMessage.h */,
+				4856DF7D0DCF95B8000BF47C /* Message.h */,
+				4856DF7E0DCF95B8000BF47C /* QuitMessage.h */,
+				4856DF7F0DCF95B8000BF47C /* ReturnMessage.cpp */,
+				4856DF800DCF95B8000BF47C /* ReturnMessage.h */,
+				4856DF810DCF95B8000BF47C /* scoped_ptr */,
+				4856DF840DCF95B8000BF47C /* ServerMethods.cpp */,
+				4856DF850DCF95B8000BF47C /* ServerMethods.h */,
+				4856DF860DCF95B8000BF47C /* SessionHandler.h */,
+				4856DF880DCF95B8000BF47C /* Value.h */,
+			);
+			name = common;
+			path = ../common;
+			sourceTree = SOURCE_ROOT;
+		};
+		4856DF810DCF95B8000BF47C /* scoped_ptr */ = {
+			isa = PBXGroup;
+			children = (
+				4856DF820DCF95B8000BF47C /* README.google */,
+				4856DF830DCF95B8000BF47C /* scoped_ptr.h */,
+			);
+			name = scoped_ptr;
+			path = ../common/scoped_ptr;
+			sourceTree = SOURCE_ROOT;
+		};
+		4856DFFA0DCFAEBC000BF47C /* Core */ = {
+			isa = PBXGroup;
+			children = (
+				48ABDDC30DCBA04800B0159A /* WebScriptSessionHandler.h */,
+				48ABDDC40DCBA04800B0159A /* WebScriptSessionHandler.cpp */,
+				48ABDDC80DCBA09D00B0159A /* TrackingData.h */,
+				48ABE1050DCBB67600B0159A /* SessionData.h */,
+				48EF692B0E318E200050F5D6 /* ObjectFunctions.h */,
+				48EF692C0E318E200050F5D6 /* ObjectFunctions.cpp */,
+			);
+			path = Core;
+			sourceTree = "<group>";
+		};
+		4856DFFB0DCFAEFD000BF47C /* Plugin */ = {
+			isa = PBXGroup;
+			children = (
+				485CD0A90DDDEAF300AEE666 /* Debug.mm */,
+				48FD988E0DC62E7400E011A2 /* OophmPlugin.h */,
+				48FD988F0DC62E7400E011A2 /* OophmPlugin.mm */,
+				48FD99520DC6349F00E011A2 /* OophmWebScriptObject.h */,
+				48FD99530DC6349F00E011A2 /* OophmWebScriptObject.mm */,
+				485505EB0DCD475C0009536F /* SlowScriptProxy.h */,
+				485505EC0DCD475C0009536F /* SlowScriptProxy.m */,
+				48FD989B0DC62F8800E011A2 /* WebFrameNonTigerHeaders.h */,
+				48547F490DD88D110047AC8A /* NSMutableString+HtmlReplacement.h */,
+				48547F4A0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m */,
+			);
+			path = Plugin;
+			sourceTree = "<group>";
+		};
+		48A23B9D0DD0E57E004EF5CA /* Browser */ = {
+			isa = PBXGroup;
+			children = (
+				48A23C760DD0F545004EF5CA /* BrowserWindow.h */,
+				48A23C770DD0F545004EF5CA /* BrowserWindow.m */,
+				48A23C500DD0F2D6004EF5CA /* Browser-Info.plist */,
+				48A23BB40DD0E688004EF5CA /* AppController.h */,
+				48A23BB50DD0E688004EF5CA /* AppController.m */,
+				48A23BB60DD0E688004EF5CA /* main.m */,
+				48A23BC50DD0E6EE004EF5CA /* browser.nib */,
+			);
+			path = Browser;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		48A23BA10DD0E5B4004EF5CA /* Browser */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 48A23BA70DD0E5B5004EF5CA /* Build configuration list for PBXNativeTarget "Browser" */;
+			buildPhases = (
+				48A23B9E0DD0E5B4004EF5CA /* Resources */,
+				48A23B9F0DD0E5B4004EF5CA /* Sources */,
+				48A23BA00DD0E5B4004EF5CA /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				485CD0C50DDDED1700AEE666 /* PBXTargetDependency */,
+			);
+			name = Browser;
+			productName = Browser;
+			productReference = 48A23BA20DD0E5B4004EF5CA /* Browser.app */;
+			productType = "com.apple.product-type.application";
+		};
+		8D5B49AC048680CD000E48DA /* oophm */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "oophm" */;
+			buildPhases = (
+				8D5B49AF048680CD000E48DA /* Resources */,
+				8D5B49B1048680CD000E48DA /* Sources */,
+				8D5B49B3048680CD000E48DA /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = oophm;
+			productInstallPath = "$(HOME)/Library/Bundles";
+			productName = oophm;
+			productReference = 8D5B49B6048680CD000E48DA /* oophm.webplugin */;
+			productType = "com.apple.product-type.bundle";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		089C1669FE841209C02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "oophm" */;
+			compatibilityVersion = "Xcode 2.4";
+			hasScannedForEncodings = 1;
+			mainGroup = 089C166AFE841209C02AAC07 /* oophm */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				48A23BA10DD0E5B4004EF5CA /* Browser */,
+				8D5B49AC048680CD000E48DA /* oophm */,
+				48420E420DD52761001F3839 /* oophm.dmg */,
+				48547E030DD882170047AC8A /* symlinks */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		48A23B9E0DD0E5B4004EF5CA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48A23BC60DD0E6EE004EF5CA /* browser.nib in Resources */,
+				48A23C510DD0F2D6004EF5CA /* Browser-Info.plist in Resources */,
+				48A23C530DD0F302004EF5CA /* gwtlogo.icns in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D5B49AF048680CD000E48DA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
+				48C4D72E0DCA2B6900C34919 /* gwtlogo.icns in Resources */,
+				4856DF8F0DCF95B8000BF47C /* README.google in Resources */,
+				486DA8F50DD22BD50065980B /* crash.html in Resources */,
+				48338DDF0E4A2CA7008ACF0F /* oophm_bypass.plist in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		48420E460DD52768001F3839 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(BUILT_PRODUCTS_DIR)/oophm.webplugin",
+			);
+			outputPaths = (
+				"$(BUILT_PRODUCTS_DIR)/oophm.dmg",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -x\n# This is because the PackageMaker definition has \"Release\" hard-coded into it\nif [ \"${CONFIGURATION}\" != \"Release\" ]; then\n  echo error: Must be in Release configuration to build disk image\n  exit 1\nfi\n\n/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker --doc \"${PROJECT_DIR}/oophm.pmdoc\" --out \"${TEMP_FILES_DIR}/oophm.mpkg\"\n\nhdiutil create -ov -srcfolder \"${TEMP_FILES_DIR}/oophm.mpkg\" -format UDBZ \"${BUILT_PRODUCTS_DIR}/oophm.dmg\"\nhdiutil internet-enable \"${BUILT_PRODUCTS_DIR}/oophm.dmg\"";
+			showEnvVarsInLog = 0;
+		};
+		48547E020DD882170047AC8A /* Make symlink */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(BUILT_PRODUCTS_DIR)/oophm.webplugin",
+			);
+			name = "Make symlink";
+			outputPaths = (
+				"$(USER_LIBRARY_DIR)/Internet Plug-Ins/oophm.webplugin/Contents",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -x\nln -sf \"${BUILT_PRODUCTS_DIR}/oophm.webplugin\" \"${USER_LIBRARY_DIR}/Internet Plug-Ins/.\"";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		48A23B9F0DD0E5B4004EF5CA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				480DDCAA0E381E22000711F4 /* AppController.m in Sources */,
+				480DDCAB0E381E23000711F4 /* BrowserWindow.m in Sources */,
+				480DDCAC0E381E28000711F4 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D5B49B1048680CD000E48DA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				48FD98900DC62E7400E011A2 /* OophmPlugin.mm in Sources */,
+				48FD99540DC6349F00E011A2 /* OophmWebScriptObject.mm in Sources */,
+				48ABDDC50DCBA04800B0159A /* WebScriptSessionHandler.cpp in Sources */,
+				485505ED0DCD475C0009536F /* SlowScriptProxy.m in Sources */,
+				4856DF890DCF95B8000BF47C /* HostChannel.cpp in Sources */,
+				4856DF8A0DCF95B8000BF47C /* InvokeMessage.cpp in Sources */,
+				4856DF8B0DCF95B8000BF47C /* LoadModuleMessage.cpp in Sources */,
+				4856DF8E0DCF95B8000BF47C /* ReturnMessage.cpp in Sources */,
+				4856DF900DCF95B8000BF47C /* ServerMethods.cpp in Sources */,
+				48420D410DD51A3D001F3839 /* GTMNSString+HTML.m in Sources */,
+				48420D420DD51A3D001F3839 /* GTMStackTrace.c in Sources */,
+				48547F000DD889DA0047AC8A /* GTMSystemVersion.m in Sources */,
+				48547F4B0DD88D110047AC8A /* NSMutableString+HtmlReplacement.m in Sources */,
+				485CD0AA0DDDEAF300AEE666 /* Debug.mm in Sources */,
+				48108DDF0E2C15BD007FA76C /* AllowedConnections.cpp in Sources */,
+				48108DE00E2C15BD007FA76C /* Socket.cpp in Sources */,
+				48EF692D0E318E200050F5D6 /* ObjectFunctions.cpp in Sources */,
+				48C9EA4A0E37863700E691C6 /* FreeValueMessage.cpp in Sources */,
+				48C9EA4B0E37863700E691C6 /* InvokeSpecialMessage.cpp in Sources */,
+				48C9EA4C0E37863700E691C6 /* LoadJsniMessage.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		48420E480DD5278D001F3839 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D5B49AC048680CD000E48DA /* oophm */;
+			targetProxy = 48420E470DD5278D001F3839 /* PBXContainerItemProxy */;
+		};
+		48547E070DD8821D0047AC8A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D5B49AC048680CD000E48DA /* oophm */;
+			targetProxy = 48547E060DD8821D0047AC8A /* PBXContainerItemProxy */;
+		};
+		485CD0C50DDDED1700AEE666 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 48547E030DD882170047AC8A /* symlinks */;
+			targetProxy = 485CD0C40DDDED1700AEE666 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				089C167EFE841241C02AAC07 /* English */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+		486DA8F40DD22BD50065980B /* crash.html */ = {
+			isa = PBXVariantGroup;
+			children = (
+				486DA8ED0DD22B850065980B /* English */,
+			);
+			name = crash.html;
+			path = Plugin;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB913B08733D840010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/GTM/build/TigerOrLater-Release\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+				GCC_WARN_PEDANTIC = NO;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				PRODUCT_NAME = oophm;
+				WRAPPER_EXTENSION = webplugin;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		1DEB913C08733D840010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					ppc,
+					i386,
+				);
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/GTM/build/TigerOrLater-Release\"";
+				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;
+				GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+				GCC_WARN_PEDANTIC = NO;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Bundles";
+				PRODUCT_NAME = oophm;
+				STRIP_INSTALLED_PRODUCT = YES;
+				STRIP_STYLE = "non-global";
+				WRAPPER_EXTENSION = webplugin;
+			};
+			name = Release;
+		};
+		1DEB913F08733D840010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = "GWT_DEBUGLEVEL=Debugging";
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				OTHER_CFLAGS = "-mmacosx-version-min=10.4";
+				PREBINDING = NO;
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+				STRIP_INSTALLED_PRODUCT = NO;
+				STRIP_STYLE = "non-global";
+				SYMROOT = build;
+			};
+			name = Debug;
+		};
+		1DEB914008733D840010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 3;
+				GCC_PREPROCESSOR_DEFINITIONS = GWT_DEBUGDISABLE;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				OTHER_CFLAGS = "-mmacosx-version-min=10.4";
+				PREBINDING = NO;
+				SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
+				STRIP_STYLE = "non-global";
+				SYMROOT = build;
+			};
+			name = Release;
+		};
+		48420E430DD52761001F3839 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = oophm_package;
+			};
+			name = Debug;
+		};
+		48420E440DD52761001F3839 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				PRODUCT_NAME = oophm_package;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		48547E040DD882170047AC8A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = oophm.symlink;
+			};
+			name = Debug;
+		};
+		48547E050DD882170047AC8A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				PRODUCT_NAME = oophm.symlink;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+		48A23BA50DD0E5B5004EF5CA /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				INFOPLIST_FILE = "Browser/Browser-Info.plist";
+				INSTALL_PATH = "$(HOME)/Applications";
+				OTHER_LDFLAGS = (
+					"-framework",
+					Foundation,
+					"-framework",
+					AppKit,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = Browser;
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = YES;
+			};
+			name = Debug;
+		};
+		48A23BA60DD0E5B5004EF5CA /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = (
+					i386,
+					ppc,
+				);
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_FIX_AND_CONTINUE = NO;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = oophm_Prefix.pch;
+				INFOPLIST_FILE = "Browser/Browser-Info.plist";
+				INSTALL_PATH = "$(HOME)/Applications";
+				OTHER_LDFLAGS = (
+					"-framework",
+					Foundation,
+					"-framework",
+					AppKit,
+				);
+				PREBINDING = NO;
+				PRODUCT_NAME = Browser;
+				STRIP_INSTALLED_PRODUCT = YES;
+				STRIP_STYLE = "non-global";
+				VALID_ARCHS = "ppc64 ppc7400 ppc970 i386 x86_64 ppc";
+				WRAPPER_EXTENSION = app;
+				ZERO_LINK = NO;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "oophm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB913B08733D840010E9CD /* Debug */,
+				1DEB913C08733D840010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "oophm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB913F08733D840010E9CD /* Debug */,
+				1DEB914008733D840010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		48420E5A0DD527AD001F3839 /* Build configuration list for PBXAggregateTarget "oophm.dmg" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				48420E430DD52761001F3839 /* Debug */,
+				48420E440DD52761001F3839 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		48547E080DD8823B0047AC8A /* Build configuration list for PBXAggregateTarget "symlinks" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				48547E040DD882170047AC8A /* Debug */,
+				48547E050DD882170047AC8A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		48A23BA70DD0E5B5004EF5CA /* Build configuration list for PBXNativeTarget "Browser" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				48A23BA50DD0E5B5004EF5CA /* Debug */,
+				48A23BA60DD0E5B5004EF5CA /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 089C1669FE841209C02AAC07 /* Project object */;
+}
diff --git a/plugins/webkit/oophm_Prefix.pch b/plugins/webkit/oophm_Prefix.pch
new file mode 100644
index 0000000..e7b7f01
--- /dev/null
+++ b/plugins/webkit/oophm_Prefix.pch
@@ -0,0 +1,7 @@
+//
+// Prefix header for all source files of the 'oophm' target in the 'oophm' project.
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+#endif
diff --git a/plugins/webkit/oophm_bypass.plist b/plugins/webkit/oophm_bypass.plist
new file mode 100644
index 0000000..b7af14f
--- /dev/null
+++ b/plugins/webkit/oophm_bypass.plist
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!-- Copy this to Library/Preferences/com.google.gwt.oophm.plist -->
+<plist version="1.0">
+<dict>
+	<key>allowAll</key>
+	<true/>
+</dict>
+</plist>
diff --git a/plugins/webkit/prebuilt/oophm.dmg b/plugins/webkit/prebuilt/oophm.dmg
new file mode 100644
index 0000000..54fd2d9
--- /dev/null
+++ b/plugins/webkit/prebuilt/oophm.dmg
Binary files differ