Merge additional changes from electrolysis and mozilla-central into the electrolysis-plugins-only tracking branch. electrolysis-plugins-only
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 04 Dec 2009 11:42:28 -0500
branchelectrolysis-plugins-only
changeset 36149 cd74c0c4de892c1e34c1ccdc4cce54e5a5694fa2
parent 36147 9b7c59d4c4cd4e290d06a2fc3045d4fa54b20ea0 (current diff)
parent 36148 39e0a7b9fc54fd744a269072ba52b051e3deb247 (diff)
child 36180 8ef83d174df3227dc27a673b18d9861efc7bd2ba
child 50700 f978feaec223f9b712f7c80796fcf3267ad4b0cf
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
Merge additional changes from electrolysis and mozilla-central into the electrolysis-plugins-only tracking branch.
content/base/src/nsFrameLoader.cpp
content/canvas/src/WebGLContext.h
ipc/Makefile.in
ipc/ipdl/Makefile.in
layout/generic/nsFrameFrame.cpp
toolkit/library/dlldeps-xul.cpp
toolkit/library/libxul-config.mk
toolkit/xre/nsEmbedFunctions.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -202,17 +202,17 @@ else
 BUILDID = $(shell $(PYTHON) $(srcdir)/config/printconfigsetting.py $(DIST)/bin/platform.ini Build BuildID)
 endif
 
 #XXX: this is a hack, since we don't want to clobber for MSVC
 # PGO support, but we can't do this test in client.mk
 ifneq ($(OS_ARCH)_$(GNU_CC), WINNT_)
 # No point in clobbering if PGO has been explicitly disabled.
 ifndef NO_PROFILE_GUIDED_OPTIMIZE
-maybe_clobber_profiledbuild: clobber_all
+maybe_clobber_profiledbuild: clean
 else
 maybe_clobber_profiledbuild:
 endif
 else
 maybe_clobber_profiledbuild:
 endif
 
 .PHONY: maybe_clobber_profiledbuild
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,9 +1,9 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
     <emItem id="fdm_ffext@freedownloadmanager.org">
       <versionRange minVersion="1.0" maxVersion="1.3.1">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
            <versionRange minVersion="3.0a1" maxVersion="*"/>
         </targetApplication>
       </versionRange>
@@ -18,29 +18,28 @@
         </targetApplication>
       </versionRange>
     </emItem>
     <emItem id="support@daemon-tools.cc">
       <versionRange minVersion=" " maxVersion="1.0.0.5"/>
     </emItem>
     <emItem id="{2224e955-00e9-4613-a844-ce69fccaae91}"/>
     <emItem id="{3f963a5b-e555-4543-90e2-c3908898db71}">
-      <versionRange minVersion=" " maxVersion="8.0">
-        <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-           <versionRange minVersion="3.1a1" maxVersion="*"/>
-        </targetApplication>
-      </versionRange>
+      <versionRange minVersion=" " maxVersion="8.5"/>
     </emItem>
     <emItem id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}">
       <versionRange minVersion="1.2" maxVersion="1.2">
         <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
            <versionRange minVersion="3.0a1" maxVersion="*"/>
         </targetApplication>
       </versionRange>
     </emItem>
+    <emItem id="{B13721C7-F507-4982-B2E5-502A71474FED}">
+      <versionRange minVersion=" " maxVersion="3.3.0.3970" severity="1"/>
+    </emItem>
   </emItems>
 <pluginItems>
   <pluginItem>
     <match name="name" exp="^Yahoo Application State Plugin$"/>
     <match name="description" exp="^Yahoo Application State Plugin$"/>
     <match name="filename" exp="npYState.dll"/>
     <versionRange>
       <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -65,34 +65,34 @@ pref("xpinstall.dialog.progress.type.chr
 pref("extensions.ignoreMTimeChanges", false);
 // Enables some extra Extension System Logging (can reduce performance)
 pref("extensions.logging.enabled", false);
 // Hides the install button in the add-ons mgr
 pref("extensions.hideInstallButton", true);
 
 // Preferences for the Get Add-ons pane
 pref("extensions.getAddons.showPane", true);
-pref("extensions.getAddons.browseAddons", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%");
+pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/%APP%");
 pref("extensions.getAddons.maxResults", 5);
-pref("extensions.getAddons.recommended.browseURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/recommended");
+pref("extensions.getAddons.recommended.browseURL", "https://addons.mozilla.org/%LOCALE%/%APP%/recommended");
 pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/list/featured/all/10/%OS%/%VERSION%");
-pref("extensions.getAddons.search.browseURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/search?q=%TERMS%");
+pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/%APP%/search?q=%TERMS%");
 pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/10/%OS%/%VERSION%");
 
 // Blocklist preferences
 pref("extensions.blocklist.enabled", true);
 pref("extensions.blocklist.interval", 86400);
 // Controls what level the blocklist switches from warning about items to forcibly
 // blocking them.
 pref("extensions.blocklist.level", 2);
 pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/");
 pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
 
 // Dictionary download preference
-pref("browser.dictionaries.download.url", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/firefox/%VERSION%/dictionaries/");
+pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/%APP%/dictionaries/");
 
 // Update Timer Manager preferences
 // Interval: When all registered timers should be checked (in milliseconds)
 //           default=10 minutes
 pref("app.update.timer", 600000);
 
 // App-specific update preferences
 
@@ -274,17 +274,17 @@ pref("browser.download.manager.closeWhen
 pref("browser.download.manager.focusWhenStarting", false);
 pref("browser.download.manager.flashCount", 2);
 pref("browser.download.manager.addToRecentDocs", true);
 pref("browser.download.manager.quitBehavior", 0);
 pref("browser.download.manager.scanWhenDone", true);
 pref("browser.download.manager.resumeOnWakeDelay", 10000);
 
 // search engines URL
-pref("browser.search.searchEnginesURL",      "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/firefox/%VERSION%/search-engines/");
+pref("browser.search.searchEnginesURL",      "https://addons.mozilla.org/%LOCALE%/%APP%/search-engines/");
 
 // pointer to the default engine name
 pref("browser.search.defaultenginename",      "chrome://browser-region/locale/region.properties");
 
 // disable logging for the search service by default
 pref("browser.search.log", false);
 
 // Ordering of Search Engines in the Engine list. 
@@ -701,18 +701,18 @@ pref("browser.safebrowsing.provider.0.ge
 // HTML report pages
 pref("browser.safebrowsing.provider.0.reportGenericURL", "http://{moz:locale}.phish-generic.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportErrorURL", "http://{moz:locale}.phish-error.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportPhishURL", "http://{moz:locale}.phish-report.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportMalwareURL", "http://{moz:locale}.malware-report.mozilla.com/?hl={moz:locale}");
 pref("browser.safebrowsing.provider.0.reportMalwareErrorURL", "http://{moz:locale}.malware-error.mozilla.com/?hl={moz:locale}");
 
 // FAQ URLs
-pref("browser.safebrowsing.warning.infoURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/firefox/phishing-protection/");
-pref("browser.geolocation.warning.infoURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/firefox/geolocation/");
+pref("browser.safebrowsing.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/phishing-protection/");
+pref("browser.geolocation.warning.infoURL", "http://www.mozilla.com/%LOCALE%/%APP%/geolocation/");
 
 // Name of the about: page contributed by safebrowsing to handle display of error
 // pages on phishing/malware hits.  (bug 399233)
 pref("urlclassifier.alternate_error_page", "blocked");
 
 // The number of random entries to send with a gethash request.
 pref("urlclassifier.gethashnoise", 4);
 
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -187,16 +187,17 @@ window[chromehidden~="toolbar"] toolbar:
 /* ::::: Ctrl-Tab Panel ::::: */
 .ctrlTab-preview {
   -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#ctrlTab-preview");
 }
 
 /* ::::: All Tabs Panel ::::: */
 .allTabs-preview {
   -moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#allTabs-preview");
+  vertical-align: top;
 }
 
 #allTabs-tab-close-button {
   -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image");
   margin: 0;
 }
 
 #allTabs-container {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6287,18 +6287,18 @@ function undoCloseWindow(aIndex) {
     window = ss.undoCloseWindow(aIndex || 0);
 
   return window;
 }
 
 /**
  * Format a URL
  * eg:
- * echo formatURL("http://%LOCALE%.amo.mozilla.org/%LOCALE%/%APP%/%VERSION%/");
- * > http://en-US.amo.mozilla.org/en-US/firefox/3.0a1/
+ * echo formatURL("https://addons.mozilla.org/%LOCALE%/%APP%/%VERSION%/");
+ * > https://addons.mozilla.org/en-US/firefox/3.0a1/
  *
  * Currently supported built-ins are LOCALE, APP, and any value from nsIXULAppInfo, uppercased.
  */
 function formatURL(aFormat, aIsPref) {
   var formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
   return aIsPref ? formatter.formatURLPref(aFormat) : formatter.formatURL(aFormat);
 }
 
--- a/configure.in
+++ b/configure.in
@@ -8149,17 +8149,17 @@ if test -n "$MOZ_WEBGL"; then
         fi
     fi
 fi # MOZ_WEBGL
 fi # COMPILE_ENVIRONMENT
 
 if test "$USE_FC_FREETYPE"; then
     if test "$COMPILE_ENVIRONMENT"; then
     	_SAVE_CPPFLAGS="$CPPFLAGS"
-    	CPPFLAGS="$CPPFLAGS $FT2_CFLAGS"
+    	CPPFLAGS="$CPPFLAGS $FT2_CFLAGS $XCFLAGS"
         AC_CHECK_HEADERS(fontconfig/fcfreetype.h, , 
             [AC_MSG_ERROR(Can't find header fontconfig/fcfreetype.h.)])
     	CPPFLAGS="$_SAVE_CPPFLAGS"
     else
         AC_DEFINE(HAVE_FONTCONFIG_FCFREETYPE_H)
     fi
 fi
 
@@ -8441,17 +8441,26 @@ if test "$BUILD_CTYPES"; then
       ac_configure_args="$ac_configure_args --enable-debug"
     fi
     if test -n "$DSO_PIC_CFLAGS"; then
       ac_configure_args="$ac_configure_args --with-pic"
     fi
     if test -n "$CROSS_COMPILE"; then
       ac_configure_args="$ac_configure_args --build=$build --host=$target"
     fi
-    AC_OUTPUT_SUBDIRS(js/ctypes/libffi)
+    if test "$SOLARIS_SUNPRO_CC"; then
+      # Always use gcc for libffi on Solaris
+      old_cache_file=$cache_file
+      cache_file=js/ctypes/libffi/config.cache
+      ac_configure_args="$ac_configure_args CC=gcc"
+      AC_OUTPUT_SUBDIRS(js/ctypes/libffi)
+      cache_file=$old_cache_file
+    else
+      AC_OUTPUT_SUBDIRS(js/ctypes/libffi)
+    fi
     ac_configure_args="$_SUBDIR_CONFIG_ARGS"
   fi
 fi
 
 fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR
 
 dnl Prevent the regeneration of autoconf.mk forcing rebuilds of the world
 dnl Needs to be at the end to respect possible changes from NSPR configure
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1127,19 +1127,17 @@ nsNSElementTearoff::GetElementsByClassNa
 {
   return nsDocument::GetElementsByClassNameHelper(mContent, aClasses, aReturn);
 }
 
 nsIFrame*
 nsGenericElement::GetStyledFrame()
 {
   nsIFrame *frame = GetPrimaryFrame(Flush_Layout);
-
-  return (frame && frame->GetType() == nsGkAtoms::tableOuterFrame) ?
-    frame->GetFirstChild(nsnull) : frame;
+  return frame ? nsLayoutUtils::GetStyleFrame(frame) : nsnull;
 }
 
 void
 nsGenericElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
 {
   *aOffsetParent = nsnull;
   aRect = nsRect();
 
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -409,21 +409,25 @@ nsObjectLoadingContent::OnStartRequest(n
     channelType = APPLICATION_OCTET_STREAM;
     chan->SetContentType(channelType);
   }
 
   // We want to use the channel type unless one of the following is
   // true:
   //
   // 1) The channel type is application/octet-stream and we have a
-  //    type hint
+  //    type hint and the type hint is not a document type.
   // 2) Our type hint is a type that we support with a plugin.
 
   if ((channelType.EqualsASCII(APPLICATION_OCTET_STREAM) && 
-       !mContentType.IsEmpty()) ||
+       !mContentType.IsEmpty() &&
+       GetTypeOfContent(mContentType) != eType_Document) ||
+      // Need to check IsSupportedPlugin() in addition to GetTypeOfContent()
+      // because otherwise the default plug-in's catch-all behavior would
+      // confuse things.
       (IsSupportedPlugin(mContentType) && 
        GetTypeOfContent(mContentType) == eType_Plugin)) {
     // Set the type we'll use for dispatch on the channel.  Otherwise we could
     // end up trying to dispatch to a nsFrameLoader, which will complain that
     // it couldn't find a way to handle application/octet-stream
 
     chan->SetContentType(mContentType);
   } else {
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -294,16 +294,17 @@ include $(topsrcdir)/config/rules.mk
 		test_w3element_traversal.html \
 		test_w3element_traversal.xhtml \
 		test_bug469020.html \
 		test_w3element_traversal_svg.html \
 		w3element_traversal.svg \
 		test_bug444322.html \
 		bug444322.txt \
 		bug444322.js \
+		test_bug455472.html \
 		test_bug455629.html \
 		bug455629-helper.svg \
 		test_bug473162-1.html \
 		test_bug473162-2.html \
 		test_bug466751.xhtml \
 		test_bug461555.html \
 		test_sync_xhr_timer.xhtml \
 		test_bug498240.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug455472.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=455472
+-->
+<head>
+  <title>Test for Bug 455472</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=455472">Mozilla Bug 455472</a>
+<p id="display"></p>
+<script>
+  var ran = [ false, false, false, false, false ];
+</script>
+<div id="content" style="display: none">
+  <iframe src="data:text/html,<script>parent.ran[0]=true</script>"></iframe>
+  <object type="text/html" data="data:text/html,<script>parent.ran[1]=true</script>"></object>
+  <embed type="image/svg+xml" src="data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20onload='parent.ran[2]=true'/>">
+  <object type="text/html" data="data:application/octet-stream,<script>parent.ran[3]=true</script>"></object>
+  <embed type="image/svg+xml" src="data:application/octet-stream,<svg%20xmlns='http://www.w3.org/2000/svg'%20onload='parent.ran[4]=true'/>">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 455472 **/
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+  var expected = [ true, true, true, false, false ];
+  is (expected.length, ran.length, "Length mismatch");
+  for (var i = 0; i < expected.length; ++i) {
+    is(ran[i], expected[i],
+       "Unexpected behavior in object " + i + " (0-based)");
+  }
+  SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/public/WebGLArray.h
+++ b/content/canvas/public/WebGLArray.h
@@ -33,18 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef WEBGLARRAY_H_
 #define WEBGLARRAY_H_
 
-nsresult NS_NewCanvasArrayBuffer(nsISupports **aNewObject);
-nsresult NS_NewCanvasFloatArray(nsISupports **aNewObject);
-nsresult NS_NewCanvasByteArray(nsISupports **aNewObject);
-nsresult NS_NewCanvasUnsignedByteArray(nsISupports **aNewObject);
-nsresult NS_NewCanvasShortArray(nsISupports **aNewObject);
-nsresult NS_NewCanvasUnsignedShortArray(nsISupports **aNewObject);
-nsresult NS_NewCanvasIntArray(nsISupports **aNewObject);
-nsresult NS_NewCanvasUnsignedIntArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLArrayBuffer(nsISupports **aNewObject);
+nsresult NS_NewWebGLFloatArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLByteArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLUnsignedByteArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLShortArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLUnsignedShortArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLIntArray(nsISupports **aNewObject);
+nsresult NS_NewWebGLUnsignedIntArray(nsISupports **aNewObject);
 
 #endif
--- a/content/canvas/src/WebGLArrays.cpp
+++ b/content/canvas/src/WebGLArrays.cpp
@@ -48,19 +48,19 @@
 //      just be doing calloc
 // XXX: array Set() shouldn't call into the inner Set(), because that
 //      repeats the length check and is probably not getting inlined
 // write benchmarks
 
 using namespace mozilla;
 
 nsresult
-NS_NewCanvasArrayBuffer(nsISupports **aResult)
+NS_NewWebGLArrayBuffer(nsISupports **aResult)
 {
-    nsICanvasArrayBuffer *wgab = new WebGLArrayBuffer();
+    nsIWebGLArrayBuffer *wgab = new WebGLArrayBuffer();
     if (!wgab)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wgab);
     return NS_OK;
 }
 
 WebGLArrayBuffer::WebGLArrayBuffer(PRUint32 length)
@@ -111,23 +111,23 @@ NS_IMETHODIMP_(void *) WebGLArrayBuffer:
 
 /* [noscript, notxpcom] unsigned long nativeSize (); */
 NS_IMETHODIMP_(PRUint32) WebGLArrayBuffer::NativeSize()
 {
     return capacity;
 }
 
 /*
- * CanvasFloatArray
+ * WebGLFloatArray
  */
 
 nsresult
-NS_NewCanvasFloatArray(nsISupports **aResult)
+NS_NewWebGLFloatArray(nsISupports **aResult)
 {
-    nsICanvasFloatArray *wgfa = new WebGLFloatArray();
+    nsIWebGLFloatArray *wgfa = new WebGLFloatArray();
     if (!wgfa)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wgfa);
     return NS_OK;
 }
 
 WebGLFloatArray::WebGLFloatArray(PRUint32 length)
@@ -176,19 +176,19 @@ WebGLFloatArray::Initialize(nsISupports 
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_FLOAT, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if (byteOffset % sizeof(float))
                 return NS_ERROR_FAILURE;
@@ -205,18 +205,18 @@ WebGLFloatArray::Initialize(nsISupports 
                 mLength = (mBuffer->capacity - byteOffset) / sizeof(float);
             }
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLFloatArray::GetBuffer(nsICanvasArrayBuffer **aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLFloatArray::GetBuffer(nsIWebGLArrayBuffer **aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLFloatArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -240,26 +240,26 @@ NS_IMETHODIMP WebGLFloatArray::GetLength
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLFloatArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLFloatArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLFloatArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLFloatArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLFloatArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] float get (in unsigned long index); */
 NS_IMETHODIMP WebGLFloatArray::Get(PRUint32 index, float *retval)
 {
     if (index >= mLength)
@@ -336,24 +336,117 @@ NS_IMETHODIMP_(PRUint32) WebGLFloatArray
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLFloatArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLFloatArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLFloatArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLFloatArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLFloatArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                           JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    float val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLFloatArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                       JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    float val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = (float) JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        jsdouble dval;
+        ok = JS_ValueToNumber(cx, *vp, &dval);
+        val = (float) dval;
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, val);
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLFloatArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                      JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                      PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
 /*
- * CanvasByteArray
+ * WebGLByteArray
  */
 
 nsresult
-NS_NewCanvasByteArray(nsISupports **aResult)
+NS_NewWebGLByteArray(nsISupports **aResult)
 {
-    nsICanvasByteArray *wgba = new WebGLByteArray();
+    nsIWebGLByteArray *wgba = new WebGLByteArray();
     if (!wgba)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wgba);
     return NS_OK;
 }
 
 WebGLByteArray::WebGLByteArray(PRUint32 length)
@@ -402,19 +495,19 @@ WebGLByteArray::Initialize(nsISupports *
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_UNSIGNED_BYTE, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if ((byteOffset + length) > mBuffer->capacity)
                 return NS_ERROR_FAILURE;
@@ -424,18 +517,18 @@ WebGLByteArray::Initialize(nsISupports *
             else
                 mLength = (mBuffer->capacity - byteOffset);
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLByteArray::GetBuffer(nsICanvasArrayBuffer **aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLByteArray::GetBuffer(nsIWebGLArrayBuffer **aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLByteArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -459,26 +552,26 @@ NS_IMETHODIMP WebGLByteArray::GetLength(
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLByteArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLByteArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLByteArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLByteArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLByteArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] long get (in unsigned long index); */
 NS_IMETHODIMP WebGLByteArray::Get(PRUint32 index, PRInt32 *retval)
 {
     if (index >= mLength)
@@ -555,25 +648,115 @@ NS_IMETHODIMP_(PRUint32) WebGLByteArray:
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLByteArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLByteArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLByteArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLByteArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLByteArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                          JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRInt32 val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_SUCCESS_I_DID_SOMETHING;
+}
+
+NS_IMETHODIMP WebGLByteArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                          JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    int32 val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAInt32(cx, *vp, &val);
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, (char) val);
+    return NS_SUCCESS_I_DID_SOMETHING;
+}
+
+NS_IMETHODIMP WebGLByteArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                         JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                                         PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
 
 /*
- * CanvasUnsignedByteArray
+ * WebGLUnsignedByteArray
  */
 
 nsresult
-NS_NewCanvasUnsignedByteArray(nsISupports **aResult)
+NS_NewWebGLUnsignedByteArray(nsISupports **aResult)
 {
-    nsICanvasUnsignedByteArray *wguba = new WebGLUnsignedByteArray();
+    nsIWebGLUnsignedByteArray *wguba = new WebGLUnsignedByteArray();
     if (!wguba)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wguba);
     return NS_OK;
 }
 
 WebGLUnsignedByteArray::WebGLUnsignedByteArray(PRUint32 length)
@@ -622,19 +805,19 @@ WebGLUnsignedByteArray::Initialize(nsISu
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_UNSIGNED_BYTE, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if ((byteOffset + length) > mBuffer->capacity)
                 return NS_ERROR_FAILURE;
@@ -644,18 +827,18 @@ WebGLUnsignedByteArray::Initialize(nsISu
             else
                 mLength = (mBuffer->capacity - byteOffset);
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLUnsignedByteArray::GetBuffer(nsICanvasArrayBuffer **aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLUnsignedByteArray::GetBuffer(nsIWebGLArrayBuffer **aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLUnsignedByteArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -679,26 +862,26 @@ NS_IMETHODIMP WebGLUnsignedByteArray::Ge
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLUnsignedByteArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLUnsignedByteArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLUnsignedByteArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLUnsignedByteArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLUnsignedByteArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] unsigned long get (in unsigned long index); */
 NS_IMETHODIMP WebGLUnsignedByteArray::Get(PRUint32 index, PRUint32 *retval)
 {
     if (index >= mLength)
@@ -775,24 +958,115 @@ NS_IMETHODIMP_(PRUint32) WebGLUnsignedBy
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLUnsignedByteArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLUnsignedByteArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLUnsignedByteArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLUnsignedByteArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLUnsignedByteArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                  JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRUint32 val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLUnsignedByteArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                  JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    uint32 val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, *vp, &val);
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, (unsigned char) val);
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLUnsignedByteArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                 JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                                                 PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
 /*
- * CanvasShortArray
+ * WebGLShortArray
  */
 
 nsresult
-NS_NewCanvasShortArray(nsISupports **aResult)
+NS_NewWebGLShortArray(nsISupports **aResult)
 {
-    nsICanvasShortArray *wgsa = new WebGLShortArray();
+    nsIWebGLShortArray *wgsa = new WebGLShortArray();
     if (!wgsa)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wgsa);
     return NS_OK;
 }
 
 WebGLShortArray::WebGLShortArray(PRUint32 length)
@@ -841,19 +1115,19 @@ WebGLShortArray::Initialize(nsISupports 
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_SHORT, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if (byteOffset % sizeof(short))
                 return NS_ERROR_FAILURE;
@@ -870,18 +1144,18 @@ WebGLShortArray::Initialize(nsISupports 
                 mLength = (mBuffer->capacity - byteOffset) / sizeof(short);
             }
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLShortArray::GetBuffer(nsICanvasArrayBuffer * *aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLShortArray::GetBuffer(nsIWebGLArrayBuffer * *aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLShortArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -905,26 +1179,26 @@ NS_IMETHODIMP WebGLShortArray::GetLength
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLShortArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLShortArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLShortArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLShortArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLShortArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] long get (in unsigned long index); */
 NS_IMETHODIMP WebGLShortArray::Get(PRUint32 index, PRInt32 *retval)
 {
     if (index >= mLength)
@@ -1001,24 +1275,115 @@ NS_IMETHODIMP_(PRUint32) WebGLShortArray
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLShortArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLShortArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLShortArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLShortArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLShortArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                           JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRInt32 val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLShortArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                           JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    int32 val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAInt32(cx, *vp, &val);
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, (short) val);
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLShortArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                          JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                                          PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
 /*
- * CanvasUnsignedShortArray
+ * WebGLUnsignedShortArray
  */
 
 nsresult
-NS_NewCanvasUnsignedShortArray(nsISupports **aResult)
+NS_NewWebGLUnsignedShortArray(nsISupports **aResult)
 {
-    nsICanvasUnsignedShortArray *wgusa = new WebGLUnsignedShortArray();
+    nsIWebGLUnsignedShortArray *wgusa = new WebGLUnsignedShortArray();
     if (!wgusa)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wgusa);
     return NS_OK;
 }
 
 WebGLUnsignedShortArray::WebGLUnsignedShortArray(PRUint32 length)
@@ -1067,19 +1432,19 @@ WebGLUnsignedShortArray::Initialize(nsIS
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_UNSIGNED_SHORT, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if (byteOffset % sizeof(short))
                 return NS_ERROR_FAILURE;
@@ -1096,18 +1461,18 @@ WebGLUnsignedShortArray::Initialize(nsIS
                 mLength = (mBuffer->capacity - byteOffset) / sizeof(short);
             }
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLUnsignedShortArray::GetBuffer(nsICanvasArrayBuffer * *aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLUnsignedShortArray::GetBuffer(nsIWebGLArrayBuffer * *aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLUnsignedShortArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -1131,26 +1496,26 @@ NS_IMETHODIMP WebGLUnsignedShortArray::G
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLUnsignedShortArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLUnsignedShortArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLUnsignedShortArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLUnsignedShortArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLUnsignedShortArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] unsigned long get (in unsigned long index); */
 NS_IMETHODIMP WebGLUnsignedShortArray::Get(PRUint32 index, PRUint32 *retval)
 {
     if (index >= mLength)
@@ -1227,24 +1592,115 @@ NS_IMETHODIMP_(PRUint32) WebGLUnsignedSh
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLUnsignedShortArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLUnsignedShortArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLUnsignedShortArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLUnsignedShortArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLUnsignedShortArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                   JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRUint32 val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLUnsignedShortArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                   JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    uint32 val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, *vp, &val);
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, (unsigned short) val);
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLUnsignedShortArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                  JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                                                  PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
 /*
- * CanvasIntArray
+ * WebGLIntArray
  */
 
 nsresult
-NS_NewCanvasIntArray(nsISupports **aResult)
+NS_NewWebGLIntArray(nsISupports **aResult)
 {
-    nsICanvasIntArray *wgia = new WebGLIntArray();
+    nsIWebGLIntArray *wgia = new WebGLIntArray();
     if (!wgia)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wgia);
     return NS_OK;
 }
 
 WebGLIntArray::WebGLIntArray(PRUint32 length)
@@ -1293,19 +1749,19 @@ WebGLIntArray::Initialize(nsISupports *o
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_INT, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if (byteOffset % sizeof(int))
                 return NS_ERROR_FAILURE;
@@ -1322,18 +1778,18 @@ WebGLIntArray::Initialize(nsISupports *o
                 mLength = (mBuffer->capacity - byteOffset) / sizeof(int);
             }
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLIntArray::GetBuffer(nsICanvasArrayBuffer * *aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLIntArray::GetBuffer(nsIWebGLArrayBuffer * *aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLIntArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -1357,26 +1813,26 @@ NS_IMETHODIMP WebGLIntArray::GetLength(P
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLIntArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLIntArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLIntArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLIntArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLIntArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] long get (in unsigned long index); */
 NS_IMETHODIMP WebGLIntArray::Get(PRUint32 index, PRInt32 *retval)
 {
     if (index >= mLength)
@@ -1453,24 +1909,115 @@ NS_IMETHODIMP_(PRUint32) WebGLIntArray::
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLIntArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLIntArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLIntArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLIntArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLIntArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                         JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRInt32 val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLIntArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                         JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    int32 val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAInt32(cx, *vp, &val);
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, val);
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLIntArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                        JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                                        PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
 /*
- * CanvasUnsignedIntArray
+ * WebGLUnsignedIntArray
  */
 
 nsresult
-NS_NewCanvasUnsignedIntArray(nsISupports **aResult)
+NS_NewWebGLUnsignedIntArray(nsISupports **aResult)
 {
-    nsICanvasUnsignedIntArray *wguia = new WebGLUnsignedIntArray();
+    nsIWebGLUnsignedIntArray *wguia = new WebGLUnsignedIntArray();
     if (!wguia)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ADDREF(*aResult = wguia);
     return NS_OK;
 }
 
 WebGLUnsignedIntArray::WebGLUnsignedIntArray(PRUint32 length)
@@ -1519,19 +2066,19 @@ WebGLUnsignedIntArray::Initialize(nsISup
 
         if (::JS_IsArrayObject(cx, arrayObj) &&
             ::JS_GetArrayLength(cx, arrayObj, &arrayLen))
         {
             mBuffer = new WebGLArrayBuffer();
             mBuffer->InitFromJSArray(LOCAL_GL_UNSIGNED_INT, 1, cx, arrayObj, arrayLen);
             mLength = arrayLen;
         } else {
-            nsCOMPtr<nsICanvasArrayBuffer> canvasObj;
+            nsCOMPtr<nsIWebGLArrayBuffer> canvasObj;
             nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(canvasObj));
+            rv = nsContentUtils::XPConnect()->WrapJS(cx, arrayObj, NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(canvasObj));
             if (NS_FAILED(rv) || !canvasObj) {
                 return NS_ERROR_DOM_SYNTAX_ERR;
             }
 
             mBuffer = canvasObj->GetNativeArrayBuffer();
 
             if (byteOffset % sizeof(int))
                 return NS_ERROR_FAILURE;
@@ -1548,18 +2095,18 @@ WebGLUnsignedIntArray::Initialize(nsISup
                 mLength = (mBuffer->capacity - byteOffset) / sizeof(int);
             }
         }
     }
 
     return NS_OK;
 }
 
-/* readonly attribute nsICanvasArrayBuffer buffer; */
-NS_IMETHODIMP WebGLUnsignedIntArray::GetBuffer(nsICanvasArrayBuffer * *aBuffer)
+/* readonly attribute nsIWebGLArrayBuffer buffer; */
+NS_IMETHODIMP WebGLUnsignedIntArray::GetBuffer(nsIWebGLArrayBuffer * *aBuffer)
 {
     NS_ADDREF(*aBuffer = mBuffer);
     return NS_OK;
 }
 
 /* readonly attribute unsigned long byteOffset; */
 NS_IMETHODIMP WebGLUnsignedIntArray::GetByteOffset(PRUint32 *aByteOffset)
 {
@@ -1583,26 +2130,26 @@ NS_IMETHODIMP WebGLUnsignedIntArray::Get
 
 /* unsigned long alignedSizeInBytes (); */
 NS_IMETHODIMP WebGLUnsignedIntArray::AlignedSizeInBytes(PRUint32 *retval)
 {
     *retval = mBuffer->capacity;
     return NS_OK;
 }
 
-/* nsICanvasArray slice (in unsigned long offset, in unsigned long length); */
-NS_IMETHODIMP WebGLUnsignedIntArray::Slice(PRUint32 offset, PRUint32 length, nsICanvasArray **retval)
+/* nsIWebGLArray slice (in unsigned long offset, in unsigned long length); */
+NS_IMETHODIMP WebGLUnsignedIntArray::Slice(PRUint32 offset, PRUint32 length, nsIWebGLArray **retval)
 {
     if (length == 0) 
         return NS_ERROR_FAILURE;
 
     if (offset + length > mBuffer->capacity)
         return NS_ERROR_FAILURE;
 
-    nsICanvasArray *wga = new WebGLUnsignedIntArray(mBuffer, offset, length);
+    nsIWebGLArray *wga = new WebGLUnsignedIntArray(mBuffer, offset, length);
     NS_ADDREF(*retval = wga);
     return NS_OK;
 }
 
 /* [IndexGetter] unsigned long get (in unsigned long index); */
 NS_IMETHODIMP WebGLUnsignedIntArray::Get(PRUint32 index, PRUint32 *retval)
 {
     if (index >= mLength)
@@ -1679,99 +2226,196 @@ NS_IMETHODIMP_(PRUint32) WebGLUnsignedIn
 }
 
 /* [noscript, notxpcom] unsigned long nativeCount (); */
 NS_IMETHODIMP_(PRUint32) WebGLUnsignedIntArray::NativeCount()
 {
     return mBuffer->length;
 }
 
+// nsIXPCScriptable
+#define XPC_MAP_CLASSNAME WebGLUnsignedIntArray
+#define XPC_MAP_QUOTED_CLASSNAME "WebGLUnsignedIntArray"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY
+#include "xpc_map_end.h"
+
+PRBool WebGLUnsignedIntArray::JSValToIndex(JSContext *cx, jsval id, uint32 *retval) {
+    PRBool ok = PR_FALSE;
+    uint32 index;
+
+    if (JSVAL_IS_INT(id)) {
+        index = JSVAL_TO_INT(id);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, id, &index);
+    }
+
+    if (!ok || index >= mLength)
+        return PR_FALSE;
+
+    *retval = index;
+    return PR_TRUE;
+}
+
+NS_IMETHODIMP WebGLUnsignedIntArray::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                 JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRUint32 val;
+    Get(index, &val);
+    *_retval = JS_NewNumberValue(cx, val, vp);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLUnsignedIntArray::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                 JSObject * obj, jsval id, jsval * vp, PRBool *_retval)
+{
+    uint32 index;
+    uint32 val;
+
+    if (!JSValToIndex(cx, id, &index)) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    PRBool ok = PR_FALSE;
+
+    if (JSVAL_IS_INT(*vp)) {
+        val = JSVAL_TO_INT(*vp);
+        ok = PR_TRUE;
+    } else {
+        ok = JS_ValueToECMAUint32(cx, *vp, &val);
+    }
+
+    if (!ok) {
+        *_retval = PR_FALSE;
+        return NS_ERROR_INVALID_ARG;
+    }
+
+    Set(index, val);
+    return NS_OK;
+}
+
+NS_IMETHODIMP WebGLUnsignedIntArray::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
+                                                JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp,
+                                                PRBool *_retval)
+{
+    uint32 index;
+    PRBool ok = JSValToIndex(cx, id, &index);
+
+    if (ok) {
+        *_retval = PR_TRUE;
+        *objp = obj;
+    } else {
+        *_retval = PR_FALSE;
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
 
 
 /*
  * XPCOM AddRef/Release/QI
  */
 NS_IMPL_ADDREF(WebGLArrayBuffer)
 NS_IMPL_RELEASE(WebGLArrayBuffer)
 
 NS_INTERFACE_MAP_BEGIN(WebGLArrayBuffer)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArrayBuffer)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasArrayBuffer)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArrayBuffer)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLArrayBuffer)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasArrayBuffer)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLArrayBuffer)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLFloatArray)
 NS_IMPL_RELEASE(WebGLFloatArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLFloatArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasFloatArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasFloatArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLFloatArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLFloatArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasFloatArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLFloatArray)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLByteArray)
 NS_IMPL_RELEASE(WebGLByteArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLByteArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasByteArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasByteArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLByteArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLByteArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasByteArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLByteArray)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLUnsignedByteArray)
 NS_IMPL_RELEASE(WebGLUnsignedByteArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLUnsignedByteArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasUnsignedByteArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasUnsignedByteArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLUnsignedByteArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLUnsignedByteArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasUnsignedByteArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLUnsignedByteArray)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLShortArray)
 NS_IMPL_RELEASE(WebGLShortArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLShortArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasShortArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasShortArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLShortArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLShortArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasShortArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLShortArray)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLUnsignedShortArray)
 NS_IMPL_RELEASE(WebGLUnsignedShortArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLUnsignedShortArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasUnsignedShortArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasUnsignedShortArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLUnsignedShortArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLUnsignedShortArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasUnsignedShortArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLUnsignedShortArray)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLIntArray)
 NS_IMPL_RELEASE(WebGLIntArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLIntArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasIntArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasIntArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLIntArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLIntArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasIntArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLIntArray)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WebGLUnsignedIntArray)
 NS_IMPL_RELEASE(WebGLUnsignedIntArray)
 
 NS_INTERFACE_MAP_BEGIN(WebGLUnsignedIntArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasArray)
-  NS_INTERFACE_MAP_ENTRY(nsICanvasUnsignedIntArray)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICanvasUnsignedIntArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLArray)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLUnsignedIntArray)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebGLUnsignedIntArray)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CanvasUnsignedIntArray)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(WebGLUnsignedIntArray)
 NS_INTERFACE_MAP_END
--- a/content/canvas/src/WebGLArrays.h
+++ b/content/canvas/src/WebGLArrays.h
@@ -45,267 +45,294 @@
 #include "nsTArray.h"
 #include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsHashKeys.h"
 
 #include "nsICanvasRenderingContextWebGL.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsIJSNativeInitializer.h"
+#include "nsIXPCScriptable.h"
 
 #include "SimpleBuffer.h"
 
 namespace mozilla {
 
 //
 // array wrapper classes
 //
 
 // XXX refactor buffer stuff
 class WebGLArrayBuffer :
-    public nsICanvasArrayBuffer,
+    public nsIWebGLArrayBuffer,
     public nsIJSNativeInitializer,
     public SimpleBuffer
 {
 public:
 
     WebGLArrayBuffer() { }
     WebGLArrayBuffer(PRUint32 length);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAYBUFFER
+    NS_DECL_NSIWEBGLARRAYBUFFER
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 };
 
+class WebGLArray
+{
+    
+};
+
 class WebGLFloatArray :
-    public nsICanvasFloatArray,
+    public nsIXPCScriptable,
+    public nsIWebGLFloatArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLFloatArray() :
         mOffset(0), mLength(0) { }
 
     WebGLFloatArray(PRUint32 length);
     WebGLFloatArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLFloatArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASFLOATARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLFLOATARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, float value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
 };
 
 class WebGLByteArray :
-    public nsICanvasByteArray,
+    public nsIXPCScriptable,
+    public nsIWebGLByteArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLByteArray() :
         mOffset(0), mLength(0) { }
 
     WebGLByteArray(PRUint32 length);
     WebGLByteArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLByteArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASBYTEARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLBYTEARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, char value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
 };
 
 class WebGLUnsignedByteArray :
-    public nsICanvasUnsignedByteArray,
+    public nsIXPCScriptable,
+    public nsIWebGLUnsignedByteArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLUnsignedByteArray() :
         mOffset(0), mLength(0) { }
 
     WebGLUnsignedByteArray(PRUint32 length);
     WebGLUnsignedByteArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLUnsignedByteArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASUNSIGNEDBYTEARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLUNSIGNEDBYTEARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, unsigned char value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
 };
 
 class WebGLShortArray :
-    public nsICanvasShortArray,
+    public nsIXPCScriptable,
+    public nsIWebGLShortArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLShortArray() :
         mOffset(0), mLength(0) { }
 
     WebGLShortArray(PRUint32 length);
     WebGLShortArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLShortArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASSHORTARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLSHORTARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, short value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
 };
 
 class WebGLUnsignedShortArray :
-    public nsICanvasUnsignedShortArray,
+    public nsIXPCScriptable,
+    public nsIWebGLUnsignedShortArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLUnsignedShortArray() :
         mOffset(0), mLength(0) { }
 
     WebGLUnsignedShortArray(PRUint32 length);
     WebGLUnsignedShortArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLUnsignedShortArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASUNSIGNEDSHORTARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLUNSIGNEDSHORTARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, unsigned short value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
 };
 
 class WebGLIntArray :
-    public nsICanvasIntArray,
+    public nsIXPCScriptable,
+    public nsIWebGLIntArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLIntArray() :
         mOffset(0), mLength(0) { }
 
     WebGLIntArray(PRUint32 length);
     WebGLIntArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLIntArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASINTARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLINTARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, int value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
 };
 
 class WebGLUnsignedIntArray :
-    public nsICanvasUnsignedIntArray,
+    public nsIXPCScriptable,
+    public nsIWebGLUnsignedIntArray,
     public nsIJSNativeInitializer
 {
 public:
     WebGLUnsignedIntArray() :
         mOffset(0), mLength(0) { }
 
     WebGLUnsignedIntArray(PRUint32 length);
     WebGLUnsignedIntArray(WebGLArrayBuffer *buffer, PRUint32 offset, PRUint32 length);
     WebGLUnsignedIntArray(JSContext *cx, JSObject *arrayObj, jsuint arrayLen);
 
     NS_DECL_ISUPPORTS
-    NS_DECL_NSICANVASARRAY
-    NS_DECL_NSICANVASUNSIGNEDINTARRAY
+    NS_DECL_NSIWEBGLARRAY
+    NS_DECL_NSIWEBGLUNSIGNEDINTARRAY
+    NS_DECL_NSIXPCSCRIPTABLE
 
     NS_IMETHOD Initialize(nsISupports* aOwner,
                           JSContext* aCx,
                           JSObject* aObj,
                           PRUint32 aArgc,
                           jsval* aArgv);
 
     void Set(PRUint32 index, unsigned int value);
+    PRBool JSValToIndex(JSContext *cx, jsval id, uint32 *retval);
 
 protected:
     nsRefPtr<WebGLArrayBuffer> mBuffer;
     PRUint32 mOffset;
     PRUint32 mLength;
     PRUint32 mSize;
     PRUint32 mElementSize;
     PRUint32 mCount;
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -261,17 +261,17 @@ protected:
     PRBool ValidateBuffers(PRUint32 count);
 
     void Invalidate();
 
     void MakeContextCurrent() { mGLPbuffer->MakeContextCurrent(); }
 
     nsresult TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
                                  gfxImageSurface **imageOut,
-                                 bool flipY, bool premultiplyAlpha);
+                                 PRBool flipY, PRBool premultiplyAlpha);
 
     GLuint mActiveTexture;
 
     // the buffers bound to the current program's attribs
     nsTArray<WebGLVertexAttribData> mAttribBuffers;
 
     // the textures bound to any sampler uniforms
     nsTArray<WebGLObjectRefPtr<WebGLTexture> > mUniformTextures;
@@ -348,17 +348,17 @@ public:
         if (mDeleted)
             return;
         ZeroOwners();
         mDeleted = PR_TRUE;
     }
     PRBool Deleted() { return mDeleted; }
     GLuint GLName() { return mName; }
 
-    void Set(nsICanvasArray *na) {
+    void Set(nsIWebGLArray *na) {
         mGLType = na->NativeType();
         mElementSize = na->NativeElementSize();
         mCount = na->NativeCount();
     }
 
     void SetCount(GLuint count) {
         mCount = count;
     }
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -102,19 +102,19 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, 
 NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \
     MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \
 }
 
 //
 //  WebGL API
 //
 
-/* nsICanvasFloatArray createFloatArray (); */
+/* nsIWebGLFloatArray createFloatArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateFloatArray(nsICanvasFloatArray **retval)
+WebGLContext::CreateFloatArray(nsIWebGLFloatArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -129,19 +129,19 @@ WebGLContext::CreateFloatArray(nsICanvas
 
     WebGLFloatArray *wgfa = new WebGLFloatArray(js.ctx, arrayObj, arrayLen);
     if (wgfa)
         NS_ADDREF(*retval = wgfa);
 
     return NS_OK;
 }
 
-/* nsICanvasByteArray createByteArray (); */
+/* nsIWebGLByteArray createByteArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateByteArray(nsICanvasByteArray **retval)
+WebGLContext::CreateByteArray(nsIWebGLByteArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -155,19 +155,19 @@ WebGLContext::CreateByteArray(nsICanvasB
     }
 
     WebGLByteArray *wgba = new WebGLByteArray(js.ctx, arrayObj, arrayLen);
     if (wgba)
         NS_ADDREF(*retval = wgba);
     return NS_OK;
 }
 
-/* nsICanvasUnsignedByteArray createUnsignedByteArray (); */
+/* nsIWebGLUnsignedByteArray createUnsignedByteArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateUnsignedByteArray(nsICanvasUnsignedByteArray **retval)
+WebGLContext::CreateUnsignedByteArray(nsIWebGLUnsignedByteArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -181,19 +181,19 @@ WebGLContext::CreateUnsignedByteArray(ns
     }
 
     WebGLUnsignedByteArray *wguba = new WebGLUnsignedByteArray(js.ctx, arrayObj, arrayLen);
     if (wguba)
         NS_ADDREF(*retval = wguba);
     return NS_OK;
 }
 
-/* nsICanvasShortArray createShortArray (); */
+/* nsIWebGLShortArray createShortArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateShortArray(nsICanvasShortArray **retval)
+WebGLContext::CreateShortArray(nsIWebGLShortArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -207,19 +207,19 @@ WebGLContext::CreateShortArray(nsICanvas
     }
 
     WebGLShortArray *wgsa = new WebGLShortArray(js.ctx, arrayObj, arrayLen);
     if (wgsa)
         NS_ADDREF(*retval = wgsa);
     return NS_OK;
 }
 
-/* nsICanvasUnsignedShortArray createUnsignedShortArray (); */
+/* nsIWebGLUnsignedShortArray createUnsignedShortArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateUnsignedShortArray(nsICanvasUnsignedShortArray **retval)
+WebGLContext::CreateUnsignedShortArray(nsIWebGLUnsignedShortArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -234,19 +234,19 @@ WebGLContext::CreateUnsignedShortArray(n
 
     WebGLUnsignedShortArray *wgusa = new WebGLUnsignedShortArray(js.ctx, arrayObj, arrayLen);
     if (wgusa)
         NS_ADDREF(*retval = wgusa);
     return NS_OK;
 }
 
 
-/* nsICanvasUnsignedIntArray createUnsignedIntArray (); */
+/* nsIWebGLUnsignedIntArray createUnsignedIntArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateIntArray(nsICanvasIntArray **retval)
+WebGLContext::CreateIntArray(nsIWebGLIntArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -260,19 +260,19 @@ WebGLContext::CreateIntArray(nsICanvasIn
     }
 
     WebGLIntArray *wgia = new WebGLIntArray(js.ctx, arrayObj, arrayLen);
     if (wgia)
         NS_ADDREF(*retval = wgia);
     return NS_OK;
 }
 
-/* nsICanvasUnsignedIntArray createUnsignedIntArray (); */
+/* nsIWebGLUnsignedIntArray createUnsignedIntArray (); */
 NS_IMETHODIMP
-WebGLContext::CreateUnsignedIntArray(nsICanvasUnsignedIntArray **retval)
+WebGLContext::CreateUnsignedIntArray(nsIWebGLUnsignedIntArray **retval)
 {
     NativeJSContext js;
 
     if (js.argc != 1)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
     JSObject *arrayObj;
     jsuint arrayLen;
@@ -474,18 +474,18 @@ GL_SAME_METHOD_2(BlendFunc, BlendFunc, P
 
 GL_SAME_METHOD_4(BlendFuncSeparate, BlendFuncSeparate, PRUint32, PRUint32, PRUint32, PRUint32)
 
 NS_IMETHODIMP
 WebGLContext::BufferData(GLenum target)
 {
     // overloaded:
     // void bufferData (in GLenum target, in GLsizei size, in GLenum usage);
-    // void bufferData (in GLenum target, in nsICanvasArray data, in GLenum usage);
-    // void bufferData (in GLenum target, in nsICanvasArrayBuffer data, in GLenum usage)
+    // void bufferData (in GLenum target, in nsIWebGLArray data, in GLenum usage);
+    // void bufferData (in GLenum target, in nsIWebGLArrayBuffer data, in GLenum usage)
 
     NativeJSContext js;
     if (NS_FAILED(js.error))
         return js.error;
 
     if (js.argc != 3)
         return NS_ERROR_DOM_SYNTAX_ERR;
 
@@ -519,25 +519,25 @@ WebGLContext::BufferData(GLenum target)
     if (JSVAL_IS_NUMBER(js.argv[1])) {
         int32 size;
         if (!::JS_ValueToECMAInt32(js.ctx, js.argv[1], &size)) {
             return ErrorMessage("bufferData: invalid size parameter");
         }
         boundBuffer->SetCount(size);
         gl->fBufferData(target, size, 0, usage);
     } else if (JSVAL_IS_OBJECT(js.argv[1])) {
-        nsCOMPtr<nsICanvasArray> canvasArrayObj;
+        nsCOMPtr<nsIWebGLArray> canvasArrayObj;
         nsresult rv;
 
         rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[1]),
-                                                 NS_GET_IID(nsICanvasArray), getter_AddRefs(canvasArrayObj));
+                                                 NS_GET_IID(nsIWebGLArray), getter_AddRefs(canvasArrayObj));
         if (NS_FAILED(rv) || !canvasArrayObj) {
-            nsCOMPtr<nsICanvasArrayBuffer> arrayBuf;
+            nsCOMPtr<nsIWebGLArrayBuffer> arrayBuf;
             rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[1]),
-                                                     NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(arrayBuf));
+                                                     NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(arrayBuf));
             if (NS_FAILED(rv) || !arrayBuf)
                 return ErrorMessage("bufferData: need CanvasArray or CanvasArrayBuffer");
 
             boundBuffer->SetCount(arrayBuf->NativeSize());
             gl->fBufferData(target, arrayBuf->NativeSize(), arrayBuf->NativePointer(), usage);
         } else {
             boundBuffer->Set(canvasArrayObj);
             gl->fBufferData(target, canvasArrayObj->NativeSize(), canvasArrayObj->NativePointer(), usage);
@@ -581,25 +581,25 @@ WebGLContext::BufferSubData(GLenum targe
     // check type
     if (na->NativeType() != boundBuffer->GLType()) {
         return ErrorMessage("glBufferSubData: existing buffer has different base type (0x%04x) the sub data (0x%04x)!", boundBuffer->GLType(), na->NativeType());
         return NS_ERROR_FAILURE;
     }
     */
 
     if (JSVAL_IS_OBJECT(js.argv[2])) {
-        nsCOMPtr<nsICanvasArray> canvasArrayObj;
+        nsCOMPtr<nsIWebGLArray> canvasArrayObj;
         nsresult rv;
 
         rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[2]),
-                                                 NS_GET_IID(nsICanvasArray), getter_AddRefs(canvasArrayObj));
+                                                 NS_GET_IID(nsIWebGLArray), getter_AddRefs(canvasArrayObj));
         if (NS_FAILED(rv) || !canvasArrayObj) {
-            nsCOMPtr<nsICanvasArrayBuffer> arrayBuf;
+            nsCOMPtr<nsIWebGLArrayBuffer> arrayBuf;
             rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[2]),
-                                                     NS_GET_IID(nsICanvasArrayBuffer), getter_AddRefs(arrayBuf));
+                                                     NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(arrayBuf));
             if (NS_FAILED(rv) || !arrayBuf)
                 return ErrorMessage("bufferData: need CanvasArray or CanvasArrayBuffer");
 
             // check size
             // XXX should be bytes
             if ((offset + arrayBuf->NativeSize()) > boundBuffer->Count()) {
                 return ErrorMessage("glBufferSubData: existing buffer is too small (%d) for data at offset (%d+%d)",
                                     boundBuffer->Count(), offset, arrayBuf->NativeSize());
@@ -2317,17 +2317,17 @@ GL_SAME_METHOD_2(StencilMaskSeparate, St
 GL_SAME_METHOD_3(StencilOp, StencilOp, GLenum, GLenum, GLenum)
 
 GL_SAME_METHOD_4(StencilOpSeparate, StencilOpSeparate, GLenum, GLenum, GLenum, GLenum)
 
 
 nsresult
 WebGLContext::TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
                                   gfxImageSurface **imageOut,
-                                  bool flipY, bool premultiplyAlpha)
+                                  PRBool flipY, PRBool premultiplyAlpha)
 {
     gfxImageSurface *surf = nsnull;
 
     nsLayoutUtils::SurfaceFromElementResult res =
         nsLayoutUtils::SurfaceFromElement(imageOrCanvas,
                                           nsLayoutUtils::SFE_WANT_NEW_SURFACE | nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
     if (!res.mSurface)
         return NS_ERROR_FAILURE;
@@ -2453,17 +2453,17 @@ GL_SAME_METHOD_5(Uniform4i, Uniform4i, G
 GL_SAME_METHOD_2(Uniform1f, Uniform1f, GLint, GLfloat)
 GL_SAME_METHOD_3(Uniform2f, Uniform2f, GLint, GLfloat, GLfloat)
 GL_SAME_METHOD_4(Uniform3f, Uniform3f, GLint, GLfloat, GLfloat, GLfloat)
 GL_SAME_METHOD_5(Uniform4f, Uniform4f, GLint, GLfloat, GLfloat, GLfloat, GLfloat)
 
 // one uint arg followed by an array of c elements of glTypeConst.
 #define GL_SIMPLE_ARRAY_METHOD(glname, name, c, glTypeConst, ptrType)             \
 NS_IMETHODIMP                                                                     \
-WebGLContext::name(GLint idx, nsICanvasArray *v)                                  \
+WebGLContext::name(GLint idx, nsIWebGLArray *v)                                  \
 {                                                                                 \
     NativeJSContext js;                                                           \
     if (NS_FAILED(js.error))                                                      \
         return js.error;                                                          \
     JSObject *arrayObj;                                                           \
     jsuint arrayLen;                                                              \
     if (js.argc != 2)                                                             \
         return NS_ERROR_INVALID_ARG;                                              \
@@ -2499,17 +2499,17 @@ WebGLContext::name(GLint idx, nsICanvasA
             return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\
         }                                                                         \
     }                                                                             \
     return NS_OK;                                                                 \
 }
 
 #define GL_SIMPLE_ARRAY_METHOD_NO_COUNT(glname, name, c, glTypeConst, ptrType)    \
 NS_IMETHODIMP                                                                     \
-WebGLContext::name(GLuint idx, nsICanvasArray *v)                                 \
+WebGLContext::name(GLuint idx, nsIWebGLArray *v)                                 \
 {                                                                                 \
     NativeJSContext js;                                                           \
     if (NS_FAILED(js.error))                                                      \
         return js.error;                                                          \
     JSObject *arrayObj;                                                           \
     jsuint arrayLen;                                                              \
     if (js.argc != 2)                                                             \
         return NS_ERROR_INVALID_ARG;                                              \
@@ -2545,17 +2545,17 @@ WebGLContext::name(GLuint idx, nsICanvas
             return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\
         }                                                                         \
     }                                                                             \
     return NS_OK;                                                                 \
 }
 
 #define GL_SIMPLE_MATRIX_METHOD(glname, name, c, glTypeConst, ptrType)            \
 NS_IMETHODIMP                                                                     \
-WebGLContext::name(GLint location, GLboolean transpose, nsICanvasArray *value)    \
+WebGLContext::name(GLint location, GLboolean transpose, nsIWebGLArray *value)    \
 {                                                                                 \
     NativeJSContext js;                                                           \
     if (NS_FAILED(js.error))                                                      \
         return js.error;                                                          \
     JSObject *arrayObj;                                                           \
     jsuint arrayLen;                                                              \
     if (js.argc != 3)                                                             \
         return NS_ERROR_INVALID_ARG;                                              \
@@ -2964,17 +2964,16 @@ WebGLContext::TexSubImage2D()
             return ErrorMessage("texImage2D: failed to get image for element");
 
         MakeContextCurrent();
 
         gl->fTexSubImage2D (argTarget, argLevel, argX, argY, isurf->Width(), isurf->Height(), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
     } else {
         jsuint argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType;
         JSObject *argPixelsObj;
-        jsuint argPixelsLen;
         if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
                                    &argTarget, &argLevel, &argX, &argY,
                                    &argWidth, &argHeight, &argFormat, &argType,
                                    &argPixelsObj) ||
             !argPixelsObj)
             {
                 return ErrorMessage("texSubImage2D: argument error");
                 return NS_ERROR_DOM_SYNTAX_ERR;
@@ -3045,30 +3044,30 @@ WebGLContext::TexSubImage2D()
         }
 
         tmp = tmp * bufferSize;
         if (tmp && tmp / bufferSize != (argWidth * argHeight)) {
             return ErrorMessage("texSubImage2D: too large width or height (after multiplying with pixel size)");
             return NS_ERROR_DOM_SYNTAX_ERR;
         }
 
-        if ((PRUint32) tmp > argPixelsLen) {
-            return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        nsCOMPtr<nsICanvasArray> arrayObj;
+        nsCOMPtr<nsIWebGLArray> arrayObj;
         nsresult rv;
         rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj));
         arrayObj = do_QueryInterface(arrayObj, &rv);
 
         if (NS_FAILED(rv) || !arrayObj) {
             return ErrorMessage("texSubImage2D: pixels arg is not a WebGL array");
         }
 
+        if ((PRUint32) tmp > arrayObj->NativeSize()) {
+            return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format");
+            return NS_ERROR_DOM_SYNTAX_ERR;
+        }
+
         MakeContextCurrent();
         gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, arrayObj->NativePointer());
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D()
@@ -3122,17 +3121,16 @@ WebGLContext::TexImage2D()
             return ErrorMessage("texImage2D: failed to get image for element");
 
         MakeContextCurrent();
 
         gl->fTexImage2D (argTarget, argLevel, LOCAL_GL_RGBA, isurf->Width(), isurf->Height(), 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
 
     } else if (js.argc == 9) {
         JSObject *argPixelsObj;
-        jsuint argPixelsLen;
         if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
                                    &argTarget, &argLevel, &argInternalFormat, &argWidth,
                                    &argHeight, &argBorder, &argFormat, &argType,
                                    &argPixelsObj) ||
             !argPixelsObj)
             {
                 return ErrorMessage("texImage2D: argument error");
                 return NS_ERROR_DOM_SYNTAX_ERR;
@@ -3230,30 +3228,30 @@ WebGLContext::TexImage2D()
         }
 
         // XXX handle LOCAL_GL_UNPACK_ALIGNMENT !
 
         if (argPixelsObj == NULL) {
             MakeContextCurrent();
             gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, NULL);
         } else {
-            if ((PRUint32) tmp > argPixelsLen) {
-                return ErrorMessage("texImage2D: array dimensions too small for width, height and pixel format");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-            }
-
-            nsCOMPtr<nsICanvasArray> arrayObj;
+            nsCOMPtr<nsIWebGLArray> arrayObj;
             nsresult rv;
             rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj));
             arrayObj = do_QueryInterface(arrayObj, &rv);
 
             if (NS_FAILED(rv) || !arrayObj) {
                 return ErrorMessage("texImage2D: pixels arg is not a WebGL array");
             }
 
+            if ((PRUint32) tmp > arrayObj->NativeSize()) {
+                return ErrorMessage("texImage2D: array dimensions too small for width, height and pixel format");
+                return NS_ERROR_DOM_SYNTAX_ERR;
+            }
+
             MakeContextCurrent();
             gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, arrayObj->NativePointer());
         }
     }
     return NS_OK;
 }
 
 #if 0
--- a/content/canvas/src/WebGLContextNotSupported.cpp
+++ b/content/canvas/src/WebGLContextNotSupported.cpp
@@ -37,16 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsICanvasRenderingContextWebGL.h"
 #include "WebGLArray.h"
 
 #define DUMMY(func,rtype)  nsresult func (rtype ** aResult) { return NS_ERROR_FAILURE; }
 
 DUMMY(NS_NewCanvasRenderingContextWebGL, nsICanvasRenderingContextWebGL)
-DUMMY(NS_NewCanvasFloatArray, nsISupports)
-DUMMY(NS_NewCanvasByteArray, nsISupports)
-DUMMY(NS_NewCanvasUnsignedByteArray, nsISupports)
-DUMMY(NS_NewCanvasShortArray, nsISupports)
-DUMMY(NS_NewCanvasUnsignedShortArray, nsISupports)
-DUMMY(NS_NewCanvasIntArray, nsISupports)
-DUMMY(NS_NewCanvasUnsignedIntArray, nsISupports)
-DUMMY(NS_NewCanvasArrayBuffer, nsISupports)
+DUMMY(NS_NewWebGLFloatArray, nsISupports)
+DUMMY(NS_NewWebGLByteArray, nsISupports)
+DUMMY(NS_NewWebGLUnsignedByteArray, nsISupports)
+DUMMY(NS_NewWebGLShortArray, nsISupports)
+DUMMY(NS_NewWebGLUnsignedShortArray, nsISupports)
+DUMMY(NS_NewWebGLIntArray, nsISupports)
+DUMMY(NS_NewWebGLUnsignedIntArray, nsISupports)
+DUMMY(NS_NewWebGLArrayBuffer, nsISupports)
--- a/content/canvas/src/nsGLPbufferWGL.cpp
+++ b/content/canvas/src/nsGLPbufferWGL.cpp
@@ -282,17 +282,17 @@ nsGLPbufferWGL::Resize(PRInt32 width, PR
 
     float fattribs[] = { 0.0f };
 
     // ATI's OpenGL impl seems to have a problem with calling
     // wglChoosePixelFormatARB with NULL/0 to obtain the number of
     // matching formats; so just allocate room for a lot.
 #define MAX_NUM_FORMATS 256
     UINT numFormats = MAX_NUM_FORMATS;
-    nsAutoArrayPtr<int> formats = new int[numFormats];
+    int formats[MAX_NUM_FORMATS];
 
     //fprintf (stderr, "EXT: %p ARB: %p rest: %s\n", wglewGetContext()->__wglewChoosePixelFormatEXT, wglewGetContext()->__wglewChoosePixelFormatARB, wglGetExtensionsStringARB(mGlewDC));
 
 TRY_FIND_AGAIN:
     if (ignoreAA) {
         attribs[18] = 0;
     } else if (prefAntialiasing > 0) {
         attribs[18] = WGL_SAMPLE_BUFFERS_ARB;
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -75,16 +75,21 @@ PRBool         nsIMEStateManager::sInsta
 nsTextStateManager* nsIMEStateManager::sTextStateObserver = nsnull;
 
 nsresult
 nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
   if (aPresContext != sPresContext)
     return NS_OK;
+  nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
+  if (widget) {
+    PRUint32 newState = GetNewIMEState(sPresContext, nsnull);
+    SetIMEState(sPresContext, newState, widget);
+  }
   sContent = nsnull;
   sPresContext = nsnull;
   OnTextStateBlur(nsnull, nsnull);
   return NS_OK;
 }
 
 nsresult
 nsIMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
@@ -97,16 +102,18 @@ nsIMEStateManager::OnRemoveContent(nsPre
     return NS_OK;
 
   // Current IME transaction should commit
   nsCOMPtr<nsIWidget> widget = GetWidget(sPresContext);
   if (widget) {
     nsresult rv = widget->CancelIMEComposition();
     if (NS_FAILED(rv))
       widget->ResetInputState();
+    PRUint32 newState = GetNewIMEState(sPresContext, nsnull);
+    SetIMEState(sPresContext, newState, widget);
   }
 
   sContent = nsnull;
   sPresContext = nsnull;
 
   return NS_OK;
 }
 
new file mode 100644
--- /dev/null
+++ b/content/xslt/crashtests/528963.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xml" href="#bug"?>
+<!DOCTYPE doc [
+<!ATTLIST xsl:transform
+  id	ID	#REQUIRED>
+]>
+<doc>
+  <xsl:transform 
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    version="2.0"
+    id="bug">
+    <xsl:key name="k0" match="e2" use="name('foo')" /> 
+
+    <xsl:template name="t1" match="/">
+      <xsl:element name="e2" namespace="{//doc}" />
+    </xsl:template>
+    <xsl:template name="t2" match="key('k0', 'bar')" />
+  </xsl:transform>
+  
+  <e2/>
+  
+</doc>
--- a/content/xslt/crashtests/crashtests.list
+++ b/content/xslt/crashtests/crashtests.list
@@ -3,8 +3,9 @@ load 111994.xml
 load 182460-table.xhtml
 load 226425.xml
 load 406106-1.html
 load 483444.xml
 load 485217.xml
 load 485286.xml
 load 528300.xml
 load 528488.xml
+load 528963.xml
--- a/content/xslt/src/xslt/txKeyFunctionCall.cpp
+++ b/content/xslt/src/xslt/txKeyFunctionCall.cpp
@@ -393,19 +393,19 @@ nsresult txXSLKey::testNode(const txXPat
             NS_ENSURE_TRUE(evalContext, NS_ERROR_OUT_OF_MEMORY);
 
             nsresult rv = aEs.pushEvalContext(evalContext);
             NS_ENSURE_SUCCESS(rv, rv);
 
             nsRefPtr<txAExprResult> exprResult;
             rv = mKeys[currKey].useExpr->evaluate(evalContext,
                                                   getter_AddRefs(exprResult));
-            NS_ENSURE_SUCCESS(rv, rv);
 
             delete aEs.popEvalContext();
+            NS_ENSURE_SUCCESS(rv, rv);
 
             if (exprResult->getResultType() == txAExprResult::NODESET) {
                 txNodeSet* res = static_cast<txNodeSet*>
                                             (static_cast<txAExprResult*>
                                                         (exprResult));
                 PRInt32 i;
                 for (i = 0; i < res->size(); ++i) {
                     val.Truncate();
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1331,32 +1331,39 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(WebGLProgram, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLShader, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLFramebuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLRenderbuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasArrayBuffer, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasFloatArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasByteArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasUnsignedByteArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasShortArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasUnsignedShortArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasIntArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(CanvasUnsignedIntArray, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(WebGLArrayBuffer, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(WebGLFloatArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLByteArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedByteArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLShortArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedShortArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLIntArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
+  NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedIntArray, nsDOMGenericSH,
+                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
+                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
 
   NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PaintRequestList, nsPaintRequestListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(ScrollAreaEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1394,24 +1401,24 @@ struct nsConstructorFuncMapData
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   { eDOMClassInfo_##_class##_id, _func },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
 
   // WebGL Array Types
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasArrayBuffer, NS_NewCanvasArrayBuffer)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasFloatArray, NS_NewCanvasFloatArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasByteArray, NS_NewCanvasByteArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasUnsignedByteArray, NS_NewCanvasUnsignedByteArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasShortArray, NS_NewCanvasShortArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasUnsignedShortArray, NS_NewCanvasUnsignedShortArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasIntArray, NS_NewCanvasIntArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(CanvasUnsignedIntArray, NS_NewCanvasUnsignedIntArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLArrayBuffer, NS_NewWebGLArrayBuffer)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLFloatArray, NS_NewWebGLFloatArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLByteArray, NS_NewWebGLByteArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedByteArray, NS_NewWebGLUnsignedByteArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLShortArray, NS_NewWebGLShortArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedShortArray, NS_NewWebGLUnsignedShortArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLIntArray, NS_NewWebGLIntArray)
+  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedIntArray, NS_NewWebGLUnsignedIntArray)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
 PRBool nsDOMClassInfo::sIsInitialized = PR_FALSE;
 PRBool nsDOMClassInfo::sDisableDocumentAllSupport = PR_FALSE;
 PRBool nsDOMClassInfo::sDisableGlobalScopePollutionSupport = PR_FALSE;
 
@@ -3729,46 +3736,46 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(WebGLFramebuffer, nsIWebGLFramebuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLFramebuffer)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLRenderbuffer, nsIWebGLRenderbuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLRenderbuffer)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(CanvasArrayBuffer, nsICanvasArrayBuffer)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasArrayBuffer)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasFloatArray, nsICanvasFloatArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasFloatArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasByteArray, nsICanvasByteArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasByteArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasUnsignedByteArray, nsICanvasUnsignedByteArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasUnsignedByteArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasShortArray, nsICanvasShortArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasShortArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasUnsignedShortArray, nsICanvasUnsignedShortArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasUnsignedShortArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasIntArray, nsICanvasIntArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasIntArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(CanvasUnsignedIntArray, nsICanvasUnsignedIntArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsICanvasUnsignedIntArray)
+  DOM_CLASSINFO_MAP_BEGIN(WebGLArrayBuffer, nsIWebGLArrayBuffer)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLArrayBuffer)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLFloatArray, nsIWebGLFloatArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLFloatArray)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLByteArray, nsIWebGLByteArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLByteArray)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedByteArray, nsIWebGLUnsignedByteArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedByteArray)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLShortArray, nsIWebGLShortArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLShortArray)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedShortArray, nsIWebGLUnsignedShortArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedShortArray)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLIntArray, nsIWebGLIntArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLIntArray)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedIntArray, nsIWebGLUnsignedIntArray)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedIntArray)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
    DOM_CLASSINFO_MAP_END
  
   DOM_CLASSINFO_MAP_BEGIN(PaintRequestList, nsIDOMPaintRequestList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequestList)
--- a/dom/base/nsDOMClassInfoID.h
+++ b/dom/base/nsDOMClassInfoID.h
@@ -468,24 +468,24 @@ enum nsDOMClassInfoID {
   eDOMClassInfo_WebGLBuffer_id,
   eDOMClassInfo_WebGLTexture_id,
   eDOMClassInfo_WebGLProgram_id,
   eDOMClassInfo_WebGLShader_id,
   eDOMClassInfo_WebGLFramebuffer_id,
   eDOMClassInfo_WebGLRenderbuffer_id,
 
   // WebGL Buffers
-  eDOMClassInfo_CanvasArrayBuffer_id,
-  eDOMClassInfo_CanvasFloatArray_id,
-  eDOMClassInfo_CanvasByteArray_id,
-  eDOMClassInfo_CanvasUnsignedByteArray_id,
-  eDOMClassInfo_CanvasShortArray_id,
-  eDOMClassInfo_CanvasUnsignedShortArray_id,
-  eDOMClassInfo_CanvasIntArray_id,
-  eDOMClassInfo_CanvasUnsignedIntArray_id,
+  eDOMClassInfo_WebGLArrayBuffer_id,
+  eDOMClassInfo_WebGLFloatArray_id,
+  eDOMClassInfo_WebGLByteArray_id,
+  eDOMClassInfo_WebGLUnsignedByteArray_id,
+  eDOMClassInfo_WebGLShortArray_id,
+  eDOMClassInfo_WebGLUnsignedShortArray_id,
+  eDOMClassInfo_WebGLIntArray_id,
+  eDOMClassInfo_WebGLUnsignedIntArray_id,
 
   eDOMClassInfo_PaintRequest_id,
   eDOMClassInfo_PaintRequestList_id,
 
   eDOMClassInfo_ScrollAreaEvent_id,
 
   eDOMClassInfo_EventListenerInfo_id,
 
--- a/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
+++ b/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl
@@ -66,107 +66,107 @@ namespace mozilla {
     class WebGLArrayBuffer;
 }
 %}
 [ptr] native WebGLArrayBufferPtr (mozilla::WebGLArrayBuffer);
 //
 // Array types
 //
 [scriptable, uuid(34b6cf8e-47da-458e-ab42-0451a3533ee5)]
-interface nsICanvasArrayBuffer : nsISupports
+interface nsIWebGLArrayBuffer : nsISupports
 {
   readonly attribute unsigned long byteLength;
 
   [noscript, notxpcom] WebGLArrayBufferPtr GetNativeArrayBuffer();
   [noscript, notxpcom] voidPtr nativePointer();
   [noscript, notxpcom] unsigned long nativeSize();
 };
 
 [scriptable, uuid(84ba4e98-8173-7c10-dca0-b5ba7809fcf3)]
-interface nsICanvasArray : nsISupports
+interface nsIWebGLArray : nsISupports
 {
-  readonly attribute nsICanvasArrayBuffer buffer;
+  readonly attribute nsIWebGLArrayBuffer buffer;
   readonly attribute unsigned long byteOffset;
   readonly attribute unsigned long byteLength;
   readonly attribute unsigned long length;
 
   // XXX kill this.
   unsigned long alignedSizeInBytes();
 
-  nsICanvasArray slice(in unsigned long offset, in unsigned long length);
+  nsIWebGLArray slice(in unsigned long offset, in unsigned long length);
 
   [noscript, notxpcom] unsigned long nativeType();
   [noscript, notxpcom] voidPtr nativePointer();
   [noscript, notxpcom] unsigned long nativeSize();
   [noscript, notxpcom] unsigned long nativeElementSize();
   [noscript, notxpcom] unsigned long nativeCount();
 };
 
 [scriptable, Uuid(0f6d0e7b-bcfc-9305-6a1d-a9653b5e8c80)]
-interface nsICanvasFloatArray : nsICanvasArray
+interface nsIWebGLFloatArray : nsIWebGLArray
 {
   [IndexGetter] float get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in float value);
   //void set(in CanvasFloatArray array, [Optional] in unsigned long offset);
   //void set(in sequence<float> array, [Optional] in unsigned long offset);
   void set();
 };
 
 [scriptable, uuid(b29db7cf-fa58-435f-8d45-611cc50979ad)]
-interface nsICanvasByteArray : nsICanvasArray
+interface nsIWebGLByteArray : nsIWebGLArray
 {
   [IndexGetter] long get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in long value);
-  //void set(in nsICanvasByteArray array, [Optional] in unsigned long offset);
+  //void set(in nsIWebGLByteArray array, [Optional] in unsigned long offset);
   //void set(in sequence<long> array, [Optional] in unsigned long offset);
   void set();
 };
 
 [scriptable, uuid(3daa67fa-e743-2cbd-a212-805c2fc520cc)]
-interface nsICanvasUnsignedByteArray : nsICanvasArray
+interface nsIWebGLUnsignedByteArray : nsIWebGLArray
 {
   [IndexGetter] unsigned long get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in unsigned long value);
   //void set(in CanvasUnsignedByteArray array, [Optional] in unsigned long offset);
   //void set(in sequence<unsigned long> array, [Optional] in unsigned long offset);
   void set();
 };
 
 [scriptable, uuid(a8a982e3-3977-7364-f012-c497a5ab7681)]
-interface nsICanvasShortArray : nsICanvasArray
+interface nsIWebGLShortArray : nsIWebGLArray
 {
   [IndexGetter] long get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in long value);
   //void set(in CanvasShortArray array, [Optional] in unsigned long offset);
   //void set(in sequence<long> array, [Optional] in unsigned long offset);
   void set();
 };
 
 [scriptable, uuid(8b9c67cc-c7be-a062-84b0-76a910a5c1e6)]
-interface nsICanvasUnsignedShortArray : nsICanvasArray
+interface nsIWebGLUnsignedShortArray : nsIWebGLArray
 {
   [IndexGetter] unsigned long get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in unsigned long value);
   //void set(in CanvasUnsignedShortArray array, [Optional] in unsigned long offset);
   //void set(in sequence<unsigned long> array, [Optional] in unsigned long offset);
   void set();
 };
 
 [scriptable, uuid(b9b2e861-3a28-4311-993c-799e4f77dcba)]
-interface nsICanvasIntArray : nsICanvasArray
+interface nsIWebGLIntArray : nsIWebGLArray
 {
   [IndexGetter] long get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in long value);
   //void set(in CanvasIntArray array, [Optional] in unsigned long offset);
   //void set(in sequence<long> array, [Optional] in unsigned long offset);
   void set();
 };
 
 [scriptable, uuid(0d6ee3f8-71b6-460d-b05a-d579cc55edbe)]
-interface nsICanvasUnsignedIntArray : nsICanvasArray
+interface nsIWebGLUnsignedIntArray : nsIWebGLArray
 {
   [IndexGetter] unsigned long get(in unsigned long index);
   //[IndexSetter] void set(in unsigned long index, in unsigned long value);
   //void set(in CanvasUnsignedIntArray array, [Optional] in unsigned long offset);
   //void set(in sequence<unsigned long> array, [Optional] in unsigned long offset);
   void set();
 };
 
@@ -226,23 +226,23 @@ interface nsIWebGLActiveInfo {
 
 [scriptable, uuid(f02c85e0-8305-11de-abe2-000c29206271)]
 interface nsICanvasRenderingContextWebGL : nsISupports
 {
   //
   //  ARRAY CONSTRUCTORS
   //
 
-  nsICanvasFloatArray createFloatArray();
-  nsICanvasByteArray createByteArray();
-  nsICanvasUnsignedByteArray createUnsignedByteArray();
-  nsICanvasShortArray createShortArray();
-  nsICanvasUnsignedShortArray createUnsignedShortArray();
-  nsICanvasIntArray createIntArray();
-  nsICanvasUnsignedIntArray createUnsignedIntArray();
+  nsIWebGLFloatArray createFloatArray();
+  nsIWebGLByteArray createByteArray();
+  nsIWebGLUnsignedByteArray createUnsignedByteArray();
+  nsIWebGLShortArray createShortArray();
+  nsIWebGLUnsignedShortArray createUnsignedShortArray();
+  nsIWebGLIntArray createIntArray();
+  nsIWebGLUnsignedIntArray createUnsignedIntArray();
 
   //
   //  CONSTANTS
   //
 
   /* ClearBufferMask */
   const unsigned long DEPTH_BUFFER_BIT               = 0x00000100;
   const unsigned long STENCIL_BUFFER_BIT             = 0x00000400;
@@ -352,16 +352,20 @@ interface nsICanvasRenderingContextWebGL
   const unsigned long STENCIL_TEST                   = 0x0B90;
   const unsigned long DEPTH_TEST                     = 0x0B71;
   const unsigned long SCISSOR_TEST                   = 0x0C11;
   const unsigned long POLYGON_OFFSET_FILL            = 0x8037;
   const unsigned long SAMPLE_ALPHA_TO_COVERAGE       = 0x809E;
   const unsigned long SAMPLE_COVERAGE                = 0x80A0;
 
   /* ErrorCode */
+%{C++
+/* Avoid conflict with WinAPI */
+#undef NO_ERROR
+%}
   const unsigned long NO_ERROR                       = 0;
   const unsigned long INVALID_ENUM                   = 0x0500;
   const unsigned long INVALID_VALUE                  = 0x0501;
   const unsigned long INVALID_OPERATION              = 0x0502;
   const unsigned long OUT_OF_MEMORY                  = 0x0505;
 
   /* FrontFaceDirection */
   const unsigned long CW                             = 0x0900;
@@ -687,22 +691,22 @@ interface nsICanvasRenderingContextWebGL
   void blendColor (in GLclampf red, in GLclampf green, in GLclampf blue, in GLclampf alpha);
   void blendEquation (in GLenum mode);
   void blendEquationSeparate (in GLenum modeRGB, in GLenum modeAlpha);
   void blendFunc (in GLenum sfactor, in GLenum dfactor);
   void blendFuncSeparate (in GLenum srcRGB, in GLenum dstRGB, in GLenum srcAlpha, in GLenum dstAlpha);
 
   // Modified: void glBufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage);
   // void bufferData (in GLenum target, in GLsizei size, in GLenum usage);
-  // void bufferData (in GLenum target, in nsICanvasArray data, in GLenum usage);
-  // void bufferData (in GLenum target, in nsICanvasArrayBuffer data, in GLenum usage);
+  // void bufferData (in GLenum target, in nsIWebGLArray data, in GLenum usage);
+  // void bufferData (in GLenum target, in nsIWebGLArrayBuffer data, in GLenum usage);
   void bufferData (in GLenum target);
 
   // Modified: void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data);
-  // void bufferSubData (in GLenum target, in GLsizeiptr offset, in nsICanvasArray data);
+  // void bufferSubData (in GLenum target, in GLsizeiptr offset, in nsIWebGLArray data);
   // void bufferSubData (in GLenum target, in GLsizeiptr offset, in CanvasArrayBuffer data);
   void bufferSubData (in GLenum target, in GLsizeiptr offset);
 
   GLenum checkFramebufferStatus (in GLenum target);
   void clear (in GLbitfield mask);
   void clearColor (in GLclampf red, in GLclampf green, in GLclampf blue, in GLclampf alpha);
   void clearDepth (in GLclampf depth);
   void clearStencil (in GLint s);
@@ -880,56 +884,56 @@ interface nsICanvasRenderingContextWebGL
   // Modified: void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
   //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in GLenum format, in GLenum type, nsIWebGLArray pixels);
   //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in HTMLImageElement image);
   //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in HTMLnsIWebGLElement canvas);
   //void glTexSubImage2D (in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, in GLsizei width, in GLsizei height, in HTMLVideoElement video);
 
   void texSubImage2D ();
 
-  // Modified: All the glUniform*v forms below are modified by replacing 'count' and 'v' with a nsICanvasArray
+  // Modified: All the glUniform*v forms below are modified by replacing 'count' and 'v' with a nsIWebGLArray
   void uniform1f (in GLint location, in GLfloat x);
   void uniform1i (in GLint location, in GLint x);
   void uniform2f (in GLint location, in GLfloat x, in GLfloat y);
   void uniform2i (in GLint location, in GLint x, in GLint y);
   void uniform3f (in GLint location, in GLfloat x, in GLfloat y, in GLfloat z);
   void uniform3i (in GLint location, in GLint x, in GLint y, in GLint z);
   void uniform4f (in GLint location, in GLfloat x, in GLfloat y, in GLfloat z, in GLfloat w);
   void uniform4i (in GLint location, in GLint x, in GLint y, in GLint z, in GLint w);
 
-  void uniform1fv (in GLint location, in nsICanvasArray v);
-  void uniform1iv (in GLint location, in nsICanvasArray v);
-  void uniform2fv (in GLint location, in nsICanvasArray v);
-  void uniform2iv (in GLint location, in nsICanvasArray v);
-  void uniform3fv (in GLint location, in nsICanvasArray v);
-  void uniform3iv (in GLint location, in nsICanvasArray v);
-  void uniform4fv (in GLint location, in nsICanvasArray v);
-  void uniform4iv (in GLint location, in nsICanvasArray v);
+  void uniform1fv (in GLint location, in nsIWebGLArray v);
+  void uniform1iv (in GLint location, in nsIWebGLArray v);
+  void uniform2fv (in GLint location, in nsIWebGLArray v);
+  void uniform2iv (in GLint location, in nsIWebGLArray v);
+  void uniform3fv (in GLint location, in nsIWebGLArray v);
+  void uniform3iv (in GLint location, in nsIWebGLArray v);
+  void uniform4fv (in GLint location, in nsIWebGLArray v);
+  void uniform4iv (in GLint location, in nsIWebGLArray v);
 
-  // Modified. These are modified by replacing 'count' and 'value' with a nsICanvasArray
-  void uniformMatrix2fv (in GLint location, in GLboolean transpose, in nsICanvasArray value);
-  void uniformMatrix3fv (in GLint location, in GLboolean transpose, in nsICanvasArray value);
-  void uniformMatrix4fv (in GLint location, in GLboolean transpose, in nsICanvasArray value);
+  // Modified. These are modified by replacing 'count' and 'value' with a nsIWebGLArray
+  void uniformMatrix2fv (in GLint location, in GLboolean transpose, in nsIWebGLArray value);
+  void uniformMatrix3fv (in GLint location, in GLboolean transpose, in nsIWebGLArray value);
+  void uniformMatrix4fv (in GLint location, in GLboolean transpose, in nsIWebGLArray value);
 
   // Added API using top entry from the passed nsIWebGLMatrixStack
   //ZZ void glUniformMatrix (in GLint location, in GLboolean transpose, in nsIWebGLMatrixStack value);
 
   void useProgram (in nsIWebGLProgram program);
   void validateProgram (in nsIWebGLProgram program);
 
-  // Modified: All the glVertexAttrib*v forms below are modified by replacing 'values' with a nsICanvasArray
+  // Modified: All the glVertexAttrib*v forms below are modified by replacing 'values' with a nsIWebGLArray
   void vertexAttrib1f (in GLuint indx, in GLfloat x);
   void vertexAttrib2f (in GLuint indx, in GLfloat x, in GLfloat y);
   void vertexAttrib3f (in GLuint indx, in GLfloat x, in GLfloat y, in GLfloat z);
   void vertexAttrib4f (in GLuint indx, in GLfloat x, in GLfloat y, in GLfloat z, in GLfloat w);
 
-  void vertexAttrib1fv (in GLuint indx, in nsICanvasArray values);
-  void vertexAttrib2fv (in GLuint indx, in nsICanvasArray values);
-  void vertexAttrib3fv (in GLuint indx, in nsICanvasArray values);
-  void vertexAttrib4fv (in GLuint indx, in nsICanvasArray values);
+  void vertexAttrib1fv (in GLuint indx, in nsIWebGLArray values);
+  void vertexAttrib2fv (in GLuint indx, in nsIWebGLArray values);
+  void vertexAttrib3fv (in GLuint indx, in nsIWebGLArray values);
+  void vertexAttrib4fv (in GLuint indx, in nsIWebGLArray values);
 
   // TBD
   //void glVertexAttribPointer (in GLuint indx, GLint size, GLenum type, GLboolean normalized, 
   // GLsizei stride, const void* ptr);
 
   // size is number of elements; type must match the bound vbo type; offset is in elements
   void vertexAttribPointer (in GLuint idx, in GLint size, in GLenum type, in GLboolean normalized, in GLuint stride, in GLuint offset);
 
--- a/dom/plugins/BrowserStreamChild.cpp
+++ b/dom/plugins/BrowserStreamChild.cpp
@@ -122,16 +122,26 @@ BrowserStreamChild::AnswerNPP_StreamAsFi
   if (mClosed)
     return true;
 
   mInstance->mPluginIface->asfile(&mInstance->mData, &mStream,
                                   fname.get());
   return true;
 }
 
+bool
+BrowserStreamChild::Answer__delete__(const NPError& reason,
+                                     const bool& artificial)
+{
+  AssertPluginThread();
+  if (!artificial)
+    NPP_DestroyStream(reason);
+  return true;
+}
+
 NPError
 BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
 {
   AssertPluginThread();
 
   IPCByteRanges ranges;
   for (; aRangeList; aRangeList = aRangeList->next) {
     IPCByteRange br = {aRangeList->offset, aRangeList->length};
--- a/dom/plugins/BrowserStreamChild.h
+++ b/dom/plugins/BrowserStreamChild.h
@@ -66,16 +66,19 @@ public:
 
   virtual bool AnswerNPP_WriteReady(const int32_t& newlength,
                                         int32_t *size);
   virtual bool AnswerNPP_Write(const int32_t& offset,
                                    const Buffer& data,
                                    int32_t* consumed);
 
   virtual bool AnswerNPP_StreamAsFile(const nsCString& fname);
+  virtual bool Answer__delete__(const NPError& reason,
+                                const bool& artificial);
+
 
   void EnsureCorrectInstance(PluginInstanceChild* i)
   {
     if (i != mInstance)
       NS_RUNTIMEABORT("Incorrect stream instance");
   }
   void EnsureCorrectStream(NPStream* s)
   {
--- a/dom/plugins/BrowserStreamParent.cpp
+++ b/dom/plugins/BrowserStreamParent.cpp
@@ -39,16 +39,25 @@ BrowserStreamParent::AnswerNPN_RequestRe
     rp[i].next = &rp[i + 1];
   }
   rp[ranges.size() - 1].next = NULL;
 
   *result = mNPP->mNPNIface->requestread(mStream, rp);
   return true;
 }
 
+bool
+BrowserStreamParent::Answer__delete__(const NPError& reason,
+                                      const bool& artificial)
+{
+  if (!artificial)
+    NPN_DestroyStream(reason);
+  return true;
+}
+
 int32_t
 BrowserStreamParent::WriteReady()
 {
   _MOZ_LOG(__FUNCTION__);
 
   int32_t result;
   if (!CallNPP_WriteReady(mStream->end, &result))
     return -1;
--- a/dom/plugins/BrowserStreamParent.h
+++ b/dom/plugins/BrowserStreamParent.h
@@ -56,22 +56,26 @@ public:
                       NPStream* stream);
   virtual ~BrowserStreamParent();
 
   NS_OVERRIDE virtual bool IsBrowserStream() { return true; }
 
   virtual bool AnswerNPN_RequestRead(const IPCByteRanges& ranges,
                                      NPError* result);
 
+  virtual bool
+  Answer__delete__(const NPError& reason, const bool& artificial);
+
   int32_t WriteReady();
   int32_t Write(int32_t offset, int32_t len, void* buffer);
   void StreamAsFile(const char* fname);
+
+private:
   NPError NPN_DestroyStream(NPError reason);
 
-private:
   PluginInstanceParent* mNPP;
   NPStream* mStream;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif
--- a/dom/plugins/PBrowserStream.ipdl
+++ b/dom/plugins/PBrowserStream.ipdl
@@ -38,16 +38,17 @@
 include protocol "PPluginInstance.ipdl";
 
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using mozilla::plugins::Buffer;
 using mozilla::plugins::IPCByteRanges;
 
 using NPError;
+using NPReason;
 
 namespace mozilla {
 namespace plugins {
 
 /**
  * NPBrowserStream represents a NPStream sent from the browser to the plugin.
  */
 
@@ -63,12 +64,20 @@ child:
                 Buffer data)
     returns (int32_t consumed);
 
   rpc NPP_StreamAsFile(nsCString fname);
 
 parent:
   rpc NPN_RequestRead(IPCByteRanges ranges)
     returns (NPError result);
+
+both:
+  /**
+   * ~PBrowserStream is for both NPN_DestroyStream and NPP_DestroyStream.
+   * @param artificial True when the stream is closed as a by-product of
+   *                        some other call (such as a failure in NPP_Write).
+   */
+  rpc __delete__(NPReason reason, bool artificial);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PPluginInstance.ipdl
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -43,57 +43,59 @@ include protocol "PBrowserStream.ipdl";
 include protocol "PPluginStream.ipdl";
 include protocol "PStreamNotify.ipdl";
 
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using NPError;
 using NPRemoteWindow;
 using NPRemoteEvent;
-using NPReason;
 using NPRect;
 
 namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginInstance
 {
   manager PPluginModule;
 
   manages PPluginScriptableObject;
   manages PBrowserStream;
   manages PPluginStream;
   manages PStreamNotify;
 
 child:
+  rpc __delete__()
+    returns (NPError rv);
+
   rpc NPP_SetWindow(NPRemoteWindow window)
     returns (NPError rv);
 
   rpc NPP_GetValue_NPPVpluginWindow()
     returns (bool value, NPError result);
   rpc NPP_GetValue_NPPVpluginTransparent()
     returns (bool value, NPError result);
   // this message is not used on non-X platforms
   rpc NPP_GetValue_NPPVpluginNeedsXEmbed()
     returns (bool value, NPError result);
   rpc NPP_GetValue_NPPVpluginScriptableNPObject()
-    returns (PPluginScriptableObject value, NPError result);
+    returns (nullable PPluginScriptableObject value, NPError result);
 
   rpc NPP_HandleEvent(NPRemoteEvent event)
     returns (int16_t handled);
 
 parent:
   rpc NPN_GetValue_NPNVjavascriptEnabledBool()
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVisOfflineBool()
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVWindowNPObject()
-    returns (PPluginScriptableObject value, NPError result);
+    returns (nullable PPluginScriptableObject value, NPError result);
   rpc NPN_GetValue_NPNVPluginElementNPObject()
-    returns (PPluginScriptableObject value, NPError result);
+    returns (nullable PPluginScriptableObject value, NPError result);
   rpc NPN_GetValue_NPNVprivateModeBool()
     returns (bool value, NPError result);
 
   rpc NPN_SetValue_NPPVpluginWindow(bool windowed)
     returns (NPError result);
   rpc NPN_SetValue_NPPVpluginTransparent(bool transparent)
     returns (NPError result);
 
@@ -114,56 +116,32 @@ parent:
   async NPN_InvalidateRect(NPRect rect);
 
   rpc NPN_PushPopupsEnabledState(bool aState)
     returns (bool aSuccess);
 
   rpc NPN_PopPopupsEnabledState()
     returns (bool aSuccess);
 
-child:
-  /**
-   * Represents NPP_URLNotify
-   */
-  rpc ~PStreamNotify(NPReason reason);
-
 both:
   rpc PPluginScriptableObject();
-  rpc ~PPluginScriptableObject();
 
 child:
   /* NPP_NewStream */
   rpc PBrowserStream(nsCString url,
                      uint32_t length,
                      uint32_t lastmodified,
-                     PStreamNotify notifyData,
+                     nullable PStreamNotify notifyData,
                      nsCString headers,
                      nsCString mimeType,
                      bool seekable)
     returns (NPError rv,
              uint16_t stype);
 
-both:
-  /**
-   * ~PBrowserStream is for both NPN_DestroyStream and NPP_DestroyStream.
-   * @param artificial True when the stream is closed as a by-product of
-   *                        some other call (such as a failure in NPP_Write).
-   */
-  rpc ~PBrowserStream(NPReason reason,
-                      bool artificial);
-
 parent:
   /* NPN_NewStream */
   rpc PPluginStream(nsCString mimeType,
                     nsCString target)
     returns (NPError result);
-
-both:
-  /**
-   * ~PPluginStream is for both NPN_DestroyStream and NPP_DestroyStream.
-   * @param artificial True when the stream is closed as a by-product of
-   *                        some other call (such as a failure in NPN_Write).
-   */
-  rpc ~PPluginStream(NPReason reason, bool artificial);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PPluginModule.ipdl
+++ b/dom/plugins/PPluginModule.ipdl
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 include protocol "PPluginInstance.ipdl";
 
 include "npapi.h";
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using NPError;
+using NPNVariable;
 using mozilla::ipc::NPRemoteIdentifier;
 
 namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginModule
 {
   manages PPluginInstance;
@@ -57,19 +58,16 @@ child:
     returns (NPError rv);
 
   rpc PPluginInstance(nsCString aMimeType,
                       uint16_t aMode,
                       nsCString[] aNames,
                       nsCString[] aValues)
     returns (NPError rv);
 
-  rpc ~PPluginInstance()
-    returns (NPError rv);
-
   rpc NP_Shutdown()
     returns (NPError rv);
 
 parent:
   rpc NPN_UserAgent()
     returns (nsCString userAgent);
 
   sync NPN_GetStringIdentifier(nsCString aString)
@@ -86,12 +84,16 @@ parent:
   sync NPN_IntFromIdentifier(NPRemoteIdentifier aId)
     returns (NPError err, int32_t aInt);
 
   sync NPN_IdentifierIsString(NPRemoteIdentifier aId)
     returns (bool aIsString);
 
   sync NPN_GetStringIdentifiers(nsCString[] aNames)
     returns (NPRemoteIdentifier[] aIds);
+
+  rpc NPN_GetValue_WithBoolReturn(NPNVariable aVariable)
+    returns (NPError aError,
+             bool aBoolVal);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PPluginScriptableObject.ipdl
+++ b/dom/plugins/PPluginScriptableObject.ipdl
@@ -52,23 +52,26 @@ namespace plugins {
 
 union Variant {
   void_t;
   null_t;
   bool;
   int;
   double;
   nsCString;
-  PPluginScriptableObject;
+  nullable PPluginScriptableObject;
 };
 
 rpc protocol PPluginScriptableObject
 {
   manager PPluginInstance;
 
+both:
+  rpc __delete__();
+
 parent:
   rpc NPN_Evaluate(nsCString aScript)
     returns (Variant aResult,
              bool aSuccess);
 
 both:
   // NPClass methods
   rpc Invalidate();
--- a/dom/plugins/PPluginStream.ipdl
+++ b/dom/plugins/PPluginStream.ipdl
@@ -36,26 +36,35 @@
  * ***** END LICENSE BLOCK ***** */
 
 include protocol "PPluginInstance.ipdl";
 
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using mozilla::plugins::Buffer;
 using NPError;
+using NPReason;
 
 namespace mozilla {
 namespace plugins {
 
 /**
  * PPluginStream represents an NPStream sent from the plugin to the browser.
  */
 
 rpc protocol PPluginStream
 {
   manager PPluginInstance;
 
 parent:
   rpc NPN_Write(Buffer data) returns (int32_t written);
+
+both:
+  /**
+   * ~PPluginStream is for both NPN_DestroyStream and NPP_DestroyStream.
+   * @param artificial True when the stream is closed as a by-product of
+   *                        some other call (such as a failure in NPN_Write).
+   */
+  rpc __delete__(NPReason reason, bool artificial);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PStreamNotify.ipdl
+++ b/dom/plugins/PStreamNotify.ipdl
@@ -1,17 +1,27 @@
 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
 
 include protocol "PPluginInstance.ipdl";
 
+include "npapi.h";
+
+using NPReason;
+
 namespace mozilla {
 namespace plugins {
 
 /**
  * This empty protocol exists only to be constructed and destroyed.
  */
 rpc protocol PStreamNotify
 {
   manager PPluginInstance;
+
+child:
+  /**
+   * Represents NPP_URLNotify
+   */
+  rpc __delete__(NPReason reason);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -16,16 +16,17 @@
  * The Original Code is Mozilla Plugin App.
  *
  * The Initial Developer of the Original Code is
  *   Chris Jones <jones.chris.g@gmail.com>
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -49,16 +50,17 @@ using namespace mozilla::plugins;
 #ifdef MOZ_WIDGET_GTK2
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdk.h>
 #include "gtk2xtbin.h"
 
 #elif defined(OS_WIN)
+using mozilla::gfx::SharedDIB;
 
 #include <windows.h>
 
 #endif
 
 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface) :
         mPluginIface(aPluginIface)
 #if defined(OS_WIN)
@@ -80,16 +82,24 @@ PluginInstanceChild::PluginInstanceChild
 
 PluginInstanceChild::~PluginInstanceChild()
 {
 #if defined(OS_WIN)
   DestroyPluginWindow();
 #endif
 }
 
+bool
+PluginInstanceChild::Answer__delete__(NPError* rv)
+{
+    return static_cast<PluginModuleChild*>(Manager())->
+        PluginInstanceDestroyed(this, rv);
+}
+
+
 NPError
 PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
                                   void* aValue)
 {
     printf ("[PluginInstanceChild] NPN_GetValue(%s)\n",
             NPNVariableToString(aVar));
     AssertPluginThread();
 
@@ -323,18 +333,25 @@ PluginInstanceChild::AnswerNPP_HandleEve
     AssertPluginThread();
 
 #if defined(OS_LINUX) && defined(DEBUG)
     if (GraphicsExpose == event.event.type)
         printf("  received drawable 0x%lx\n",
                event.event.xgraphicsexpose.drawable);
 #endif
 
-    // plugins might be fooling with these, make a copy
+    // Make a copy since we may modify values.
     NPEvent evcopy = event.event;
+
+#ifdef OS_WIN
+    // Setup the shared dib for painting and update evcopy.
+    if (NPWindowTypeDrawable == mWindow.type && WM_PAINT == evcopy.event)
+        SharedSurfaceBeforePaint(evcopy);
+#endif
+
     *handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
 
 #ifdef MOZ_X11
     if (GraphicsExpose == event.event.type) {
         // Make sure the X server completes the drawing before the parent
         // draws on top and destroys the Drawable.
         //
         // XSync() waits for the X server to complete.  Really this child
@@ -403,55 +420,68 @@ PluginInstanceChild::AnswerNPP_SetWindow
     mWsInfo.colormap = aWindow.colormap;
     if (!XVisualIDToInfo(mWsInfo.display, aWindow.visualID,
                          &mWsInfo.visual, &mWsInfo.depth))
         return false;
 
     *rv = mPluginIface->setwindow(&mData, &mWindow);
 
 #elif defined(OS_WIN)
-    ReparentPluginWindow((HWND)aWindow.window);
-    SizePluginWindow(aWindow.width, aWindow.height);
+    switch (aWindow.type) {
+      case NPWindowTypeWindow:
+      {
+          if (!CreatePluginWindow())
+              return false;
 
-    mWindow.window = (void*)mPluginWindowHWND;
-    mWindow.x = aWindow.x;
-    mWindow.y = aWindow.y;
-    mWindow.width = aWindow.width;
-    mWindow.height = aWindow.height;
-    mWindow.type = aWindow.type;
+          ReparentPluginWindow((HWND)aWindow.window);
+          SizePluginWindow(aWindow.width, aWindow.height);
+
+          mWindow.window = (void*)mPluginWindowHWND;
+          mWindow.x = aWindow.x;
+          mWindow.y = aWindow.y;
+          mWindow.width = aWindow.width;
+          mWindow.height = aWindow.height;
+          mWindow.type = aWindow.type;
 
-    *rv = mPluginIface->setwindow(&mData, &mWindow);
-    if (*rv == NPERR_NO_ERROR) {
-        WNDPROC wndProc = reinterpret_cast<WNDPROC>(
-            GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
-        if (wndProc != PluginWindowProc) {
-            mPluginWndProc = reinterpret_cast<WNDPROC>(
-                SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
-                                 reinterpret_cast<LONG>(PluginWindowProc)));
-        }
+          *rv = mPluginIface->setwindow(&mData, &mWindow);
+          if (*rv == NPERR_NO_ERROR) {
+              WNDPROC wndProc = reinterpret_cast<WNDPROC>(
+                  GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
+              if (wndProc != PluginWindowProc) {
+                  mPluginWndProc = reinterpret_cast<WNDPROC>(
+                      SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
+                                       reinterpret_cast<LONG>(PluginWindowProc)));
+              }
+          }
+      }
+      break;
+
+      case NPWindowTypeDrawable:
+          return SharedSurfaceSetWindow(aWindow, rv);
+      break;
+
+      default:
+          NS_NOTREACHED("Bad plugin window type.");
+          return false;
+      break;
     }
 
 #elif defined(OS_MACOSX)
 #  warning This is only a stub implementation IMPLEMENT ME
 
 #else
 #  error Implement me for your OS
 #endif
 
     return true;
 }
 
 bool
 PluginInstanceChild::Initialize()
 {
-#if defined(OS_WIN)
-    if (!CreatePluginWindow())
-        return false;
-#endif
-
     return true;
 }
 
 void
 PluginInstanceChild::Destroy()
 {
     // Copy the actors here so we don't enumerate a mutating array.
     nsAutoTArray<PluginScriptableObjectChild*, 10> objects;
@@ -463,16 +493,20 @@ PluginInstanceChild::Destroy()
     count = objects.Length();
     for (PRUint32 index = 0; index < count; index++) {
         PluginScriptableObjectChild*& actor = objects[index];
         NPObject* object = actor->GetObject();
         if (object->_class == PluginScriptableObjectChild::GetClass()) {
           PluginScriptableObjectChild::ScriptableInvalidate(object);
         }
     }
+
+#if defined(OS_WIN)
+    SharedSurfaceRelease();
+#endif
 }
 
 #if defined(OS_WIN)
 
 static const TCHAR kWindowClassName[] = TEXT("GeckoPluginWindow");
 static const TCHAR kPluginInstanceChildProperty[] = TEXT("PluginInstanceChildProperty");
 
 // static
@@ -500,36 +534,38 @@ PluginInstanceChild::RegisterWindowClass
     wcex.hIconSm        = 0;
 
     return RegisterClassEx(&wcex) ? true : false;
 }
 
 bool
 PluginInstanceChild::CreatePluginWindow()
 {
+    // already initialized
+    if (mPluginWindowHWND)
+        return true;
+        
     if (!RegisterWindowClass())
         return false;
 
-    if (!mPluginWindowHWND) {
-        mPluginWindowHWND =
-            CreateWindowEx(WS_EX_LEFT | WS_EX_LTRREADING |
-                           WS_EX_NOPARENTNOTIFY | // XXXbent Get rid of this!
-                           WS_EX_RIGHTSCROLLBAR,
-                           kWindowClassName, 0,
-                           WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
-                           0, 0, NULL, 0, GetModuleHandle(NULL), 0);
-        if (!mPluginWindowHWND)
-            return false;
-        if (!SetProp(mPluginWindowHWND, kPluginInstanceChildProperty, this))
-            return false;
+    mPluginWindowHWND =
+        CreateWindowEx(WS_EX_LEFT | WS_EX_LTRREADING |
+                       WS_EX_NOPARENTNOTIFY | // XXXbent Get rid of this!
+                       WS_EX_RIGHTSCROLLBAR,
+                       kWindowClassName, 0,
+                       WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
+                       0, 0, NULL, 0, GetModuleHandle(NULL), 0);
+    if (!mPluginWindowHWND)
+        return false;
+    if (!SetProp(mPluginWindowHWND, kPluginInstanceChildProperty, this))
+        return false;
 
-        // Apparently some plugins require an ASCII WndProc.
-        SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC,
-                          reinterpret_cast<LONG>(DefWindowProcA));
-    }
+    // Apparently some plugins require an ASCII WndProc.
+    SetWindowLongPtrA(mPluginWindowHWND, GWLP_WNDPROC,
+                      reinterpret_cast<LONG>(DefWindowProcA));
 
     return true;
 }
 
 void
 PluginInstanceChild::DestroyPluginWindow()
 {
     if (mPluginWindowHWND) {
@@ -615,16 +651,70 @@ PluginInstanceChild::PluginWindowProc(HW
         self->DestroyPluginWindow();
 
     if (message == WM_NCDESTROY)
         RemoveProp(hWnd, kPluginInstanceChildProperty);
 
     return res;
 }
 
+/* windowless drawing helpers */
+
+bool
+PluginInstanceChild::SharedSurfaceSetWindow(const NPRemoteWindow& aWindow,
+                                            NPError* rv)
+{
+    // If the surfaceHandle is empty, parent is telling us we can reuse our cached
+    // memory surface and hdc. Otherwise, we need to reset, usually due to a
+    // expanding plugin port size.
+    if (!aWindow.surfaceHandle) {
+        if (!mSharedSurfaceDib.IsValid()) {
+            return false;
+        }
+    }
+    else {
+        // Attach to the new shared surface parent handed us.
+        if (NS_FAILED(mSharedSurfaceDib.Attach((SharedDIB::Handle)aWindow.surfaceHandle,
+                                               aWindow.width, aWindow.height, 32)))
+          return false;
+    }
+      
+    // NPRemoteWindow's origin is the origin of our shared dib.
+    mWindow.x      = 0;
+    mWindow.y      = 0;
+    mWindow.width  = aWindow.width;
+    mWindow.height = aWindow.height;
+    mWindow.type   = aWindow.type;
+
+    mWindow.window = reinterpret_cast<void*>(mSharedSurfaceDib.GetHDC());
+    *rv = mPluginIface->setwindow(&mData, &mWindow);
+
+    return true;
+}
+
+void
+PluginInstanceChild::SharedSurfaceRelease()
+{
+    mSharedSurfaceDib.Close();
+}
+
+void
+PluginInstanceChild::SharedSurfaceBeforePaint(NPEvent& evcopy)
+{
+    // Update the clip rect on our internal hdc
+    RECT* pRect = reinterpret_cast<RECT*>(evcopy.lParam);
+    if (pRect) {
+      HRGN clip = ::CreateRectRgnIndirect(pRect);
+      ::SelectClipRgn(mSharedSurfaceDib.GetHDC(), clip);
+      ::DeleteObject(clip);
+    }
+    // pass the internal hdc to the plugin
+    evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC());
+}
+
 #endif // OS_WIN
 
 PPluginScriptableObjectChild*
 PluginInstanceChild::AllocPPluginScriptableObject()
 {
     AssertPluginThread();
 
     nsAutoPtr<PluginScriptableObjectChild>* object =
@@ -634,17 +724,17 @@ PluginInstanceChild::AllocPPluginScripta
     *object = new PluginScriptableObjectChild();
     NS_ENSURE_TRUE(*object, nsnull);
 
     return object->get();
 }
 
 bool
 PluginInstanceChild::DeallocPPluginScriptableObject(
-                                          PPluginScriptableObjectChild* aObject)
+    PPluginScriptableObjectChild* aObject)
 {
     AssertPluginThread();
 
     PluginScriptableObjectChild* object =
         reinterpret_cast<PluginScriptableObjectChild*>(aObject);
 
     NPObject* npobject = object->GetObject();
     if (npobject &&
@@ -701,61 +791,34 @@ PluginInstanceChild::AllocPBrowserStream
                                          uint16_t *stype)
 {
     AssertPluginThread();
     return new BrowserStreamChild(this, url, length, lastmodified, notifyData,
                                   headers, mimeType, seekable, rv, stype);
 }
 
 bool
-PluginInstanceChild::AnswerPBrowserStreamDestructor(PBrowserStreamChild* stream,
-                                                    const NPError& reason,
-                                                    const bool& artificial)
-{
-    AssertPluginThread();
-    if (!artificial)
-        static_cast<BrowserStreamChild*>(stream)->NPP_DestroyStream(reason);
-    return true;
-}
-
-bool
-PluginInstanceChild::DeallocPBrowserStream(PBrowserStreamChild* stream,
-                                           const NPError& reason,
-                                           const bool& artificial)
+PluginInstanceChild::DeallocPBrowserStream(PBrowserStreamChild* stream)
 {
     AssertPluginThread();
     delete stream;
     return true;
 }
 
 PPluginStreamChild*
 PluginInstanceChild::AllocPPluginStream(const nsCString& mimeType,
                                         const nsCString& target,
                                         NPError* result)
 {
     NS_RUNTIMEABORT("not callable");
     return NULL;
 }
 
 bool
-PluginInstanceChild::AnswerPPluginStreamDestructor(PPluginStreamChild* stream,
-                                                   const NPReason& reason,
-                                                   const bool& artificial)
-{
-    AssertPluginThread();
-    if (!artificial) {
-        static_cast<PluginStreamChild*>(stream)->NPP_DestroyStream(reason);
-    }
-    return true;
-}
-
-bool
-PluginInstanceChild::DeallocPPluginStream(PPluginStreamChild* stream,
-                                          const NPError& reason,
-                                          const bool& artificial)
+PluginInstanceChild::DeallocPPluginStream(PPluginStreamChild* stream)
 {
     AssertPluginThread();
     delete stream;
     return true;
 }
 
 PStreamNotifyChild*
 PluginInstanceChild::AllocPStreamNotify(const nsCString& url,
@@ -766,32 +829,37 @@ PluginInstanceChild::AllocPStreamNotify(
                                         NPError* result)
 {
     AssertPluginThread();
     NS_RUNTIMEABORT("not reached");
     return NULL;
 }
 
 bool
-PluginInstanceChild::AnswerPStreamNotifyDestructor(PStreamNotifyChild* notifyData,
-                                                   const NPReason& reason)
+StreamNotifyChild::Answer__delete__(const NPReason& reason)
 {
     AssertPluginThread();
+    return static_cast<PluginInstanceChild*>(Manager())
+        ->NotifyStream(this, reason);
+}
 
-    StreamNotifyChild* sn = static_cast<StreamNotifyChild*>(notifyData);
-    if (sn->mClosure)
-        mPluginIface->urlnotify(&mData, sn->mURL.get(), reason, sn->mClosure);
-
+bool
+PluginInstanceChild::NotifyStream(StreamNotifyChild* notifyData,
+                                  NPReason reason)
+{
+    if (notifyData->mClosure)
+        mPluginIface->urlnotify(&mData, notifyData->mURL.get(), reason,
+                                notifyData->mClosure);
     return true;
 }
 
 bool
-PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData,
-                                          const NPReason& reason)
+PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild* notifyData)
 {
+    AssertPluginThread();
     delete notifyData;
     return true;
 }
 
 PluginScriptableObjectChild*
 PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
 {
     AssertPluginThread();
@@ -827,38 +895,45 @@ PluginInstanceChild::GetActorForNPObject
 }
 
 NPError
 PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
                                    NPStream** aStream)
 {
     AssertPluginThread();
 
-    PluginStreamChild* ps = new PluginStreamChild(this);
+    PluginStreamChild* ps = new PluginStreamChild();
 
     NPError result;
     CallPPluginStreamConstructor(ps, nsDependentCString(aMIMEType),
                                  NullableString(aWindow), &result);
     if (NPERR_NO_ERROR != result) {
         *aStream = NULL;
-        CallPPluginStreamDestructor(ps, NPERR_GENERIC_ERROR, true);
+        PPluginStreamChild::Call__delete__(ps, NPERR_GENERIC_ERROR, true);
         return result;
     }
 
     *aStream = &ps->mStream;
     return NPERR_NO_ERROR;
 }
 
 bool
 PluginInstanceChild::InternalInvalidateRect(NPRect* aInvalidRect)
 {
     NS_ASSERTION(aInvalidRect, "Null pointer!");
 
 #ifdef OS_WIN
-    NS_ASSERTION(IsWindow(mPluginWindowHWND), "Bad window?!");
-    RECT rect = { aInvalidRect->left, aInvalidRect->top,
-                  aInvalidRect->right, aInvalidRect->bottom };
-    InvalidateRect(mPluginWindowHWND, &rect, FALSE);
+    // Invalidate and draw locally for windowed plugins.
+    if (mWindow.type == NPWindowTypeWindow) {
+      NS_ASSERTION(IsWindow(mPluginWindowHWND), "Bad window?!");
+      RECT rect = { aInvalidRect->left, aInvalidRect->top,
+                    aInvalidRect->right, aInvalidRect->bottom };
+      InvalidateRect(mPluginWindowHWND, &rect, FALSE);
+      return false;
+    }
+    // Windowless need the invalidation to propegate to parent
+    // triggering wm_paint handle event calls.
+    return true;
 #endif
 
     // Windowless plugins must return true!
     return false;
 }
--- a/dom/plugins/PluginInstanceChild.h
+++ b/dom/plugins/PluginInstanceChild.h
@@ -36,16 +36,20 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef dom_plugins_PluginInstanceChild_h
 #define dom_plugins_PluginInstanceChild_h 1
 
 #include "mozilla/plugins/PPluginInstanceChild.h"
 #include "mozilla/plugins/PluginScriptableObjectChild.h"
+#include "mozilla/plugins/StreamNotifyChild.h"
+#if defined(OS_WIN)
+#include "mozilla/gfx/SharedDIBWin.h"
+#endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 
 #undef _MOZ_LOG
 #define _MOZ_LOG(s) printf("[PluginInstanceChild] %s\n", s)
 
@@ -65,16 +69,18 @@ class PluginInstanceChild : public PPlug
                                              UINT message,
                                              WPARAM wParam,
                                              LPARAM lParam);
 #endif
 
 protected:
     virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window, NPError* rv);
 
+    virtual bool Answer__delete__(NPError* rv);
+
 
     virtual bool
     AnswerNPP_GetValue_NPPVpluginWindow(bool* windowed, NPError* rv);
     virtual bool
     AnswerNPP_GetValue_NPPVpluginTransparent(bool* transparent, NPError* rv);
     virtual bool
     AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv);
     virtual bool
@@ -100,53 +106,34 @@ protected:
                         PStreamNotifyChild* notifyData,
                         const nsCString& headers,
                         const nsCString& mimeType,
                         const bool& seekable,
                         NPError* rv,
                         uint16_t *stype);
 
     virtual bool
-    AnswerPBrowserStreamDestructor(PBrowserStreamChild* stream,
-                                   const NPError& reason,
-                                   const bool& artificial);
-
-    virtual bool
-    DeallocPBrowserStream(PBrowserStreamChild* stream,
-                          const NPError& reason,
-                          const bool& artificial);
+    DeallocPBrowserStream(PBrowserStreamChild* stream);
 
     virtual PPluginStreamChild*
     AllocPPluginStream(const nsCString& mimeType,
                        const nsCString& target,
                        NPError* result);
 
     virtual bool
-    AnswerPPluginStreamDestructor(PPluginStreamChild* stream,
-                                  const NPReason& reason,
-                                  const bool& artificial);
-
-    virtual bool
-    DeallocPPluginStream(PPluginStreamChild* stream,
-                         const NPReason& reason,
-                         const bool& artificial);
+    DeallocPPluginStream(PPluginStreamChild* stream);
 
     virtual PStreamNotifyChild*
     AllocPStreamNotify(const nsCString& url, const nsCString& target,
                        const bool& post, const nsCString& buffer,
                        const bool& file,
                        NPError* result);
 
     NS_OVERRIDE virtual bool
-    AnswerPStreamNotifyDestructor(PStreamNotifyChild* notifyData,
-                                  const NPReason& reason);
-
-    NS_OVERRIDE virtual bool
-    DeallocPStreamNotify(PStreamNotifyChild* notifyData,
-                         const NPReason& reason);
+    DeallocPStreamNotify(PStreamNotifyChild* notifyData);
 
 public:
     PluginInstanceChild(const NPPluginFuncs* aPluginIface);
 
     virtual ~PluginInstanceChild();
 
     bool Initialize();
     void Destroy();
@@ -169,16 +156,18 @@ public:
     NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
                   NPStream** aStream);
 
     // Return true if you want to send the notification to the parent process
     // also.
     bool
     InternalInvalidateRect(NPRect* aInvalidRect);
 
+    bool NotifyStream(StreamNotifyChild* notifyData, NPReason reason);
+
 private:
 
 #if defined(OS_WIN)
     static bool RegisterWindowClass();
     bool CreatePluginWindow();
     void DestroyPluginWindow();
     void ReparentPluginWindow(HWND hWndParent);
     void SizePluginWindow(int width, int height);
@@ -199,14 +188,25 @@ private:
     NPSetWindowCallbackStruct mWsInfo;
 #elif defined(OS_WIN)
     HWND mPluginWindowHWND;
     WNDPROC mPluginWndProc;
     HWND mPluginParentHWND;
 #endif
 
     nsTArray<nsAutoPtr<PluginScriptableObjectChild> > mScriptableObjects;
+
+#if defined(OS_WIN)
+private:
+    // Shared dib rendering management for windowless plugins.
+    bool SharedSurfaceSetWindow(const NPRemoteWindow& aWindow, NPError* rv);
+    void SharedSurfaceBeforePaint(NPEvent& evcopy);
+    void SharedSurfaceRelease();
+
+private:
+    gfx::SharedDIBWin mSharedSurfaceDib;
+#endif // defined(OS_WIN)
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif // ifndef dom_plugins_PluginInstanceChild_h
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -16,16 +16,17 @@
  * The Original Code is Mozilla Plugin App.
  *
  * The Initial Developer of the Original Code is
  *   Chris Jones <jones.chris.g@gmail.com>
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -41,29 +42,44 @@
 #include "BrowserStreamParent.h"
 #include "PluginModuleParent.h"
 #include "PluginStreamParent.h"
 #include "StreamNotifyParent.h"
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 
+#if defined(OS_WIN)
+#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
+#endif
+
 using namespace mozilla::plugins;
 
 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
                                            NPP npp,
                                            const NPNetscapeFuncs* npniface)
   : mParent(parent),
     mNPP(npp),
-    mNPNIface(npniface)
+    mNPNIface(npniface),
+    mWindowType(NPWindowTypeWindow)
 {
+#if defined(OS_WIN)
+    // Event sent from nsObjectFrame indicating double pass rendering for
+    // windowless plugins. RegisterWindowMessage makes it easy sync event
+    // values, and insures we never conflict with windowing events we allow
+    // for windowless plugins.
+    mDoublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
+    mLocalCopyRender = false;
+#endif
 }
 
 PluginInstanceParent::~PluginInstanceParent()
 {
+    if (mNPP)
+        mNPP->pdata = NULL;
 }
 
 void
 PluginInstanceParent::Destroy()
 {
     // Copy the actors here so we don't enumerate a mutating array.
     nsAutoTArray<PluginScriptableObjectParent*, 10> objects;
     PRUint32 count = mScriptableObjects.Length();
@@ -73,16 +89,20 @@ PluginInstanceParent::Destroy()
 
     count = objects.Length();
     for (PRUint32 index = 0; index < count; index++) {
         NPObject* object = objects[index]->GetObject();
         if (object->_class == PluginScriptableObjectParent::GetClass()) {
           PluginScriptableObjectParent::ScriptableInvalidate(object);
         }
     }
+
+#if defined(OS_WIN)
+    SharedSurfaceRelease();
+#endif
 }
 
 PBrowserStreamParent*
 PluginInstanceParent::AllocPBrowserStream(const nsCString& url,
                                           const uint32_t& length,
                                           const uint32_t& lastmodified,
                                           PStreamNotifyParent* notifyData,
                                           const nsCString& headers,
@@ -91,51 +111,33 @@ PluginInstanceParent::AllocPBrowserStrea
                                           NPError* rv,
                                           uint16_t *stype)
 {
     NS_RUNTIMEABORT("Not reachable");
     return NULL;
 }
 
 bool
-PluginInstanceParent::AnswerPBrowserStreamDestructor(PBrowserStreamParent* stream,
-                                                     const NPError& reason,
-                                                     const bool& artificial)
-{
-    if (!artificial) {
-        static_cast<BrowserStreamParent*>(stream)->NPN_DestroyStream(reason);
-    }
-    return true;
-}
-
-bool
-PluginInstanceParent::DeallocPBrowserStream(PBrowserStreamParent* stream,
-                                            const NPError& reason,
-                                            const bool& artificial)
+PluginInstanceParent::DeallocPBrowserStream(PBrowserStreamParent* stream)
 {
     delete stream;
     return true;
 }
 
 PPluginStreamParent*
 PluginInstanceParent::AllocPPluginStream(const nsCString& mimeType,
                                          const nsCString& target,
                                          NPError* result)
 {
     return new PluginStreamParent(this, mimeType, target, result);
 }
 
 bool
-PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent* stream,
-                                           const NPError& reason,
-                                           const bool& artificial)
+PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent* stream)
 {
-    if (!artificial) {
-        static_cast<PluginStreamParent*>(stream)->NPN_DestroyStream(reason);
-    }
     delete stream;
     return true;
 }
 
 bool
 PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
                                                        bool* value,
                                                        NPError* result)
@@ -287,24 +289,23 @@ PluginInstanceParent::AnswerPStreamNotif
                                            NullableStringGet(url),
                                            NullableStringGet(target),
                                            buffer.Length(),
                                            NullableStringGet(buffer),
                                            file, actor);
     }
 
     if (*result != NPERR_NO_ERROR)
-        CallPStreamNotifyDestructor(actor, NPERR_GENERIC_ERROR);
+        PStreamNotifyParent::Call__delete__(actor, NPERR_GENERIC_ERROR);
 
     return true;
 }
 
 bool
-PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent* notifyData,
-                                           const NPReason& reason)
+PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent* notifyData)
 {
     delete notifyData;
     return true;
 }
 
 bool
 PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect& rect)
 {
@@ -314,23 +315,44 @@ PluginInstanceParent::RecvNPN_Invalidate
 
 NPError
 PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
 {
     _MOZ_LOG(__FUNCTION__);
     NS_ENSURE_TRUE(aWindow, NPERR_GENERIC_ERROR);
 
     NPRemoteWindow window;
+    mWindowType = aWindow->type;
+
+#if defined(OS_WIN)
+    // On windowless controls, reset the shared memory surface as needed.
+    if (mWindowType == NPWindowTypeDrawable) {
+        // SharedSurfaceSetWindow will take care of NPRemoteWindow.
+        if (!SharedSurfaceSetWindow(aWindow, window)) {
+          return NPERR_OUT_OF_MEMORY_ERROR;
+        }
+    }
+    else {
+        window.window = reinterpret_cast<unsigned long>(aWindow->window);
+        window.x = aWindow->x;
+        window.y = aWindow->y;
+        window.width = aWindow->width;
+        window.height = aWindow->height;
+        window.type = aWindow->type;
+    }
+#else
     window.window = reinterpret_cast<unsigned long>(aWindow->window);
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
-    window.clipRect = aWindow->clipRect;
+    window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
+#endif
+
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     const NPSetWindowCallbackStruct* ws_info =
       static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info);
     window.visualID = ws_info->visual ? ws_info->visual->visualid : None;
     window.colormap = ws_info->colormap;
 #endif
 
     NPError prv;
@@ -438,16 +460,31 @@ int16_t
 PluginInstanceParent::NPP_HandleEvent(void* event)
 {
     _MOZ_LOG(__FUNCTION__);
 
     NPEvent* npevent = reinterpret_cast<NPEvent*>(event);
     NPRemoteEvent npremoteevent;
     npremoteevent.event = *npevent;
 
+#if defined(OS_WIN)
+    RECT rect;
+    if (mWindowType == NPWindowTypeDrawable) {
+        if (mDoublePassEvent && mDoublePassEvent == npevent->event) {
+            // Sent from nsObjectFrame to let us know a double pass render is in progress.
+            mLocalCopyRender = PR_TRUE;
+            return true;
+        } else if (WM_PAINT == npevent->event) {
+            // Don't forward on the second pass, otherwise, fall through.
+            if (!SharedSurfaceBeforePaint(rect, npremoteevent))
+                return true;
+        }
+    }
+#endif
+
 #if defined(MOZ_X11)
     if (GraphicsExpose == npevent->type) {
         printf("  schlepping drawable 0x%lx across the pipe\n",
                npevent->xgraphicsexpose.drawable);
         // Make sure the X server has created the Drawable and completes any
         // drawing before the plugin draws on top.
         //
         // XSync() waits for the X server to complete.  Really this parent
@@ -459,16 +496,22 @@ PluginInstanceParent::NPP_HandleEvent(vo
 #  endif
     }
 #endif
 
     int16_t handled;
     if (!CallNPP_HandleEvent(npremoteevent, &handled)) {
         return 0;               // no good way to handle errors here...
     }
+
+#if defined(OS_WIN)
+    if (handled && mWindowType == NPWindowTypeDrawable && WM_PAINT == npevent->event)
+        SharedSurfaceAfterPaint(npevent);
+#endif
+
     return handled;
 }
 
 NPError
 PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
                                     NPBool seekable, uint16_t* stype)
 {
     _MOZ_LOG(__FUNCTION__);
@@ -482,43 +525,43 @@ PluginInstanceParent::NPP_NewStream(NPMI
                                        stream->lastmodified,
                                        static_cast<PStreamNotifyParent*>(stream->notifyData),
                                        NullableString(stream->headers),
                                        NullableString(type), seekable,
                                        &err, stype))
         return NPERR_GENERIC_ERROR;
 
     if (NPERR_NO_ERROR != err)
-        CallPBrowserStreamDestructor(bs, NPERR_GENERIC_ERROR, true);
+        PBrowserStreamParent::Call__delete__(bs, NPERR_GENERIC_ERROR, true);
 
     return err;
 }
 
 NPError
 PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
 {
     _MOZ_LOG(__FUNCTION__);
 
     AStream* s = static_cast<AStream*>(stream->pdata);
     if (s->IsBrowserStream()) {
         BrowserStreamParent* sp =
             static_cast<BrowserStreamParent*>(s);
         if (sp->mNPP != this)
             NS_RUNTIMEABORT("Mismatched plugin data");
 
-        CallPBrowserStreamDestructor(sp, reason, false);
+        PBrowserStreamParent::Call__delete__(sp, reason, false);
         return NPERR_NO_ERROR;
     }
     else {
         PluginStreamParent* sp =
             static_cast<PluginStreamParent*>(s);
         if (sp->mInstance != this)
             NS_RUNTIMEABORT("Mismatched plugin data");
 
-        CallPPluginStreamDestructor(sp, reason, false);
+        PPluginStreamParent::Call__delete__(sp, reason, false);
         return NPERR_NO_ERROR;
     }
 }
 
 PPluginScriptableObjectParent*
 PluginInstanceParent::AllocPPluginScriptableObject()
 {
     nsAutoPtr<PluginScriptableObjectParent>* object =
@@ -580,17 +623,17 @@ PluginInstanceParent::AnswerPPluginScrip
 void
 PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason,
                                     void* notifyData)
 {
     _MOZ_LOG(__FUNCTION__);
 
     PStreamNotifyParent* streamNotify =
         static_cast<PStreamNotifyParent*>(notifyData);
-    CallPStreamNotifyDestructor(streamNotify, reason);
+    PStreamNotifyParent::Call__delete__(streamNotify, reason);
 }
 
 PluginScriptableObjectParent*
 PluginInstanceParent::GetActorForNPObject(NPObject* aObject)
 {
     NS_ASSERTION(aObject, "Null pointer!");
 
     if (aObject->_class == PluginScriptableObjectParent::GetClass()) {
@@ -627,8 +670,131 @@ PluginInstanceParent::AnswerNPN_PushPopu
 }
 
 bool
 PluginInstanceParent::AnswerNPN_PopPopupsEnabledState(bool* aSuccess)
 {
     *aSuccess = mNPNIface->poppopupsenabledstate(mNPP);
     return true;
 }
+
+#if defined(OS_WIN)
+
+/* windowless drawing helpers */
+
+void
+PluginInstanceParent::SharedSurfaceRelease()
+{
+    mSharedSurfaceDib.Close();
+}
+
+bool
+PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
+                                             NPRemoteWindow& aRemoteWindow)
+{
+    aRemoteWindow.window = nsnull;
+    aRemoteWindow.x      = 0;
+    aRemoteWindow.y      = 0;
+    aRemoteWindow.width  = aWindow->width;
+    aRemoteWindow.height = aWindow->height;
+    aRemoteWindow.type   = aWindow->type;
+
+    nsIntRect newPort(aWindow->x, aWindow->y, aWindow->width, aWindow->height);
+
+    // save the the rect location within the browser window.
+    mPluginPort = newPort;
+
+    // move the port to our shared surface origin
+    newPort.MoveTo(0,0);
+
+    // check to see if we have the room in shared surface
+    if (mSharedSurfaceDib.IsValid() && mSharedSize.Contains(newPort)) {
+      // ok to paint
+      aRemoteWindow.surfaceHandle = 0;
+      return true;
+    }
+    
+    // allocate a new shared surface
+    SharedSurfaceRelease();
+    if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast<HDC>(aWindow->window),
+                                           newPort.width, newPort.height, 32)))
+      return false;
+
+    // save the new shared surface size we just allocated
+    mSharedSize = newPort;
+    
+    base::SharedMemoryHandle handle;
+    if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle)))
+      return false;
+
+    aRemoteWindow.surfaceHandle = handle;
+    
+    return true;
+}
+
+bool
+PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect,
+                                               NPRemoteEvent& npremoteevent)
+{
+    RECT* dr = (RECT*)npremoteevent.event.lParam;
+    HDC parentHdc = (HDC)npremoteevent.event.wParam;
+
+    // We render twice per frame for windowless plugins that sit in transparent
+    // frames. (See nsObjectFrame and gfxWindowsNativeDrawing for details.) IPC
+    // message delays in OOP plugin painting can result in two passes yeilding
+    // different animation frames. The second rendering doesn't need to go over
+    // the wire (we already have a copy of the frame in mSharedSurfaceDib) so we
+    // skip off requesting the second. This also gives us a nice perf boost.
+    if (mLocalCopyRender) {
+      mLocalCopyRender = false;
+      // Reuse the old render.
+      SharedSurfaceAfterPaint(&npremoteevent.event);
+      return false;
+    }
+
+    nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top);
+    dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); // should always be smaller than dirtyRect
+
+    ::BitBlt(mSharedSurfaceDib.GetHDC(),
+             dirtyRect.x,
+             dirtyRect.y,
+             dirtyRect.width,
+             dirtyRect.height,
+             parentHdc,
+             dr->left,
+             dr->top,
+             SRCCOPY);
+
+    // setup the translated dirty rect we'll send to the child
+    rect.left   = dirtyRect.x;
+    rect.top    = dirtyRect.y;
+    rect.right  = dirtyRect.width;
+    rect.bottom = dirtyRect.height;
+
+    npremoteevent.event.wParam = WPARAM(0);
+    npremoteevent.event.lParam = LPARAM(&rect);
+
+    // Send the event to the plugin
+    return true;
+}
+
+void
+PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent)
+{
+    RECT* dr = (RECT*)npevent->lParam;
+    HDC parentHdc = (HDC)npevent->wParam;
+
+    nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top);
+    dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y);
+
+    // src copy the shared dib into the parent surface we are handed.
+    ::BitBlt(parentHdc,
+             dr->left,
+             dr->top,
+             dirtyRect.width,
+             dirtyRect.height,
+             mSharedSurfaceDib.GetHDC(),
+             dirtyRect.x,
+             dirtyRect.y,
+             SRCCOPY);
+}
+
+#endif // defined(OS_WIN)
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -36,29 +36,32 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef dom_plugins_PluginInstanceParent_h
 #define dom_plugins_PluginInstanceParent_h 1
 
 #include "mozilla/plugins/PPluginInstanceParent.h"
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
+#if defined(OS_WIN)
+#include "mozilla/gfx/SharedDIBWin.h"
+#endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
+#include "nsRect.h"
 
 #undef _MOZ_LOG
 #define _MOZ_LOG(s) printf("[PluginInstanceParent] %s\n", s)
 
 namespace mozilla {
 namespace plugins {
 
 class PBrowserStreamParent;
-class BrowserStreamParent;
 class PluginModuleParent;
 
 class PluginInstanceParent : public PPluginInstanceParent
 {
     friend class PluginModuleParent;
     friend class BrowserStreamParent;
     friend class PluginStreamParent;
 
@@ -84,36 +87,25 @@ public:
                         const uint32_t& length,
                         const uint32_t& lastmodified,
                         PStreamNotifyParent* notifyData,
                         const nsCString& headers,
                         const nsCString& mimeType,
                         const bool& seekable,
                         NPError* rv,
                         uint16_t *stype);
-
     virtual bool
-    AnswerPBrowserStreamDestructor(PBrowserStreamParent* stream,
-                                   const NPError& reason,
-                                   const bool& artificial);
-
-    virtual bool
-    DeallocPBrowserStream(PBrowserStreamParent* stream,
-                          const NPError& reason,
-                          const bool& artificial);
+    DeallocPBrowserStream(PBrowserStreamParent* stream);
 
     virtual PPluginStreamParent*
     AllocPPluginStream(const nsCString& mimeType,
                        const nsCString& target,
                        NPError* result);
-
     virtual bool
-    DeallocPPluginStream(PPluginStreamParent* stream,
-                         const NPError& reason,
-                         const bool& artificial);
+    DeallocPPluginStream(PPluginStreamParent* stream);
 
     virtual bool
     AnswerNPN_GetValue_NPNVjavascriptEnabledBool(bool* value, NPError* result);
     virtual bool
     AnswerNPN_GetValue_NPNVisOfflineBool(bool* value, NPError* result);
     virtual bool
     AnswerNPN_GetValue_NPNVWindowNPObject(
                                        PPluginScriptableObjectParent** value,
@@ -150,18 +142,17 @@ public:
     AnswerPStreamNotifyConstructor(PStreamNotifyParent* actor,
                                    const nsCString& url,
                                    const nsCString& target,
                                    const bool& post, const nsCString& buffer,
                                    const bool& file,
                                    NPError* result);
 
     virtual bool
-    DeallocPStreamNotify(PStreamNotifyParent* notifyData,
-                         const NPReason& reason);
+    DeallocPStreamNotify(PStreamNotifyParent* notifyData);
 
     virtual bool
     RecvNPN_InvalidateRect(const NPRect& rect);
 
     virtual bool
     AnswerNPN_PushPopupsEnabledState(const bool& aState,
                                      bool* aSuccess);
 
@@ -213,17 +204,34 @@ private:
     bool InternalGetValueForNPObject(NPNVariable aVariable,
                                      PPluginScriptableObjectParent** aValue,
                                      NPError* aResult);
 
 private:
     PluginModuleParent* mParent;
     NPP mNPP;
     const NPNetscapeFuncs* mNPNIface;
+    NPWindowType mWindowType;
 
     nsTArray<nsAutoPtr<PluginScriptableObjectParent> > mScriptableObjects;
+
+#if defined(OS_WIN)
+private:
+    // Used in rendering windowless plugins in other processes.
+    bool SharedSurfaceSetWindow(const NPWindow* aWindow, NPRemoteWindow& aRemoteWindow);
+    bool SharedSurfaceBeforePaint(RECT &rect, NPRemoteEvent& npremoteevent);
+    void SharedSurfaceAfterPaint(NPEvent* npevent);
+    void SharedSurfaceRelease();
+
+private:
+    gfx::SharedDIBWin  mSharedSurfaceDib;
+    nsIntRect          mPluginPort;
+    nsIntRect          mSharedSize;
+    PRUint32           mDoublePassEvent;
+    bool               mLocalCopyRender;
+#endif // defined(XP_WIN)
 };
 
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif // ifndef dom_plugins_PluginInstanceParent_h
--- a/dom/plugins/PluginMessageUtils.h
+++ b/dom/plugins/PluginMessageUtils.h
@@ -84,16 +84,19 @@ struct NPRemoteWindow
   uint32_t width;
   uint32_t height;
   NPRect clipRect;
   NPWindowType type;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
   VisualID visualID;
   Colormap colormap;
 #endif /* XP_UNIX */
+#if defined(XP_WIN)
+  base::SharedMemoryHandle surfaceHandle;
+#endif
 };
 
 // XXX maybe not the best place for these. better one?
 
 #define VARSTR(v_)  case v_: return #v_
 inline const char* const
 NPPVariableToString(NPPVariable aVar)
 {
@@ -273,16 +276,19 @@ struct ParamTraits<mozilla::plugins::NPR
     WriteParam(aMsg, aParam.width);
     WriteParam(aMsg, aParam.height);
     WriteParam(aMsg, aParam.clipRect);
     WriteParam(aMsg, aParam.type);
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     aMsg->WriteULong(aParam.visualID);
     aMsg->WriteULong(aParam.colormap);
 #endif
+#if defined(XP_WIN)
+    WriteParam(aMsg, aParam.surfaceHandle);
+#endif
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     unsigned long window;
     int32_t x, y;
     uint32_t width, height;
     NPRect clipRect;
@@ -299,27 +305,36 @@ struct ParamTraits<mozilla::plugins::NPR
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     unsigned long visualID;
     unsigned long colormap;
     if (!(aMsg->ReadULong(aIter, &visualID) &&
           aMsg->ReadULong(aIter, &colormap)))
       return false;
 #endif
 
+#if defined(XP_WIN)
+    base::SharedMemoryHandle surfaceHandle;
+    if (!ReadParam(aMsg, aIter, &surfaceHandle))
+      return false;
+#endif
+
     aResult->window = window;
     aResult->x = x;
     aResult->y = y;
     aResult->width = width;
     aResult->height = height;
     aResult->clipRect = clipRect;
     aResult->type = type;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     aResult->visualID = visualID;
     aResult->colormap = colormap;
 #endif
+#if defined(XP_WIN)
+    aResult->surfaceHandle = surfaceHandle;
+#endif
     return true;
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
     aLog->append(StringPrintf(L"[%u, %d, %d, %u, %u, %d",
                               (unsigned long)aParam.window,
                               aParam.x, aParam.y, aParam.width,
@@ -545,16 +560,36 @@ struct ParamTraits<mozilla::plugins::IPC
         ReadParam(aMsg, aIter, &p.length)) {
       *aResult = p;
       return true;
     }
     return false;
   }
 };
 
+template <>
+struct ParamTraits<NPNVariable>
+{
+  typedef NPNVariable paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, int(aParam));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    int intval;
+    if (ReadParam(aMsg, aIter, &intval)) {
+      *aResult = paramType(intval);
+      return true;
+    }
+    return false;
+  }
+};
 
 } /* namespace IPC */
 
 
 // Serializing NPEvents is completely platform-specific and can be rather
 // intricate depending on the platform.  So for readability we split it
 // into separate files and have the only macro crud live here.
 // 
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -44,22 +44,25 @@
 #endif
 
 #include "nsILocalFile.h"
 
 #include "pratom.h"
 #include "nsDebug.h"
 #include "nsCOMPtr.h"
 #include "nsPluginsDir.h"
+#include "nsXULAppAPI.h"
 
 #include "mozilla/plugins/PluginInstanceChild.h"
 #include "mozilla/plugins/StreamNotifyChild.h"
 #include "mozilla/plugins/BrowserStreamChild.h"
 #include "mozilla/plugins/PluginStreamChild.h"
 
+#include "nsNPAPIPlugin.h"
+
 using mozilla::ipc::NPRemoteIdentifier;
 
 using namespace mozilla::plugins;
 
 namespace {
 PluginModuleChild* gInstance = nsnull;
 }
 
@@ -187,23 +190,36 @@ PluginModuleChild::InitGraphics()
     return true;
 }
 
 bool
 PluginModuleChild::AnswerNP_Shutdown(NPError *rv)
 {
     AssertPluginThread();
 
-    // FIXME/cjones: should all instances be dead by now?
+    // the PluginModuleParent shuts down this process after this RPC
+    // call pops off its stack
 
     *rv = mShutdownFunc ? mShutdownFunc() : NPERR_NO_ERROR;
+
+    // weakly guard against re-entry after NP_Shutdown
+    memset(&mFunctions, 0, sizeof(mFunctions));
+
     return true;
 }
 
 void
+PluginModuleChild::ActorDestroy(ActorDestroyReason why)
+{
+    // doesn't matter why we're being destroyed; it's up to us to
+    // initiate (clean) shutdown
+    XRE_ShutdownChildProcess();
+}
+
+void
 PluginModuleChild::CleanUp()
 {
 }
 
 const char*
 PluginModuleChild::GetUserAgent()
 {
     if (!CallNPN_UserAgent(&mUserAgent))
@@ -283,21 +299,23 @@ PluginModuleChild::NPObjectIsRegisteredF
     mObjectMap.EnumerateRead(ActorSearch, &info);
     return info.found;
 }
 #endif
 
 //-----------------------------------------------------------------------------
 // FIXME/cjones: just getting this out of the way for the moment ...
 
+namespace mozilla {
+namespace plugins {
+namespace child {
+
 // FIXME
 typedef void (*PluginThreadCallback)(void*);
 
-PR_BEGIN_EXTERN_C
-
 static NPError NP_CALLBACK
 _requestread(NPStream *pstream, NPByteRange *rangeList);
 
 static NPError NP_CALLBACK
 _geturlnotify(NPP aNPP, const char* relativeURL, const char* target,
               void* notifyData);
 
 static NPError NP_CALLBACK
@@ -466,82 +484,88 @@ static void NP_CALLBACK
 static NPError NP_CALLBACK
 _popupcontextmenu(NPP instance, NPMenu* menu);
 
 static NPBool NP_CALLBACK
 _convertpoint(NPP instance, 
               double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
               double *destX, double *destY, NPCoordinateSpace destSpace);
 
-PR_END_EXTERN_C
+} /* namespace child */
+} /* namespace plugins */
+} /* namespace mozilla */
 
 const NPNetscapeFuncs PluginModuleChild::sBrowserFuncs = {
     sizeof(sBrowserFuncs),
     (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR,
-    _geturl,
-    _posturl,
-    _requestread,
-    _newstream,
-    _write,
-    _destroystream,
-    _status,
-    _useragent,
-    _memalloc,
-    _memfree,
-    _memflush,
-    _reloadplugins,
-    _getjavaenv,
-    _getjavapeer,
-    _geturlnotify,
-    _posturlnotify,
-    _getvalue,
-    _setvalue,
-    _invalidaterect,
-    _invalidateregion,
-    _forceredraw,
-    _getstringidentifier,
-    _getstringidentifiers,
-    _getintidentifier,
-    _identifierisstring,
-    _utf8fromidentifier,
-    _intfromidentifier,
-    _createobject,
-    _retainobject,
-    _releaseobject,
-    _invoke,
-    _invokedefault,
-    _evaluate,
-    _getproperty,
-    _setproperty,
-    _removeproperty,
-    _hasproperty,
-    _hasmethod,
-    _releasevariantvalue,
-    _setexception,
-    _pushpopupsenabledstate,
-    _poppopupsenabledstate,
-    _enumerate,
-    _pluginthreadasynccall,
-    _construct,
-    _getvalueforurl,
-    _setvalueforurl,
-    _getauthenticationinfo,
-    _scheduletimer,
-    _unscheduletimer,
-    _popupcontextmenu,
-    _convertpoint
+    mozilla::plugins::child::_geturl,
+    mozilla::plugins::child::_posturl,
+    mozilla::plugins::child::_requestread,
+    mozilla::plugins::child::_newstream,
+    mozilla::plugins::child::_write,
+    mozilla::plugins::child::_destroystream,
+    mozilla::plugins::child::_status,
+    mozilla::plugins::child::_useragent,
+    mozilla::plugins::child::_memalloc,
+    mozilla::plugins::child::_memfree,
+    mozilla::plugins::child::_memflush,
+    mozilla::plugins::child::_reloadplugins,
+    mozilla::plugins::child::_getjavaenv,
+    mozilla::plugins::child::_getjavapeer,
+    mozilla::plugins::child::_geturlnotify,
+    mozilla::plugins::child::_posturlnotify,
+    mozilla::plugins::child::_getvalue,
+    mozilla::plugins::child::_setvalue,
+    mozilla::plugins::child::_invalidaterect,
+    mozilla::plugins::child::_invalidateregion,
+    mozilla::plugins::child::_forceredraw,
+    mozilla::plugins::child::_getstringidentifier,
+    mozilla::plugins::child::_getstringidentifiers,
+    mozilla::plugins::child::_getintidentifier,
+    mozilla::plugins::child::_identifierisstring,
+    mozilla::plugins::child::_utf8fromidentifier,
+    mozilla::plugins::child::_intfromidentifier,
+    mozilla::plugins::child::_createobject,
+    mozilla::plugins::child::_retainobject,
+    mozilla::plugins::child::_releaseobject,
+    mozilla::plugins::child::_invoke,
+    mozilla::plugins::child::_invokedefault,
+    mozilla::plugins::child::_evaluate,
+    mozilla::plugins::child::_getproperty,
+    mozilla::plugins::child::_setproperty,
+    mozilla::plugins::child::_removeproperty,
+    mozilla::plugins::child::_hasproperty,
+    mozilla::plugins::child::_hasmethod,
+    mozilla::plugins::child::_releasevariantvalue,
+    mozilla::plugins::child::_setexception,
+    mozilla::plugins::child::_pushpopupsenabledstate,
+    mozilla::plugins::child::_poppopupsenabledstate,
+    mozilla::plugins::child::_enumerate,
+    mozilla::plugins::child::_pluginthreadasynccall,
+    mozilla::plugins::child::_construct,
+    mozilla::plugins::child::_getvalueforurl,
+    mozilla::plugins::child::_setvalueforurl,
+    mozilla::plugins::child::_getauthenticationinfo,
+    mozilla::plugins::child::_scheduletimer,
+    mozilla::plugins::child::_unscheduletimer,
+    mozilla::plugins::child::_popupcontextmenu,
+    mozilla::plugins::child::_convertpoint
 };
 
 PluginInstanceChild*
 InstCast(NPP aNPP)
 {
     NS_ABORT_IF_FALSE(!!(aNPP->ndata), "nil instance");
     return static_cast<PluginInstanceChild*>(aNPP->ndata);
 }
 
+namespace mozilla {
+namespace plugins {
+namespace child {
+
 NPError NP_CALLBACK
 _requestread(NPStream* aStream,
              NPByteRange* aRangeList)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
 
     BrowserStreamChild* bs =
@@ -577,20 +601,46 @@ NPError NP_CALLBACK
 
 NPError NP_CALLBACK
 _getvalue(NPP aNPP,
           NPNVariable aVariable,
           void* aValue)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
-    return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
+
+    switch (aVariable) {
+        case NPNVjavascriptEnabledBool: // Intentional fall-through
+        case NPNVasdEnabledBool: // Intentional fall-through
+        case NPNVisOfflineBool: // Intentional fall-through
+        case NPNVSupportsXEmbedBool: // Intentional fall-through
+        case NPNVSupportsWindowless: // Intentional fall-through
+        case NPNVprivateModeBool: {
+            NPError result;
+            bool value;
+            PluginModuleChild::current()->
+                CallNPN_GetValue_WithBoolReturn(aVariable, &result, &value);
+            *(NPBool*)aValue = value ? true : false;
+            return result;
+        }
+
+        default: {
+            if (aNPP) {
+                return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
+            }
+
+            NS_WARNING("Null NPP!");
+            return NPERR_INVALID_INSTANCE_ERROR;
+        }
+    }
+
+    NS_NOTREACHED("Shouldn't get here!");
+    return NPERR_GENERIC_ERROR;
 }
 
-
 NPError NP_CALLBACK
 _setvalue(NPP aNPP,
           NPPVariable aVariable,
           void* aValue)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
     return InstCast(aNPP)->NPN_SetValue(aVariable, aValue);
@@ -697,22 +747,22 @@ NPError NP_CALLBACK
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
 
     PluginInstanceChild* p = InstCast(aNPP);
     AStream* s = static_cast<AStream*>(aStream->ndata);
     if (s->IsBrowserStream()) {
         BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s);
         bs->EnsureCorrectInstance(p);
-        p->CallPBrowserStreamDestructor(bs, aReason, false);
+        PBrowserStreamChild::Call__delete__(bs, aReason, false);
     }
     else {
         PluginStreamChild* ps = static_cast<PluginStreamChild*>(s);
         ps->EnsureCorrectInstance(p);
-        p->CallPPluginStreamDestructor(ps, aReason, false);
+        PPluginStreamChild::Call__delete__(ps, aReason, false);
     }
     return NPERR_NO_ERROR;
 }
 
 void NP_CALLBACK
 _status(NPP aNPP,
         const char* aMessage)
 {
@@ -1294,16 +1344,20 @@ NPBool NP_CALLBACK
               double *destX, double *destY, NPCoordinateSpace destSpace)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
     NS_NOTYETIMPLEMENTED("Implement me!");
     return 0;
 }
 
+} /* namespace child */
+} /* namespace plugins */
+} /* namespace mozilla */
+
 //-----------------------------------------------------------------------------
 
 bool
 PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
 
@@ -1397,33 +1451,31 @@ PluginModuleChild::AnswerPPluginInstance
         return false;
     }
 
     printf ("[PluginModuleChild] %s: returning %hd\n", __FUNCTION__, *rv);
     return true;
 }
 
 bool
-PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor,
-                                          NPError* rv)
+PluginModuleChild::DeallocPPluginInstance(PPluginInstanceChild* aActor)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
 
     delete aActor;
 
     return true;
 }
 
 bool
-PluginModuleChild::AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor,
-                                                   NPError* rv)
+PluginModuleChild::PluginInstanceDestroyed(PluginInstanceChild* aActor,
+                                           NPError* rv)
 {
     _MOZ_LOG(__FUNCTION__);
     AssertPluginThread();
 
-    PluginInstanceChild* inst = static_cast<PluginInstanceChild*>(aActor);
-    *rv = mFunctions.destroy(inst->GetNPP(), 0);
-    inst->Destroy();
-    inst->GetNPP()->ndata = 0;
+    *rv = mFunctions.destroy(aActor->GetNPP(), 0);
+    aActor->Destroy();
+    aActor->GetNPP()->ndata = 0;
 
     return true;
 }
--- a/dom/plugins/PluginModuleChild.h
+++ b/dom/plugins/PluginModuleChild.h
@@ -104,33 +104,31 @@ protected:
     virtual PPluginInstanceChild*
     AllocPPluginInstance(const nsCString& aMimeType,
                          const uint16_t& aMode,
                          const nsTArray<nsCString>& aNames,
                          const nsTArray<nsCString>& aValues,
                          NPError* rv);
 
     virtual bool
-    DeallocPPluginInstance(PPluginInstanceChild* aActor,
-                           NPError* rv);
-
-    virtual bool
-    AnswerPPluginInstanceDestructor(PPluginInstanceChild* aActor,
-                                    NPError* rv);
+    DeallocPPluginInstance(PPluginInstanceChild* aActor);
 
     virtual bool
     AnswerPPluginInstanceConstructor(PPluginInstanceChild* aActor,
                                      const nsCString& aMimeType,
                                      const uint16_t& aMode,
                                      const nsTArray<nsCString>& aNames,
                                      const nsTArray<nsCString>& aValues,
                                      NPError* rv);
     virtual bool
     AnswerNP_Shutdown(NPError *rv);
 
+    virtual void
+    ActorDestroy(ActorDestroyReason why);
+
 public:
     PluginModuleChild();
     virtual ~PluginModuleChild();
 
     bool Init(const std::string& aPluginFilename,
               base::ProcessHandle aParentProcessHandle,
               MessageLoop* aIOLoop,
               IPC::Channel* aChannel);
@@ -149,16 +147,20 @@ public:
     void UnregisterNPObject(NPObject* aObject);
 
     PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
 
 #ifdef DEBUG
     bool NPObjectIsRegisteredForActor(PluginScriptableObjectChild* aActor);
 #endif
 
+    bool
+    PluginInstanceDestroyed(PluginInstanceChild* aActor,
+                            NPError* rv);
+
 private:
     bool InitGraphics();
 
     std::string mPluginFilename;
     PRLibrary* mLibrary;
     nsCString mUserAgent;
 
     // we get this from the plugin
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -61,53 +61,76 @@ PluginModuleParent::LoadModule(const cha
     parent->Open(parent->mSubprocess->GetChannel(),
                  parent->mSubprocess->GetChildProcessHandle());
 
     return parent;
 }
 
 
 PluginModuleParent::PluginModuleParent(const char* aFilePath)
+    : mSubprocess(new PluginProcessParent(aFilePath))
+    , mShutdown(false)
+    , mNPNIface(NULL)
 {
-    mSubprocess = new PluginProcessParent(aFilePath);
     NS_ASSERTION(mSubprocess, "Out of memory!");
 
-#ifdef DEBUG
-    PRBool ok =
-#endif
-    mValidIdentifiers.Init();
-    NS_ASSERTION(ok, "Out of memory!");
+    if (!mValidIdentifiers.Init()) {
+        NS_ERROR("Out of memory");
+    }
 }
 
 PluginModuleParent::~PluginModuleParent()
 {
+    if (!mShutdown) {
+        NS_WARNING("Plugin host deleted the module without shutting down.");
+        NPError err;
+        NP_Shutdown(&err);
+    }
+    NS_ASSERTION(mShutdown, "NP_Shutdown didn't");
+
     if (mSubprocess) {
         mSubprocess->Delete();
         mSubprocess = nsnull;
     }
 }
 
+void
+PluginModuleParent::ActorDestroy(ActorDestroyReason why)
+{
+    switch (why) {
+    case AbnormalShutdown:
+        // TODObsmedberg: notify the plugin host to forget this plugin module
+        // and instantiate us again.
+        // FALL THROUGH
+
+    case NormalShutdown:
+        mShutdown = true;
+        break;
+
+    default:
+        NS_ERROR("Unexpected shutdown reason for toplevel actor.");
+    }
+}
+
 PPluginInstanceParent*
 PluginModuleParent::AllocPPluginInstance(const nsCString& aMimeType,
                                          const uint16_t& aMode,
                                          const nsTArray<nsCString>& aNames,
                                          const nsTArray<nsCString>& aValues,
                                          NPError* rv)
 {
     NS_ERROR("Not reachable!");
     return NULL;
 }
 
 bool
-PluginModuleParent::DeallocPPluginInstance(PPluginInstanceParent* aActor,
-                                           NPError* _retval)
+PluginModuleParent::DeallocPPluginInstance(PPluginInstanceParent* aActor)
 {
     _MOZ_LOG(__FUNCTION__);
     delete aActor;
-    *_retval = NPERR_NO_ERROR;
     return true;
 }
 
 void
 PluginModuleParent::SetPluginFuncs(NPPluginFuncs* aFuncs)
 {
     aFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
     aFuncs->javaClass = nsnull;
@@ -142,17 +165,17 @@ PluginModuleParent::NPP_Destroy(NPP inst
         static_cast<PluginInstanceParent*>(instance->pdata);
 
     if (!parentInstance)
         return NPERR_NO_ERROR;
 
     parentInstance->Destroy();
 
     NPError prv;
-    if (!parentInstance->Module()->CallPPluginInstanceDestructor(parentInstance, &prv)) {
+    if (!PPluginInstanceParent::Call__delete__(parentInstance, &prv)) {
         prv = NPERR_GENERIC_ERROR;
     }
     instance->pdata = nsnull;
 
     return prv;
 }
 
 bool
@@ -179,110 +202,152 @@ PluginModuleParent::GetValidNPIdentifier
     return 0;
 }
 
 NPError
 PluginModuleParent::NPP_NewStream(NPP instance, NPMIMEType type,
                                   NPStream* stream, NPBool seekable,
                                   uint16_t* stype)
 {
-    return InstCast(instance)->NPP_NewStream(type, stream, seekable,
-                                             stype);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NPERR_GENERIC_ERROR;
+
+    return i->NPP_NewStream(type, stream, seekable,
+                            stype);
 }
 
 NPError
 PluginModuleParent::NPP_SetWindow(NPP instance, NPWindow* window)
 {
-     return InstCast(instance)->NPP_SetWindow(window);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NPERR_GENERIC_ERROR;
+
+    return i->NPP_SetWindow(window);
 }
 
 NPError
 PluginModuleParent::NPP_DestroyStream(NPP instance,
                                       NPStream* stream,
                                       NPReason reason)
 {
-    return InstCast(instance)->NPP_DestroyStream(stream, reason);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NPERR_GENERIC_ERROR;
+
+    return i->NPP_DestroyStream(stream, reason);
 }
 
 int32_t
 PluginModuleParent::NPP_WriteReady(NPP instance,
                                    NPStream* stream)
 {
-    return StreamCast(instance, stream)->WriteReady();
+    BrowserStreamParent* s = StreamCast(instance, stream);
+    if (!s)
+        return -1;
+
+    return s->WriteReady();
 }
 
 int32_t
 PluginModuleParent::NPP_Write(NPP instance,
                               NPStream* stream,
                               int32_t offset,
                               int32_t len,
                               void* buffer)
 {
-    return StreamCast(instance, stream)->Write(offset, len, buffer);
+    BrowserStreamParent* s = StreamCast(instance, stream);
+    if (!s)
+        return -1;
+
+    return s->Write(offset, len, buffer);
 }
 
 void
 PluginModuleParent::NPP_StreamAsFile(NPP instance,
                                      NPStream* stream,
                                      const char* fname)
 {
-    StreamCast(instance, stream)->StreamAsFile(fname);
+    BrowserStreamParent* s = StreamCast(instance, stream);
+    if (!s)
+        return;
+
+    s->StreamAsFile(fname);
 }
 
 void
 PluginModuleParent::NPP_Print(NPP instance, NPPrint* platformPrint)
 {
-    InstCast(instance)->NPP_Print(platformPrint);
+    PluginInstanceParent* i = InstCast(instance);
+    if (i)
+        i->NPP_Print(platformPrint);
 }
 
 int16_t
 PluginModuleParent::NPP_HandleEvent(NPP instance, void* event)
 {
-    return InstCast(instance)->NPP_HandleEvent(event);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return false;
+
+    return i->NPP_HandleEvent(event);
 }
 
 void
 PluginModuleParent::NPP_URLNotify(NPP instance, const char* url,
                                   NPReason reason, void* notifyData)
 {
-    return InstCast(instance)->NPP_URLNotify(url, reason, notifyData);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return;
+
+    i->NPP_URLNotify(url, reason, notifyData);
 }
 
 NPError
 PluginModuleParent::NPP_GetValue(NPP instance,
                                  NPPVariable variable, void *ret_value)
 {
-    return InstCast(instance)->NPP_GetValue(variable, ret_value);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NPERR_GENERIC_ERROR;
+
+    return i->NPP_GetValue(variable, ret_value);
 }
 
 NPError
 PluginModuleParent::NPP_SetValue(NPP instance, NPNVariable variable,
                                  void *value)
 {
-    return InstCast(instance)->NPP_SetValue(variable, value);
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NPERR_GENERIC_ERROR;
+
+    return i->NPP_SetValue(variable, value);
 }
 
 bool
 PluginModuleParent::AnswerNPN_UserAgent(nsCString* userAgent)
 {
-    NPP_t dummy = { 0, 0 };
-    *userAgent = NullableString(mNPNIface->uagent(&dummy));
+    *userAgent = NullableString(mNPNIface->uagent(nsnull));
     return true;
 }
 
 bool
 PluginModuleParent::RecvNPN_GetStringIdentifier(const nsCString& aString,
                                                 NPRemoteIdentifier* aId)
 {
     if (aString.IsVoid()) {
         NS_ERROR("Someone sent over a void string?!");
         return false;
     }
 
-    NPIdentifier ident = _getstringidentifier(aString.BeginReading());
+    NPIdentifier ident =
+        mozilla::plugins::parent::_getstringidentifier(aString.BeginReading());
     if (!ident) {
         *aId = 0;
         return true;
     }
 
     if (!EnsureValidNPIdentifier(ident)) {
         NS_ERROR("Out of memory?");
         return false;
@@ -291,17 +356,17 @@ PluginModuleParent::RecvNPN_GetStringIde
     *aId = (NPRemoteIdentifier)ident;
     return true;
 }
 
 bool
 PluginModuleParent::RecvNPN_GetIntIdentifier(const int32_t& aInt,
                                              NPRemoteIdentifier* aId)
 {
-    NPIdentifier ident = _getintidentifier(aInt);
+    NPIdentifier ident = mozilla::plugins::parent::_getintidentifier(aInt);
     if (!ident) {
         *aId = 0;
         return true;
     }
 
     if (!EnsureValidNPIdentifier(ident)) {
         NS_ERROR("Out of memory?");
         return false;
@@ -317,17 +382,17 @@ PluginModuleParent::RecvNPN_UTF8FromIden
                                                nsCString* aString)
 {
     NPIdentifier ident = GetValidNPIdentifier(aId);
     if (!ident) {
         *err = NPERR_INVALID_PARAM;
         return true;
     }
 
-    NPUTF8* val = _utf8fromidentifier(ident);
+    NPUTF8* val = mozilla::plugins::parent::_utf8fromidentifier(ident);
     if (!val) {
         *err = NPERR_INVALID_PARAM;
         return true;
     }
 
     aString->Assign(val);
     *err = NPERR_NO_ERROR;
     return true;
@@ -339,32 +404,32 @@ PluginModuleParent::RecvNPN_IntFromIdent
                                               int32_t* aInt)
 {
     NPIdentifier ident = GetValidNPIdentifier(aId);
     if (!ident) {
         *err = NPERR_INVALID_PARAM;
         return true;
     }
 
-    *aInt = _intfromidentifier(ident);
+    *aInt = mozilla::plugins::parent::_intfromidentifier(ident);
     *err = NPERR_NO_ERROR;
     return true;
 }
 
 bool
 PluginModuleParent::RecvNPN_IdentifierIsString(const NPRemoteIdentifier& aId,
                                                bool* aIsString)
 {
     NPIdentifier ident = GetValidNPIdentifier(aId);
     if (!ident) {
         *aIsString = false;
         return true;
     }
 
-    *aIsString = _identifierisstring(ident);
+    *aIsString = mozilla::plugins::parent::_identifierisstring(ident);
     return true;
 }
 
 bool
 PluginModuleParent::RecvNPN_GetStringIdentifiers(const nsTArray<nsCString>& aNames,
                                                  nsTArray<NPRemoteIdentifier>* aIds)
 {
     NS_ASSERTION(aIds->IsEmpty(), "Non-empty array!");
@@ -385,18 +450,18 @@ PluginModuleParent::RecvNPN_GetStringIde
         return false;
     }
 
     for (PRUint32 index = 0; index < count; index++) {
         buffers[index] = const_cast<NPUTF8*>(aNames[index].BeginReading());
         NS_ASSERTION(buffers[index], "Null pointer should be impossible!");
     }
 
-    _getstringidentifiers(const_cast<const NPUTF8**>(buffers.Elements()),
-                          count, ids.Elements());
+    mozilla::plugins::parent::_getstringidentifiers(
+        const_cast<const NPUTF8**>(buffers.Elements()), count, ids.Elements());
 
     for (PRUint32 index = 0; index < count; index++) {
         NPIdentifier& id = ids[index];
         if (id) {
             if (!EnsureValidNPIdentifier(id)) {
                 NS_ERROR("Out of memory?");
                 return false;
             }
@@ -407,27 +472,36 @@ PluginModuleParent::RecvNPN_GetStringIde
     return true;
 }
 
 PluginInstanceParent*
 PluginModuleParent::InstCast(NPP instance)
 {
     PluginInstanceParent* ip =
         static_cast<PluginInstanceParent*>(instance->pdata);
+
+    // If the plugin crashed and the PluginInstanceParent was deleted,
+    // instance->pdata will be NULL.
+    if (!ip)
+        return NULL;
+
     if (instance != ip->mNPP) {
         NS_RUNTIMEABORT("Corrupted plugin data.");
     }
     return ip;
 }
 
 BrowserStreamParent*
 PluginModuleParent::StreamCast(NPP instance,
                                NPStream* s)
 {
     PluginInstanceParent* ip = InstCast(instance);
+    if (!ip)
+        return NULL;
+
     BrowserStreamParent* sp =
         static_cast<BrowserStreamParent*>(static_cast<AStream*>(s->pdata));
     if (sp->mNPP != ip || s != sp->mStream) {
         NS_RUNTIMEABORT("Corrupted plugin stream data.");
     }
     return sp;
 }
 
@@ -440,16 +514,21 @@ PluginModuleParent::HasRequiredFunctions
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
 nsresult
 PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error)
 {
     _MOZ_LOG(__FUNCTION__);
 
     mNPNIface = bFuncs;
 
+    if (mShutdown) {
+        *error = NPERR_GENERIC_ERROR;
+        return NS_ERROR_FAILURE;
+    }
+
     if (!CallNP_Initialize(error)) {
         return NS_ERROR_FAILURE;
     }
     else if (*error != NPERR_NO_ERROR) {
         return NS_OK;
     }
 
     SetPluginFuncs(pFuncs);
@@ -458,31 +537,44 @@ PluginModuleParent::NP_Initialize(NPNets
 #else
 nsresult
 PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
 {
     _MOZ_LOG(__FUNCTION__);
 
     mNPNIface = bFuncs;
 
+    if (mShutdown) {
+        *error = NPERR_GENERIC_ERROR;
+        return NS_ERROR_FAILURE;
+    }
+
     if (!CallNP_Initialize(error))
         return NS_ERROR_FAILURE;
 
     return NS_OK;
 }
 #endif
 
 nsresult
 PluginModuleParent::NP_Shutdown(NPError* error)
 {
     _MOZ_LOG(__FUNCTION__);
 
-    // FIXME/cjones: should all sub-actors be dead by now?
+    if (mShutdown) {
+        *error = NPERR_GENERIC_ERROR;
+        return NS_ERROR_FAILURE;
+    }
 
     bool ok = CallNP_Shutdown(error);
+
+    // if NP_Shutdown() is nested within another RPC call, this will
+    // break things.  but lord help us if we're doing that anyway; the
+    // plugin dso will have been unloaded on the other side by the
+    // CallNP_Shutdown() message
     Close();
 
     return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 PluginModuleParent::NP_GetMIMEDescription(char** mimeDesc)
 {
@@ -520,16 +612,21 @@ PluginModuleParent::NP_GetEntryPoints(NP
 nsresult
 PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
                             uint16_t mode, int16_t argc, char* argn[],
                             char* argv[], NPSavedData* saved,
                             NPError* error)
 {
     _MOZ_LOG(__FUNCTION__);
 
+    if (mShutdown) {
+        *error = NPERR_GENERIC_ERROR;
+        return NS_ERROR_FAILURE;
+    }
+
     // create the instance on the other side
     nsTArray<nsCString> names;
     nsTArray<nsCString> values;
 
     for (int i = 0; i < argc; ++i) {
         names.AppendElement(NullableString(argn[i]));
         values.AppendElement(NullableString(argv[i]));
     }
@@ -551,16 +648,26 @@ PluginModuleParent::NPP_New(NPMIMEType p
             *error = NPERR_GENERIC_ERROR;
         return NS_ERROR_FAILURE;
     }
 
     printf ("[PluginModuleParent] %s: got return value %hd\n", __FUNCTION__,
             *error);
 
     if (*error != NPERR_NO_ERROR) {
-        CallPPluginInstanceDestructor(parentInstance, error);
+        PPluginInstanceParent::Call__delete__(parentInstance, error);
         instance->pdata = nsnull;
         return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
 
+bool
+PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
+                                                      NPError* aError,
+                                                      bool* aBoolVal)
+{
+    NPBool boolVal = false;
+    *aError = mozilla::plugins::parent::_getvalue(nsnull, aVariable, &boolVal);
+    *aBoolVal = boolVal ? true : false;
+    return true;
+}
--- a/dom/plugins/PluginModuleParent.h
+++ b/dom/plugins/PluginModuleParent.h
@@ -61,16 +61,18 @@
 
 #undef _MOZ_LOG
 #define _MOZ_LOG(s) printf("[PluginModuleParent] %s\n", s)
 
 namespace mozilla {
 namespace plugins {
 //-----------------------------------------------------------------------------
 
+class BrowserStreamParent;
+
 /**
  * PluginModuleParent
  *
  * This class implements the NPP API from the perspective of the rest
  * of Gecko, forwarding NPP calls along to the child process that is
  * actually running the plugin.
  *
  * This class /also/ implements a version of the NPN API, because the
@@ -86,24 +88,25 @@ protected:
     PPluginInstanceParent*
     AllocPPluginInstance(const nsCString& aMimeType,
                          const uint16_t& aMode,
                          const nsTArray<nsCString>& aNames,
                          const nsTArray<nsCString>& aValues,
                          NPError* rv);
 
     virtual bool
-    DeallocPPluginInstance(PPluginInstanceParent* aActor,
-                           NPError* _retval);
+    DeallocPPluginInstance(PPluginInstanceParent* aActor);
 
 public:
     PluginModuleParent(const char* aFilePath);
 
     virtual ~PluginModuleParent();
 
+    NS_OVERRIDE virtual void ActorDestroy(ActorDestroyReason why);
+
     /**
      * LoadModule
      *
      * This may or may not launch a plugin child process,
      * and may or may not be very expensive.
      */
     static PluginLibrary* LoadModule(const char* aFilePath);
 
@@ -127,25 +130,31 @@ public:
                               int32_t* aInt);
     virtual bool
     RecvNPN_IdentifierIsString(const NPRemoteIdentifier& aId,
                                bool* aIsString);
     virtual bool
     RecvNPN_GetStringIdentifiers(const nsTArray<nsCString>& aNames,
                                  nsTArray<NPRemoteIdentifier>* aIds);
 
+    virtual bool
+    AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
+                                      NPError* aError,
+                                      bool* aBoolVal);
+
     const NPNetscapeFuncs* GetNetscapeFuncs() {
         return mNPNIface;
     }
 
     static PluginInstanceParent* InstCast(NPP instance);
     static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
 
     bool EnsureValidNPIdentifier(NPIdentifier aIdentifier);
 
+    base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
 private:
     void SetPluginFuncs(NPPluginFuncs* aFuncs);
 
     // Implement the module-level functions from NPAPI; these are
     // normally resolved directly from the DSO.
 #ifdef OS_LINUX
     NPError NP_Initialize(const NPNetscapeFuncs* npnIface,
                           NPPluginFuncs* nppIface);
@@ -196,16 +205,17 @@ private:
     virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error);
 #endif
     virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance,
                              uint16_t mode, int16_t argc, char* argn[],
                              char* argv[], NPSavedData* saved,
                              NPError* error);
 private:
     PluginProcessParent* mSubprocess;
+    bool mShutdown;
     const NPNetscapeFuncs* mNPNIface;
     nsTHashtable<nsVoidPtrHashKey> mValidIdentifiers;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif  // ifndef dom_plugins_PluginModuleParent_h
--- a/dom/plugins/PluginScriptableObjectChild.cpp
+++ b/dom/plugins/PluginScriptableObjectChild.cpp
@@ -211,17 +211,17 @@ PluginScriptableObjectChild::ScriptableI
 
   if (actor && !actor->CallInvalidate()) {
     NS_WARNING("Failed to send message!");
   }
 
   object->invalidated = true;
 
   if (instance &&
-      !instance->CallPPluginScriptableObjectDestructor(object->parent)) {
+      !PPluginScriptableObjectChild::Call__delete__(object->parent)) {
     NS_WARNING("Failed to send message!");
   }
 }
 
 // static
 void
 PluginScriptableObjectChild::ScriptableDeallocate(NPObject* aObject)
 {
@@ -646,17 +646,21 @@ PluginScriptableObjectChild::~PluginScri
   if (mObject) {
     if (mObject->_class == GetClass()) {
       if (!static_cast<ChildNPObject*>(mObject)->invalidated) {
         NS_WARNING("This should have happened already!");
         ScriptableInvalidate(mObject);
       }
     }
     else {
-      PluginModuleChild::sBrowserFuncs.releaseobject(mObject);
+      // Make sure we've invalidated our NPObject so that the plugin doesn't
+      // hold an object with a dangling pointer.
+
+      // Calling a virtual in the destructor, make sure we call the right one.
+      PluginScriptableObjectChild::AnswerInvalidate();
     }
   }
   NS_ASSERTION(!PluginModuleChild::current()->
                NPObjectIsRegisteredForActor(this),
                "NPObjects still registered for this actor!");
 }
 
 void
--- a/dom/plugins/PluginScriptableObjectParent.cpp
+++ b/dom/plugins/PluginScriptableObjectParent.cpp
@@ -51,17 +51,17 @@ namespace {
 
 inline PluginInstanceParent*
 GetInstance(NPObject* aObject)
 {
   NS_ASSERTION(aObject->_class == PluginScriptableObjectParent::GetClass(),
                "Bad class!");
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return nsnull;
   }
   return object->parent->GetInstance();
 }
 
 inline const NPNetscapeFuncs*
 GetNetscapeFuncs(PluginInstanceParent* aInstance)
@@ -265,88 +265,82 @@ PluginScriptableObjectParent::Scriptable
   NS_ASSERTION(instance, "This should never be null!");
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_WARNING("Can't allocate!");
     return nsnull;
   }
 
-  ParentNPObject* object =
-    reinterpret_cast<ParentNPObject*>(npn->memalloc(sizeof(ParentNPObject)));
-  if (object) {
-    memset(object, 0, sizeof(ParentNPObject));
-  }
-  return object;
+  return new ParentNPObject();
 }
 
 // static
 void
 PluginScriptableObjectParent::ScriptableInvalidate(NPObject* aObject)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     // This can happen more than once, and is just fine.
     return;
   }
 
   PluginScriptableObjectParent* actor = object->parent;
-  NS_ASSERTION(actor, "Null actor?!");
+
+  object->parent = NULL;
 
   PluginInstanceParent* instance = actor->GetInstance();
   NS_WARN_IF_FALSE(instance, "No instance?!");
 
   if (!actor->CallInvalidate()) {
     NS_WARNING("Failed to send message!");
   }
 
-  object->invalidated = true;
-
   if (instance &&
-      !instance->CallPPluginScriptableObjectDestructor(actor)) {
+      !PPluginScriptableObjectParent::Call__delete__(actor)) {
     NS_WARNING("Failed to send message!");
   }
 }
 
 // static
 void
 PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (!object->invalidated) {
+  if (object->parent) {
     ScriptableInvalidate(aObject);
   }
 
-  NS_ASSERTION(object->invalidated, "Should be invalidated!");
+  NS_ASSERTION(!object->parent, "Should be invalidated!");
 
-  NS_Free(aObject);
+  delete object;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableHasMethod(NPObject* aObject,
                                                   NPIdentifier aName)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
@@ -371,17 +365,17 @@ PluginScriptableObjectParent::Scriptable
                                                NPVariant* aResult)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
@@ -429,17 +423,17 @@ PluginScriptableObjectParent::Scriptable
                                                       NPVariant* aResult)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   PluginScriptableObjectParent* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   nsAutoTArray<Variant, 10> args;
@@ -480,17 +474,17 @@ PluginScriptableObjectParent::Scriptable
                                                     NPIdentifier aName)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
@@ -513,17 +507,17 @@ PluginScriptableObjectParent::Scriptable
                                                     NPVariant* aResult)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
@@ -556,17 +550,17 @@ PluginScriptableObjectParent::Scriptable
                                                     const NPVariant* aValue)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
@@ -594,17 +588,17 @@ PluginScriptableObjectParent::Scriptable
                                                        NPIdentifier aName)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   if (!EnsureValidIdentifier(aObject, aName)) {
     return false;
   }
 
@@ -627,17 +621,17 @@ PluginScriptableObjectParent::Scriptable
                                                   uint32_t* aCount)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   PluginScriptableObjectParent* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject);
@@ -687,17 +681,17 @@ PluginScriptableObjectParent::Scriptable
                                                   NPVariant* aResult)
 {
   if (aObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
-  if (object->invalidated) {
+  if (!object->parent) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   PluginScriptableObjectParent* actor = object->parent;
   NS_ASSERTION(actor, "This shouldn't ever be null!");
 
   nsAutoTArray<Variant, 10> args;
@@ -752,20 +746,18 @@ PluginScriptableObjectParent::PluginScri
 : mInstance(nsnull),
   mObject(nsnull)
 {
 }
 
 PluginScriptableObjectParent::~PluginScriptableObjectParent()
 {
   if (mObject) {
-    if (mObject->_class == GetClass()) {
-      if (!static_cast<ParentNPObject*>(mObject)->invalidated) {
-        ScriptableInvalidate(mObject);
-      }
+    if (GetClass() == mObject->_class) {
+      static_cast<ParentNPObject*>(mObject)->parent = NULL;
     }
     else {
       mInstance->GetNPNIface()->releaseobject(mObject);
     }
   }
 }
 
 void
--- a/dom/plugins/PluginScriptableObjectParent.h
+++ b/dom/plugins/PluginScriptableObjectParent.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=4 ts=4 et :
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (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.mozilla.org/MPL/
@@ -47,18 +47,20 @@
 namespace mozilla {
 namespace plugins {
 
 class PluginInstanceParent;
 class PluginScriptableObjectParent;
 
 struct ParentNPObject : NPObject
 {
+  ParentNPObject()
+    : parent(NULL) { }
+
   PluginScriptableObjectParent* parent;
-  bool invalidated;
 };
 
 class PluginScriptableObjectParent : public PPluginScriptableObjectParent
 {
   friend class PluginInstanceParent;
 
 public:
   PluginScriptableObjectParent();
--- a/dom/plugins/PluginStreamChild.cpp
+++ b/dom/plugins/PluginStreamChild.cpp
@@ -36,43 +36,60 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "PluginStreamChild.h"
 #include "mozilla/plugins/PluginInstanceChild.h"
 
 namespace mozilla {
 namespace plugins {
 
-PluginStreamChild::PluginStreamChild(PluginInstanceChild* instance)
-  : mInstance(instance)
+PluginStreamChild::PluginStreamChild()
 {
   memset(&mStream, 0, sizeof(mStream));
   mStream.ndata = static_cast<AStream*>(this);
 }
 
+bool
+PluginStreamChild::Answer__delete__(const NPReason& reason,
+                                    const bool& artificial)
+{
+  AssertPluginThread();
+  if (!artificial)
+    NPP_DestroyStream(reason);
+  return true;
+}
+
 int32_t
 PluginStreamChild::NPN_Write(int32_t length, void* buffer)
 {
   AssertPluginThread();
 
   int32_t written = 0;
   CallNPN_Write(nsCString(static_cast<char*>(buffer), length),
                 &written);
   if (written < 0)
-    mInstance->CallPPluginStreamDestructor(this, NPERR_GENERIC_ERROR, true);
+    PPluginStreamChild::Call__delete__(this, NPERR_GENERIC_ERROR, true);
+  // careful after here! |this| just got deleted 
 
   return written;
 }
 
 void
 PluginStreamChild::NPP_DestroyStream(NPError reason)
 {
   AssertPluginThread();
 
   if (mClosed)
     return;
 
   mClosed = true;
-  mInstance->mPluginIface->destroystream(&mInstance->mData, &mStream, reason);
+  Instance()->mPluginIface->destroystream(
+    &Instance()->mData, &mStream, reason);
+}
+
+PluginInstanceChild*
+PluginStreamChild::Instance()
+{
+  return static_cast<PluginInstanceChild*>(Manager());
 }
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/PluginStreamChild.h
+++ b/dom/plugins/PluginStreamChild.h
@@ -46,37 +46,41 @@ namespace plugins {
 
 class PluginInstanceChild;
 
 class PluginStreamChild : public PPluginStreamChild, public AStream
 {
   friend class PluginInstanceChild;
 
 public:
-  PluginStreamChild(PluginInstanceChild* instance);
+  PluginStreamChild();
   virtual ~PluginStreamChild() { }
 
   NS_OVERRIDE virtual bool IsBrowserStream() { return false; }
 
+  virtual bool Answer__delete__(const NPReason& reason,
+                                const bool& artificial);
+
   int32_t NPN_Write(int32_t length, void* buffer);
   void NPP_DestroyStream(NPError reason);
 
   void EnsureCorrectInstance(PluginInstanceChild* i)
   {
-    if (i != mInstance)
+    if (i != Instance())
       NS_RUNTIMEABORT("Incorrect stream instance");
   }
   void EnsureCorrectStream(NPStream* s)
   {
     if (s != &mStream)
       NS_RUNTIMEABORT("Incorrect stream data");
   }
 
 private:
-  PluginInstanceChild* mInstance;
+  PluginInstanceChild* Instance();
+
   NPStream mStream;
   bool mClosed;
 };
 
 
 } // namespace plugins
 } // namespace mozilla
 
--- a/dom/plugins/PluginStreamParent.cpp
+++ b/dom/plugins/PluginStreamParent.cpp
@@ -70,16 +70,25 @@ PluginStreamParent::AnswerNPN_Write(cons
                                          data.Length(),
                                          const_cast<char*>(data.get()));
   if (*written < 0)
     mClosed = true;
 
   return true;
 }
 
+bool
+PluginStreamParent::Answer__delete__(const NPError& reason,
+                                     const bool& artificial)
+{
+  if (!artificial)
+    this->NPN_DestroyStream(reason);
+  return true;
+}
+
 void
 PluginStreamParent::NPN_DestroyStream(NPReason reason)
 {
   if (mClosed)
     return;
 
   mInstance->mNPNIface->destroystream(mInstance->mNPP, mStream, reason);
   mClosed = true;
--- a/dom/plugins/PluginStreamParent.h
+++ b/dom/plugins/PluginStreamParent.h
@@ -55,19 +55,21 @@ public:
   PluginStreamParent(PluginInstanceParent* npp, const nsCString& mimeType,
                      const nsCString& target, NPError* result);
   virtual ~PluginStreamParent() { }
 
   NS_OVERRIDE virtual bool IsBrowserStream() { return false; }
 
   virtual bool AnswerNPN_Write(const Buffer& data, int32_t* written);
 
+  virtual bool Answer__delete__(const NPError& reason, const bool& artificial);
+
+private:
   void NPN_DestroyStream(NPReason reason);
 
-private:
   PluginInstanceParent* mInstance;
   NPStream* mStream;
   bool mClosed;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
--- a/dom/plugins/StreamNotifyChild.h
+++ b/dom/plugins/StreamNotifyChild.h
@@ -54,16 +54,18 @@ public:
     : mURL(aURL)
     , mClosure(NULL)
   { }
 
   void SetValid(void* aClosure) {
     mClosure = aClosure;
   }
 
+  bool Answer__delete__(const NPReason& reason);
+
 private:
   nsCString mURL;
   void* mClosure;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -1916,17 +1916,24 @@ nsWindowWatcher::SizeOpenedDocShellItem(
     // Some embedding clients don't support nsIDocShellTreeOwner's
     // GetMainWidget, so try going through nsIBaseWindow's GetParentWidget
     nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(aDocShellItem));
     if (shellWindow)
       shellWindow->GetParentWidget(getter_AddRefs(mainWidget));
   }
   if (mainWidget) {
     nsCOMPtr<nsIDeviceContext> ctx = mainWidget->GetDeviceContext();
-    devPixelsPerCSSPixel = float(ctx->AppUnitsPerCSSPixel()) / ctx->AppUnitsPerDevPixel();
+    /* we might be called by an extension after mainWidget::OnDestroy() */
+    if (ctx) {
+      PRInt32 unitsPerDevPixel = ctx->AppUnitsPerDevPixel();
+      if (unitsPerDevPixel) {
+        devPixelsPerCSSPixel = float(ctx->AppUnitsPerCSSPixel()) /
+                                     unitsPerDevPixel;
+      }
+    }
   }
 
   /* The current position and size will be unchanged if not specified
      (and they fit entirely onscreen). Also, calculate the difference
      between chrome and content sizes on aDocShellItem's window.
      This latter point becomes important if chrome and content
      specifications are mixed in aFeatures, and when bringing the window
      back from too far off the right or bottom edges of the screen. */
--- a/extensions/auth/nsAuthSSPI.cpp
+++ b/extensions/auth/nsAuthSSPI.cpp
@@ -265,28 +265,26 @@ nsAuthSSPI::Init(const char *serviceName
 
     SEC_WINNT_AUTH_IDENTITY_W ai;
     SEC_WINNT_AUTH_IDENTITY_W *pai = nsnull;
     
     // domain, username, and password will be null if nsHttpNTLMAuth's ChallengeReceived
     // returns false for identityInvalid. Use default credentials in this case by passing
     // null for pai.
     if (username && password) {
-        if (domain) {
-            ai.Domain = const_cast<unsigned short*>(domain);
-            ai.DomainLength = wcslen(domain);
-        }
-        else {
-            ai.Domain = NULL;
-            ai.DomainLength = 0;
-        }
-        ai.User = const_cast<unsigned short*>(username);
-        ai.UserLength = wcslen(username);
-        ai.Password = const_cast<unsigned short*>(password);
-        ai.PasswordLength = wcslen(password);
+        // Keep a copy of these strings for the duration
+        mUsername.Assign(username);
+        mPassword.Assign(password);
+        mDomain.Assign(domain);
+        ai.Domain = reinterpret_cast<unsigned short*>(mDomain.BeginWriting());
+        ai.DomainLength = mDomain.Length();
+        ai.User = reinterpret_cast<unsigned short*>(mUsername.BeginWriting());
+        ai.UserLength = mUsername.Length();
+        ai.Password = reinterpret_cast<unsigned short*>(mPassword.BeginWriting());
+        ai.PasswordLength = mPassword.Length();
         ai.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
         pai = &ai;
     }
 
     rc = (sspi->AcquireCredentialsHandleW)(NULL,
                                            package,
                                            SECPKG_CRED_OUTBOUND,
                                            NULL,
--- a/extensions/auth/nsAuthSSPI.h
+++ b/extensions/auth/nsAuthSSPI.h
@@ -73,11 +73,14 @@ private:
 
 private:
     CredHandle   mCred;
     CtxtHandle   mCtxt;
     nsCString    mServiceName;
     PRUint32     mServiceFlags;
     PRUint32     mMaxTokenLen;
     pType        mPackage;
+    nsString     mDomain;
+    nsString     mUsername;
+    nsString     mPassword;
 };
 
 #endif /* nsAuthSSPI_h__ */
--- a/gfx/Makefile.in
+++ b/gfx/Makefile.in
@@ -45,15 +45,19 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= gfx
 
 ifdef MOZ_TREE_CAIRO
 DIRS		= cairo
 endif
 
 DIRS		+= thebes public idl src qcms
 
+ifdef MOZ_IPC
+DIRS		+= ipc
+endif
+
 ifdef ENABLE_TESTS
 ifndef MOZ_ENABLE_LIBXUL
 TOOL_DIRS	+= tests
 endif
 endif
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/Makefile.in
@@ -0,0 +1,73 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH       = ../..
+topsrcdir   = @top_srcdir@
+srcdir      = @srcdir@
+VPATH       = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+ifdef MOZ_IPC
+
+MODULE             = gfxipc
+LIBRARY_NAME       = gfxipc_s
+FORCE_STATIC_LIB   = 1
+LIBXUL_LIBRARY     = 1
+EXPORT_LIBRARY     = 1
+
+EXPORTS_NAMESPACES = mozilla/gfx
+
+EXPORTS_mozilla/gfx = \
+        SharedDIB.h   \
+        $(NULL)
+
+CPPSRCS = SharedDIB.cpp
+
+ENABLE_CXX_EXCEPTIONS	= 1
+
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+CPPSRCS += SharedDIBWin.cpp
+EXPORTS_mozilla/gfx += SharedDIBWin.h
+endif
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+endif
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/SharedDIB.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "SharedDIB.h"
+
+namespace mozilla {
+namespace gfx {
+
+SharedDIB::SharedDIB() :
+  mShMem(nsnull)
+{
+}
+
+SharedDIB::~SharedDIB()
+{
+  Close();
+}
+
+nsresult
+SharedDIB::Create(PRUint32 aSize)
+{
+  Close();
+
+  mShMem = new base::SharedMemory();
+  if (!mShMem || !mShMem->Create(std::wstring(L""), false, false, aSize))
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  // Map the entire section
+  if (!mShMem->Map(0))
+    return NS_ERROR_FAILURE;
+
+  return NS_OK;
+}
+
+bool
+SharedDIB::IsValid()
+{
+  if (!mShMem)
+    return false;
+
+  return mShMem->IsHandleValid(mShMem->handle());
+}
+
+nsresult
+SharedDIB::Close()
+{
+  if (mShMem)
+    delete mShMem;
+
+  mShMem = nsnull;
+
+  return NS_OK;
+}
+
+nsresult
+SharedDIB::Attach(Handle aHandle, PRUint32 aSize)
+{
+  Close();
+
+  mShMem = new base::SharedMemory(aHandle, false);
+  if(!mShMem)
+    return NS_ERROR_OUT_OF_MEMORY;
+
+  if (!mShMem->Map(aSize))
+    return NS_ERROR_FAILURE;
+
+  return NS_OK;
+}
+
+nsresult
+SharedDIB::ShareToProcess(base::ProcessHandle aChildProcess, Handle *aChildHandle)
+{
+  if (!mShMem)
+    return NS_ERROR_UNEXPECTED;
+
+  if (!mShMem->ShareToProcess(aChildProcess, aChildHandle))
+    return NS_ERROR_UNEXPECTED;
+
+  return NS_OK;
+}
+
+} // gfx
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/SharedDIB.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef gfx_SharedDIB_h__
+#define gfx_SharedDIB_h__
+
+#include "base/shared_memory.h"
+#include "prtypes.h"
+#include "nscore.h"
+
+namespace mozilla {
+namespace gfx {
+
+class SharedDIB
+{
+public:
+  typedef base::SharedMemoryHandle Handle;
+
+public:
+  SharedDIB();
+  ~SharedDIB();
+
+  // Create and allocate a new shared dib.
+  nsresult Create(PRUint32 aSize);
+
+  // Destroy or release resources associated with this dib.
+  nsresult Close();
+
+  // Returns true if this object contains a valid dib.
+  bool IsValid();
+
+  // Wrap a new shared dib around allocated shared memory. Note aHandle must point
+  // to a memory section large enough to hold a dib of size aSize, otherwise this
+  // will fail.
+  nsresult Attach(Handle aHandle, PRUint32 aSize);
+
+  // Returns a SharedMemoryHandle suitable for sharing with another process.
+  nsresult ShareToProcess(base::ProcessHandle aChildProcess, Handle *aChildHandle);
+
+protected:
+  base::SharedMemory *mShMem;
+};
+
+} // gfx
+} // mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/SharedDIBWin.cpp
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "SharedDIBWin.h"
+#include "nsMathUtils.h"
+#include "nsDebug.h"
+
+namespace mozilla {
+namespace gfx {
+
+SharedDIBWin::SharedDIBWin() :
+    mSharedHdc(nsnull)
+  , mSharedBmp(nsnull)
+  , mOldObj(nsnull)
+{
+}
+
+SharedDIBWin::~SharedDIBWin()
+{
+  Close();
+}
+
+nsresult
+SharedDIBWin::Close()
+{
+  if (mSharedHdc && mOldObj)
+    ::SelectObject(mSharedHdc, mOldObj);
+
+  if (mSharedHdc)
+    ::DeleteObject(mSharedHdc);
+
+  if (mSharedBmp)
+    ::DeleteObject(mSharedBmp);
+
+  mSharedHdc = NULL;
+  mOldObj = mSharedBmp = NULL;
+
+  SharedDIB::Close();
+
+  return NS_OK;
+}
+
+nsresult
+SharedDIBWin::Create(HDC aHdc, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth)
+{
+  Close();
+
+  // create the offscreen shared dib
+  BITMAPINFOHEADER bmih;
+  PRUint32 size = SetupBitmapHeader(aWidth, aHeight, aDepth, &bmih);
+
+  nsresult rv = SharedDIB::Create(size);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (NS_FAILED(SetupSurface(aHdc, &bmih))) {
+    Close();
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+SharedDIBWin::Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth)
+{
+  Close();
+
+  BITMAPINFOHEADER bmih;
+  SetupBitmapHeader(aWidth, aHeight, aDepth, &bmih);
+
+  nsresult rv = SharedDIB::Attach(aHandle, 0);
+  if (NS_FAILED(rv))
+    return rv;
+
+  if (NS_FAILED(SetupSurface(NULL, &bmih))) {
+    Close();
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+PRUint32
+SharedDIBWin::SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth, BITMAPINFOHEADER *aHeader)
+{
+  NS_ASSERTION(aDepth == 32, "Invalid SharedDIBWin depth");
+
+  memset((void*)aHeader, 0, sizeof(BITMAPINFOHEADER));
+  aHeader->biSize        = sizeof(BITMAPINFOHEADER);
+  aHeader->biWidth       = aWidth;
+  aHeader->biHeight      = aHeight;
+  aHeader->biPlanes      = 1;
+  aHeader->biBitCount    = aDepth;
+  aHeader->biCompression = BI_RGB;
+
+  // deal better with varying depths. (we currently only ask for 32 bit)
+  return (sizeof(BITMAPINFOHEADER) + (aHeader->biHeight * aHeader->biWidth * (PRUint32)NS_ceil(aDepth/8)));
+}
+
+nsresult
+SharedDIBWin::SetupSurface(HDC aHdc, BITMAPINFOHEADER *aHdr)
+{
+  mSharedHdc = ::CreateCompatibleDC(aHdc);
+
+  if (!mSharedHdc)
+    return NS_ERROR_FAILURE;
+
+  void* ppvBits = nsnull;
+  mSharedBmp = ::CreateDIBSection(mSharedHdc,
+                                  (BITMAPINFO*)aHdr,
+                                  DIB_RGB_COLORS,
+                                  (void**)&ppvBits,
+                                  mShMem->handle(),
+                                  (unsigned long)sizeof(BITMAPINFOHEADER));
+  if (!mSharedBmp)
+    return NS_ERROR_FAILURE;
+
+  mOldObj = SelectObject(mSharedHdc, mSharedBmp);
+
+  return NS_OK;
+}
+
+
+} // gfx
+} // mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/ipc/SharedDIBWin.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Mathies <jmathies@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef gfx_SharedDIBWin_h__
+#define gfx_SharedDIBWin_h__
+
+#include <windows.h>
+
+#include "SharedDIB.h"
+
+namespace mozilla {
+namespace gfx {
+
+class SharedDIBWin : public SharedDIB
+{
+public:
+  SharedDIBWin();
+  ~SharedDIBWin();
+
+  // Allocate a new win32 dib section compatible with an hdc. The dib will
+  // be selected into the hdc on return.
+  nsresult Create(HDC aHdc, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
+
+  // Wrap a dib section around an existing shared memory object. aHandle should
+  // point to a section large enough for the dib's memory, otherwise this call
+  // will fail.
+  nsresult Attach(Handle aHandle, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
+
+  // Destroy or release resources associated with this dib.
+  nsresult Close();
+
+  // Return the HDC of the shared dib.
+  HDC GetHDC() { return mSharedHdc; }
+
+private:
+  HDC                 mSharedHdc;
+  HBITMAP             mSharedBmp;
+  HGDIOBJ             mOldObj;
+
+  PRUint32 SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth, BITMAPINFOHEADER *aHeader);
+  nsresult SetupSurface(HDC aHdc, BITMAPINFOHEADER *aHdr);
+};
+
+} // gfx
+} // mozilla
+
+#endif
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -670,17 +670,23 @@ nsThebesDeviceContext::SetDPI()
         PRInt32 prefDPI = -1;
         if (prefs) {
             rv = prefs->GetIntPref("layout.css.dpi", &prefDPI);
             if (NS_FAILED(rv)) {
                 prefDPI = -1;
             }
         }
 
-        dpi = gfxPlatform::GetDPI();        
+        dpi = gfxPlatform::GetDPI();
+
+#ifdef MOZ_ENABLE_GTK2
+        if (prefDPI < 0) // Clamp the minimum dpi to 96dpi
+            dpi = PR_MAX(dpi, 96);
+#endif
+ 
         if (prefDPI > 0 && !mPrintingSurface)
             dpi = prefDPI;
     }
 
     NS_ASSERTION(dpi != -1, "no dpi set");
 
     if (dotsArePixels) {
         if (prefDevPixelsPerCSSPixel <= 0) {
--- a/gfx/thebes/src/gfxPlatformGtk.cpp
+++ b/gfx/thebes/src/gfxPlatformGtk.cpp
@@ -525,19 +525,16 @@ gfxPlatformGtk::InitDisplayCaps()
 {
     // Make sure init is run so we have a resolution
     GdkScreen *screen = gdk_screen_get_default();
     gtk_settings_get_for_screen(screen);
     gfxPlatform::sDPI = PRInt32(round(gdk_screen_get_resolution(screen)));
     if (gfxPlatform::sDPI <= 0) {
         // Fall back to something sane
         gfxPlatform::sDPI = 96;
-    } else {
-        // Minimum DPI is 96
-        gfxPlatform::sDPI = PR_MAX(sDPI, 96);
     }
 }
 
 qcms_profile *
 gfxPlatformGtk::GetPlatformCMSOutputProfile()
 {
 #ifdef MOZ_X11
     const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA";
--- a/ipc/Makefile.in
+++ b/ipc/Makefile.in
@@ -36,11 +36,16 @@
 
 DEPTH = ..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
+# NB: chromium/ and glue/ are in tier_xpcom
+
+# tier_gecko:
+DIRS += ipdl
+
 TOOL_DIRS = app
 
 include $(topsrcdir)/config/rules.mk
--- a/ipc/chromium/Makefile.in
+++ b/ipc/chromium/Makefile.in
@@ -196,17 +196,17 @@ CPPSRCS += \
   system_monitor_posix.cc \
   sys_info_posix.cc \
   thread_local_posix.cc \
   thread_local_storage_posix.cc \
   waitable_event_posix.cc \
   waitable_event_watcher_posix.cc \
   file_descriptor_set_posix.cc \
   ipc_channel_posix.cc \
-  process_watcher_posix.cc \
+  process_watcher_posix_sigchld.cc \
   $(NULL)
 
 endif # } OS_POSIX
 
 ifdef OS_MACOSX # {
 
 CMMSRCS += \
   base_paths_mac.mm \
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- a/ipc/chromium/src/base/message_loop.cc
+++ b/ipc/chromium/src/base/message_loop.cc
@@ -627,9 +627,19 @@ bool MessageLoopForIO::WatchFileDescript
   return pump_libevent()->WatchFileDescriptor(
       fd,
       persistent,
       static_cast<base::MessagePumpLibevent::Mode>(mode),
       controller,
       delegate);
 }
 
+#if defined(CHROMIUM_MOZILLA_BUILD)
+bool
+MessageLoopForIO::CatchSignal(int sig,
+                              SignalEvent* sigevent,
+                              SignalWatcher* delegate)
+{
+  return pump_libevent()->CatchSignal(sig, sigevent, delegate);
+}
+#endif  // defined(CHROMIUM_MOZILLA_BUILD)
+
 #endif
--- a/ipc/chromium/src/base/message_loop.h
+++ b/ipc/chromium/src/base/message_loop.h
@@ -502,16 +502,25 @@ class MessageLoopForIO : public MessageL
   };
 
   // Please see MessagePumpLibevent for definition.
   bool WatchFileDescriptor(int fd,
                            bool persistent,
                            Mode mode,
                            FileDescriptorWatcher *controller,
                            Watcher *delegate);
+
+#if defined(CHROMIUM_MOZILLA_BUILD)
+  typedef base::MessagePumpLibevent::SignalEvent SignalEvent;
+  typedef base::MessagePumpLibevent::SignalWatcher SignalWatcher;
+  bool CatchSignal(int sig,
+                   SignalEvent* sigevent,
+                   SignalWatcher* delegate);
+#endif  // defined(CHROMIUM_MOZILLA_BUILD)
+
 #endif  // defined(OS_POSIX)
 };
 
 // Do not add any member variables to MessageLoopForIO!  This is important b/c
 // MessageLoopForIO is often allocated via MessageLoop(TYPE_IO).  Any extra
 // data that you need should be stored on the MessageLoop's pump_ instance.
 COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO),
                MessageLoopForIO_should_not_have_extra_member_variables);
--- a/ipc/chromium/src/base/message_pump_libevent.cc
+++ b/ipc/chromium/src/base/message_pump_libevent.cc
@@ -206,16 +206,101 @@ void MessagePumpLibevent::OnLibeventNoti
   if (flags & EV_WRITE) {
     watcher->OnFileCanWriteWithoutBlocking(fd);
   }
   if (flags & EV_READ) {
     watcher->OnFileCanReadWithoutBlocking(fd);
   }
 }
 
+
+#if defined(CHROMIUM_MOZILLA_BUILD)
+MessagePumpLibevent::SignalEvent::SignalEvent() :
+  event_(NULL)
+{
+}
+
+MessagePumpLibevent::SignalEvent::~SignalEvent()
+{
+  if (event_) {
+    StopCatching();
+  }
+}
+
+void
+MessagePumpLibevent::SignalEvent::Init(event *e)
+{
+  DCHECK(e);
+  DCHECK(event_ == NULL);
+  event_ = e;
+}
+
+bool
+MessagePumpLibevent::SignalEvent::StopCatching()
+{
+  // XXX/cjones: this code could be shared with
+  // FileDescriptorWatcher. ironic that libevent is "more"
+  // object-oriented than this C++
+  event* e = ReleaseEvent();
+  if (e == NULL)
+    return true;
+
+  // event_del() is a no-op if the event isn't active.
+  int rv = event_del(e);
+  delete e;
+  return (rv == 0);
+}
+
+event *
+MessagePumpLibevent::SignalEvent::ReleaseEvent()
+{
+  event *e = event_;
+  event_ = NULL;
+  return e;
+}
+
+bool
+MessagePumpLibevent::CatchSignal(int sig,
+                                 SignalEvent* sigevent,
+                                 SignalWatcher* delegate)
+{
+  DCHECK(sig > 0);
+  DCHECK(sigevent);
+  DCHECK(delegate);
+  // TODO if we want to support re-using SignalEvents, this code needs
+  // to jump through the same hoops as WatchFileDescriptor().  Not
+  // needed at present
+  DCHECK(NULL == sigevent->event_);
+
+  scoped_ptr<event> evt(new event);
+  signal_set(evt.get(), sig, OnLibeventSignalNotification, delegate);
+
+  if (event_base_set(event_base_, evt.get()))
+    return false;
+
+  if (signal_add(evt.get(), NULL))
+    return false;
+
+  // Transfer ownership of evt to controller.
+  sigevent->Init(evt.release());
+  return true;
+}
+
+void
+MessagePumpLibevent::OnLibeventSignalNotification(int sig, short flags,
+                                                  void* context)
+{
+  DCHECK(sig > 0);
+  DCHECK(EV_SIGNAL == flags);
+  DCHECK(context);
+  reinterpret_cast<SignalWatcher*>(context)->OnSignal(sig);
+}
+#endif  // defined(CHROMIUM_MOZILLA_BUILD)
+
+
 // Reentrant!
 void MessagePumpLibevent::Run(Delegate* delegate) {
   DCHECK(keep_running_) << "Quit must have been called outside of Run!";
 
   bool old_in_run = in_run_;
   in_run_ = true;
 
   for (;;) {
--- a/ipc/chromium/src/base/message_pump_libevent.h
+++ b/ipc/chromium/src/base/message_pump_libevent.h
@@ -79,16 +79,64 @@ class MessagePumpLibevent : public Messa
   // Returns true on success.
   // TODO(dkegel): switch to edge-triggered readiness notification
   bool WatchFileDescriptor(int fd,
                            bool persistent,
                            Mode mode,
                            FileDescriptorWatcher *controller,
                            Watcher *delegate);
 
+
+#if defined(CHROMIUM_MOZILLA_BUILD)
+  // This is analagous to FileDescriptorWatcher above, which really is
+  // just a wrapper around libevent's |struct event|.  This class acts
+  // as a sort of "scoped event watcher" in that it guarantees that
+  // when this class is out of scope, the signal-event it wraps is
+  // removed from libevent's guts.
+  //
+  // XXX/cjones: this isn't my favorite API, but preserving it in
+  // order to match code above
+  class SignalEvent {
+     friend class MessagePumpLibevent;
+
+  public:
+    SignalEvent();
+    ~SignalEvent();             // implicitly calls StopCatching()
+
+    // Have libevent forget this event.
+    bool StopCatching();
+
+  private:
+    void Init(event* e);
+    event* ReleaseEvent();
+
+    event* event_;
+
+    DISALLOW_COPY_AND_ASSIGN(SignalEvent);
+  };
+
+  class SignalWatcher {
+  public:
+    virtual ~SignalWatcher() {}
+    // Called from MessageLoop::Run when |sig| has been delivered to
+    // this process
+    virtual void OnSignal(int sig) = 0;
+  };
+
+  // Have the current thread's message loop catch the signal |sig|.
+  // Multiple watchers can catch the same signal; they're all notified
+  // upon its delivery.  Callers must provide a preallocated
+  // SignalEvent object which can be used to manage the lifetime of
+  // this event.  Returns true on success.
+  bool CatchSignal(int sig,
+                   SignalEvent* sigevent,
+                   SignalWatcher* delegate);
+#endif  // defined(CHROMIUM_MOZILLA_BUILD)
+
+
   // MessagePump methods:
   virtual void Run(Delegate* delegate);
   virtual void Quit();
   virtual void ScheduleWork();
   virtual void ScheduleDelayedWork(const Time& delayed_work_time);
 
  private:
 
@@ -107,16 +155,22 @@ class MessagePumpLibevent : public Messa
   // Libevent dispatcher.  Watches all sockets registered with it, and sends
   // readiness callbacks when a socket is ready for I/O.
   event_base* event_base_;
 
   // Called by libevent to tell us a registered FD can be read/written to.
   static void OnLibeventNotification(int fd, short flags,
                                      void* context);
 
+#if defined(CHROMIUM_MOZILLA_BUILD)
+  // Called by libevent upon receiving a signal
+  static void OnLibeventSignalNotification(int sig, short flags,
+                                           void* context);
+#endif
+
   // Unix pipe used to implement ScheduleWork()
   // ... callback; called by libevent inside Run() when pipe is ready to read
   static void OnWakeup(int socket, short flags, void* context);
   // ... write end; ScheduleWork() writes a single byte to it
   int wakeup_pipe_in_;
   // ... read end; OnWakeup reads it and then breaks Run() out of its sleep
   int wakeup_pipe_out_;
   // ... libevent wrapper for read end
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/chrome/common/process_watcher_posix_sigchld.cc
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 et sw=2 tw=80: 
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+//-----------------------------------------------------------------------------
+//   XXXXXXXXXXXXXXXX
+//
+// How is this code supposed to be licensed?  I don't /think/ that
+// this code is doing anything different than, say,
+// GeckoChildProcess.h/cpp, so I /think/ this gets a MoFo copyright
+// and license.  Yes?
+//
+//   XXXXXXXXXXXXXXXX
+//-----------------------------------------------------------------------------
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "base/eintr_wrapper.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+
+#include "chrome/common/process_watcher.h"
+
+// Maximum amount of time (in milliseconds) to wait for the process to exit.
+// XXX/cjones: fairly arbitrary, chosen to match process_watcher_win.cc
+static const int kMaxWaitMs = 2000;
+
+namespace {
+
+bool
+IsProcessDead(pid_t process)
+{
+  bool exited = false;
+  // don't care if the process crashed, just if it exited
+  base::DidProcessCrash(&exited, process);
+  return exited;
+}
+
+// Fear the reaper
+class ChildReaper : public Task,
+                    public base::MessagePumpLibevent::SignalEvent,
+                    public base::MessagePumpLibevent::SignalWatcher
+{
+public:
+  explicit ChildReaper(pid_t process) : process_(process)
+  {
+  } 
+
+  virtual ~ChildReaper()
+  {
+    if (process_)
+      KillProcess();
+    // StopCatching() is implicit
+  }
+
+  // @override
+  virtual void OnSignal(int sig)
+  {
+    DCHECK(SIGCHLD == sig);
+    DCHECK(process_);
+
+    // this may be the SIGCHLD for a process other than |process_|
+    if (IsProcessDead(process_)) {
+      process_ = 0;
+      StopCatching();
+    }
+  }
+
+  // @override
+  virtual void Run()
+  {
+    // we may have already been signaled by the time this runs
+    if (process_)
+      KillProcess();
+  }
+
+private:
+  void KillProcess()
+  {
+    DCHECK(process_);
+
+    if (IsProcessDead(process_)) {
+      process_ = 0;
+      return;
+    }
+
+    if (0 == kill(process_, SIGKILL)) {
+      // XXX this will block for whatever amount of time it takes the
+      // XXX OS to tear down the process's resources.  might need to
+      // XXX rethink this if it proves expensive
+      HANDLE_EINTR(waitpid(process_, NULL, 0));
+    }
+    else {
+      LOG(ERROR) << "Failed to deliver SIGKILL to " << process_ << "!"
+                 << "("<< errno << ").";
+    }
+    process_ = 0;
+  }
+
+  pid_t process_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(ChildReaper);
+};
+
+}  // namespace <anon>
+
+
+void
+ProcessWatcher::EnsureProcessTerminated(base::ProcessHandle process)
+{
+  DCHECK(process != base::GetCurrentProcId());
+  DCHECK(process > 0);
+
+  if (IsProcessDead(process))
+    return;
+
+  MessageLoopForIO* loop = MessageLoopForIO::current();
+  ChildReaper* reaper = new ChildReaper(process);
+
+  // there are three ways |process| will be reaped:
+  //  (1) catch SIGCHLD after its death (common case)
+  //  (2) kMaxWaitMs timeout fires, |kill(SIGKILL)|
+  //  (3) shutdown before (1) or (2), |reaper| dtor does |kill(SIGKILL)|
+  loop->CatchSignal(SIGCHLD, reaper, reaper);
+  // |loop| takes ownership of |reaper|
+  loop->PostDelayedTask(FROM_HERE, reaper, kMaxWaitMs);
+}
--- a/ipc/glue/AsyncChannel.cpp
+++ b/ipc/glue/AsyncChannel.cpp
@@ -34,16 +34,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/ipc/AsyncChannel.h"
 #include "mozilla/ipc/GeckoThread.h"
+#include "mozilla/ipc/ProtocolUtils.h"
 
 #include "nsDebug.h"
 #include "nsTraceRefcnt.h"
 #include "nsXULAppAPI.h"
 
 using mozilla::MutexAutoLock;
 
 template<>
@@ -66,21 +67,17 @@ AsyncChannel::AsyncChannel(AsyncListener
     mWorkerLoop()
 {
     MOZ_COUNT_CTOR(AsyncChannel);
 }
 
 AsyncChannel::~AsyncChannel()
 {
     MOZ_COUNT_DTOR(AsyncChannel);
-    if (!mChild && mTransport)
-        Close();
-    // we only hold a weak ref to the transport, which is "owned"
-    // by GeckoChildProcess/GeckoThread
-    mTransport = 0;
+    Clear();
 }
 
 bool
 AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
 {
     NS_PRECONDITION(!mTransport, "Open() called > once");
     NS_PRECONDITION(aTransport, "need transport layer");
 
@@ -124,29 +121,44 @@ AsyncChannel::Open(Transport* aTransport
     }
 
     return true;
 }
 
 void
 AsyncChannel::Close()
 {
-    MutexAutoLock lock(mMutex);
+    {
+        MutexAutoLock lock(mMutex);
 
-    if (!mChild && ChannelConnected == mChannelState) {
+        if (ChannelConnected != mChannelState)
+            // XXX be strict about this until there's a compelling reason
+            // to relax
+            NS_RUNTIMEABORT("Close() called on closed channel!");
+
         AssertWorkerThread();
 
-        mIOLoop->PostTask(
-            FROM_HERE, NewRunnableMethod(this, &AsyncChannel::OnClose));
+        // notify the other side that we're about to close our socket
+        SendGoodbye();
+
+        mChannelState = ChannelClosing;
 
-        while (ChannelConnected == mChannelState)
+        // and post the task will do the actual close
+        mIOLoop->PostTask(
+            FROM_HERE, NewRunnableMethod(this, &AsyncChannel::OnCloseChannel));
+
+        while (ChannelClosing == mChannelState)
             mCvar.Wait();
+
+        // TODO sort out Close() on this side racing with Close() on the
+        // other side
+        mChannelState = ChannelClosed;
     }
 
-    mTransport = NULL;
+    return NotifyChannelClosed();
 }
 
 bool
 AsyncChannel::Send(Message* msg)
 {
     AssertWorkerThread();
     mMutex.AssertNotCurrentThreadOwns();
     NS_ABORT_IF_FALSE(MSG_ROUTING_NONE != msg->routing_id(), "need a route");
@@ -168,19 +180,128 @@ AsyncChannel::Send(Message* msg)
 
 void
 AsyncChannel::OnDispatchMessage(const Message& msg)
 {
     AssertWorkerThread();
     NS_ASSERTION(!msg.is_reply(), "can't process replies here");
     NS_ASSERTION(!(msg.is_sync() || msg.is_rpc()), "async dispatch only");
 
+    if (MaybeInterceptGoodbye(msg))
+        // there's a NotifyMaybeChannelError event waiting for us, or
+        // will be soon
+        return;
+
+    // it's OK to dispatch messages if the channel is closed/error'd,
+    // since we don't have a reply to send back
+
     (void)MaybeHandleError(mListener->OnMessageReceived(msg), "AsyncChannel");
 }
 
+// This is an async message
+class GoodbyeMessage : public IPC::Message
+{
+public:
+    enum { ID = GOODBYE_MESSAGE_TYPE };
+    GoodbyeMessage() :
+        IPC::Message(MSG_ROUTING_NONE, ID, PRIORITY_NORMAL)
+    {
+    }
+    // XXX not much point in implementing this; maybe could help with
+    // debugging?
+    static bool Read(const Message* msg)
+    {
+        return true;
+    }
+    void Log(const std::string& aPrefix,
+             FILE* aOutf) const
+    {
+        fputs("(special `Goodbye' message)", aOutf);
+    }
+};
+
+void
+AsyncChannel::SendGoodbye()
+{
+    AssertWorkerThread();
+
+    mIOLoop->PostTask(
+        FROM_HERE,
+        NewRunnableMethod(this, &AsyncChannel::OnSend, new GoodbyeMessage()));
+}
+
+bool
+AsyncChannel::MaybeInterceptGoodbye(const Message& msg)
+{
+    // IPDL code isn't allowed to send MSG_ROUTING_NONE messages, so
+    // there's no chance of confusion here
+    if (MSG_ROUTING_NONE != msg.routing_id())
+        return false;
+
+    if (msg.is_sync() || msg.is_rpc() || GOODBYE_MESSAGE_TYPE != msg.type())
+        NS_RUNTIMEABORT("received unknown MSG_ROUTING_NONE message when expecting `Goodbye'");
+
+    MutexAutoLock lock(mMutex);
+    // TODO sort out Close() on this side racing with Close() on the
+    // other side
+    mChannelState = ChannelClosing;
+
+    printf("NOTE: %s process received `Goodbye', closing down\n",
+           mChild ? "child" : "parent");
+
+    return true;
+}
+
+void
+AsyncChannel::NotifyChannelClosed()
+{
+    if (ChannelClosed != mChannelState)
+        NS_RUNTIMEABORT("channel should have been closed!");
+
+    // OK, the IO thread just closed the channel normally.  Let the
+    // listener know about it.
+    mListener->OnChannelClose();
+    Clear();
+}
+
+void
+AsyncChannel::NotifyMaybeChannelError()
+{
+    // TODO sort out Close() on this side racing with Close() on the
+    // other side
+    if (ChannelClosing == mChannelState) {
+        // the channel closed, but we received a "Goodbye" message
+        // warning us about it. no worries
+        mChannelState = ChannelClosed;
+        return NotifyChannelClosed();
+    }
+
+    // Oops, error!  Let the listener know about it.
+    mChannelState = ChannelError;
+    mListener->OnChannelError();
+
+    Clear();
+}
+
+void
+AsyncChannel::Clear()
+{
+    mListener = 0;
+    mIOLoop = 0;
+    mWorkerLoop = 0;
+
+    if (mTransport) {
+        mTransport->set_listener(0);
+
+        // we only hold a weak ref to the transport, which is "owned"
+        // by GeckoChildProcess/GeckoThread
+        mTransport = 0;
+    }
+}
+
 bool
 AsyncChannel::MaybeHandleError(Result code, const char* channelName)
 {
     if (MsgProcessed == code)
         return true;
 
     const char* errorMsg;
     switch (code) {
@@ -196,17 +317,17 @@ AsyncChannel::MaybeHandleError(Result co
     case MsgRouteError:
         errorMsg = "Route error: message sent to unknown actor ID";
         break;
     case MsgValueError:
         errorMsg = "Value error: message was deserialized, but contained an illegal value";
         break;
 
     default:
-        NOTREACHED();
+        NS_RUNTIMEABORT("unknown Result code");
         return false;
     }
 
     PrintErrorMessage(channelName, errorMsg);
     return false;
 }
 
 void
@@ -227,100 +348,81 @@ AsyncChannel::ReportConnectionError(cons
     default:
         NOTREACHED();
     }
 
     PrintErrorMessage(channelName, errorMsg);
 }
 
 //
-// The methods below run in the context of the IO thread, and can proxy
-// back to the methods above
+// The methods below run in the context of the IO thread
 //
 
 void
 AsyncChannel::OnMessageReceived(const Message& msg)
 {
     AssertIOThread();
     NS_ASSERTION(mChannelState != ChannelError, "Shouldn't get here!");
 
     // wake up the worker, there's work to do
     mWorkerLoop->PostTask(
         FROM_HERE,
         NewRunnableMethod(this, &AsyncChannel::OnDispatchMessage, msg));
 }
 
 void
+AsyncChannel::OnChannelOpened()
+{
+    AssertIOThread();
+    mChannelState = ChannelOpening;
+    /*assert*/mTransport->Connect();
+}
+
+void
 AsyncChannel::OnChannelConnected(int32 peer_pid)
 {
     AssertIOThread();
 
     MutexAutoLock lock(mMutex);
     mChannelState = ChannelConnected;
     mCvar.Notify();
 }
 
 void
 AsyncChannel::OnChannelError()
 {
     AssertIOThread();
 
-    {
-        MutexAutoLock lock(mMutex);
-        mChannelState = ChannelError;
-    }
-
-    if (XRE_GetProcessType() == GeckoProcessType_Default) {
-        // Parent process, one of our children died. Notify?
-    }
-    else {
-        // Child process, initiate quit sequence.
-#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)
-        // XXXbent this is totally out of place, but works for now.
-        XRE_ShutdownChildProcess(mWorkerLoop);
+    MutexAutoLock lock(mMutex);
 
-        // Must exit the IO loop, which will then join with the UI loop.
-        MessageLoop::current()->Quit();
-#else
-        // FIXME need to devote some thought to the most
-        // effective/least easily overrideable, yet quiet, way to
-        // exit.  abort() is a little loud
-        _exit(0);
-#endif
-    }
-}
+    // NB: this can race with the `Goodbye' event being processed by
+    // the worker thread
+    if (ChannelClosing != mChannelState)
+        mChannelState = ChannelError;
 
-void
-AsyncChannel::OnChannelOpened()
-{
-    AssertIOThread();
-    mChannelState = ChannelOpening;
-    /*assert*/mTransport->Connect();
+    mWorkerLoop->PostTask(
+        FROM_HERE,
+        NewRunnableMethod(this, &AsyncChannel::NotifyMaybeChannelError));
 }
 
 void
 AsyncChannel::OnSend(Message* aMsg)
 {
     AssertIOThread();
     mTransport->Send(aMsg);
-    // mTransport deletes aMsg
+    // mTransport assumes ownership of aMsg
 }
 
 void
-AsyncChannel::OnClose()
+AsyncChannel::OnCloseChannel()
 {
     AssertIOThread();
 
     mTransport->Close();
 
-    // don't lose error-state information
-    if (ChannelError != mChannelState)
-        mChannelState = ChannelClosed;
-
-    if (!mChild) {
-        MutexAutoLock lock(mMutex);
-        mCvar.Notify();
-    }
+    MutexAutoLock lock(mMutex);
+    mChannelState = ChannelClosed;
+    mCvar.Notify();
 }
 
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/glue/AsyncChannel.h
+++ b/ipc/glue/AsyncChannel.h
@@ -70,47 +70,58 @@ class AsyncChannel : public IPC::Channel
 protected:
     typedef mozilla::CondVar CondVar;
     typedef mozilla::Mutex Mutex;
 
     enum ChannelState {
         ChannelClosed,
         ChannelOpening,
         ChannelConnected,
+        ChannelClosing,
         ChannelError
     };
 
 public:
     typedef IPC::Channel Transport;
     typedef IPC::Message Message;
 
     class /*NS_INTERFACE_CLASS*/ AsyncListener: protected HasResultCodes
     {
     public:
         virtual ~AsyncListener() { }
+
+        virtual void OnChannelClose() = 0;
+        virtual void OnChannelError() = 0;
         virtual Result OnMessageReceived(const Message& aMessage) = 0;
     };
 
 public:
+    //
+    // These methods are called on the "worker" thread
+    //
     AsyncChannel(AsyncListener* aListener);
     virtual ~AsyncChannel();
 
     // Open  from the perspective of the transport layer; the underlying
     // socketpair/pipe should already be created.
     //
     // Returns true iff the transport layer was successfully connected,
     // i.e., mChannelState == ChannelConnected.
     bool Open(Transport* aTransport, MessageLoop* aIOLoop=0);
     
     // Close the underlying transport channel.
     void Close();
 
     // Asynchronously send a message to the other side of the channel
     bool Send(Message* msg);
 
+    //
+    // These methods are called on the "IO" thread
+    //
+
     // Implement the IPC::Channel::Listener interface
     NS_OVERRIDE virtual void OnMessageReceived(const Message& msg);
     NS_OVERRIDE virtual void OnChannelConnected(int32 peer_pid);
     NS_OVERRIDE virtual void OnChannelError();
 
 protected:
     // Can be run on either thread
     void AssertWorkerThread()
@@ -136,20 +147,31 @@ protected:
     void ReportConnectionError(const char* channelName);
 
     void PrintErrorMessage(const char* channelName, const char* msg)
     {
         fprintf(stderr, "\n###!!! [%s][%s] Error: %s\n\n",
                 mChild ? "Child" : "Parent", channelName, msg);
     }
 
+    // Run on the worker thread
+
+    void SendGoodbye();
+    bool MaybeInterceptGoodbye(const Message& msg);
+
+    void NotifyChannelClosed();
+    void NotifyMaybeChannelError();
+
+    void Clear();
+
     // Run on the IO thread
+
     void OnChannelOpened();
     void OnSend(Message* aMsg);
-    void OnClose();
+    void OnCloseChannel();
 
     Transport* mTransport;
     AsyncListener* mListener;
     ChannelState mChannelState;
     Mutex mMutex;
     CondVar mCvar;
     MessageLoop* mIOLoop;       // thread where IO happens
     MessageLoop* mWorkerLoop;   // thread where work is done
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -40,20 +40,16 @@
 #define __IPC_GLUE_IPCMESSAGEUTILS_H__
 
 #include "chrome/common/ipc_message_utils.h"
 
 #include "prtypes.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 
-#include "IPCMessageStart.h"
-
-COMPILE_ASSERT(LastMsgIndex <= 64, need_to_update_IPC_MESSAGE_MACRO);
-
 namespace IPC {
 
 template <>
 struct ParamTraits<nsACString>
 {
   typedef nsACString paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -36,21 +36,29 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_ipc_ProtocolUtils_h
 #define mozilla_ipc_ProtocolUtils_h 1
 
 #include "base/process.h"
+#include "base/process_util.h"
 #include "chrome/common/ipc_message_utils.h"
 
 #include "prenv.h"
 
-#include "mozilla/ipc/RPCChannel.h"
+
+// WARNING: this takes into account the private, special-message-type
+// enum in ipc_channel.h.  They need to be kept in sync.
+namespace {
+enum {
+    GOODBYE_MESSAGE_TYPE       = kuint16max - 1,
+};
+}
 
 namespace mozilla {
 namespace ipc {
 
 
 // Used to pass references to protocol actors across the wire.
 // Actors created on the parent-side have a positive ID, and actors
 // allocated on the child side have a negative ID.
@@ -58,24 +66,31 @@ struct ActorHandle
 {
     int mId;
 };
 
 template<class ListenerT>
 class /*NS_INTERFACE_CLASS*/ IProtocolManager
 {
 public:
+    enum ActorDestroyReason {
+        Deletion,
+        AncestorDeletion,
+        NormalShutdown,
+        AbnormalShutdown
+    };
+
     typedef base::ProcessHandle ProcessHandle;
 
     virtual int32 Register(ListenerT*) = 0;
     virtual int32 RegisterID(ListenerT*, int32) = 0;
     virtual ListenerT* Lookup(int32) = 0;
     virtual void Unregister(int32) = 0;
     // XXX odd duck, acknowledged
-    virtual ProcessHandle OtherProcess() = 0;
+    virtual ProcessHandle OtherProcess() const = 0;
 };
 
 
 inline bool
 LoggingEnabled()
 {
 #if defined(DEBUG)
     return !!PR_GetEnv("MOZ_IPC_MESSAGE_LOG");
--- a/ipc/glue/RPCChannel.cpp
+++ b/ipc/glue/RPCChannel.cpp
@@ -79,16 +79,17 @@ RPCChannel::~RPCChannel()
     MOZ_COUNT_DTOR(RPCChannel);
     // FIXME/cjones: impl
 }
 
 bool
 RPCChannel::Call(Message* msg, Message* reply)
 {
     AssertWorkerThread();
+    mMutex.AssertNotCurrentThreadOwns();
     RPC_ASSERT(!ProcessingSyncMessage(),
                "violation of sync handler invariant");
     RPC_ASSERT(msg->is_rpc(), "can only Call() RPC messages here");
 
     MutexAutoLock lock(mMutex);
 
     if (!Connected()) {
         ReportConnectionError("RPCChannel");
@@ -412,27 +413,22 @@ RPCChannel::OnMessageReceived(const Mess
         NotifyWorkerThread();
 }
 
 
 void
 RPCChannel::OnChannelError()
 {
     AssertIOThread();
-    {
-        MutexAutoLock lock(mMutex);
 
-        mChannelState = ChannelError;
-
-        if (AwaitingSyncReply()
-            || 0 < StackDepth())
-            NotifyWorkerThread();
-    }
+    AsyncChannel::OnChannelError();
 
     // skip SyncChannel::OnError(); we subsume its duties
-
-    return AsyncChannel::OnChannelError();
+    MutexAutoLock lock(mMutex);
+    if (AwaitingSyncReply()
+        || 0 < StackDepth())
+        NotifyWorkerThread();
 }
 
 
 } // namespace ipc
 } // namespace mozilla
 
--- a/ipc/glue/RPCChannel.h
+++ b/ipc/glue/RPCChannel.h
@@ -52,16 +52,19 @@ namespace ipc {
 class RPCChannel : public SyncChannel
 {
 public:
     class /*NS_INTERFACE_CLASS*/ RPCListener :
         public SyncChannel::SyncListener
     {
     public:
         virtual ~RPCListener() { }
+
+        virtual void OnChannelClose() = 0;
+        virtual void OnChannelError() = 0;
         virtual Result OnMessageReceived(const Message& aMessage) = 0;
         virtual Result OnMessageReceived(const Message& aMessage,
                                          Message*& aReply) = 0;
         virtual Result OnCallReceived(const Message& aMessage,
                                       Message*& aReply) = 0;
     };
 
     // What happens if RPC calls race?
--- a/ipc/glue/SyncChannel.cpp
+++ b/ipc/glue/SyncChannel.cpp
@@ -71,16 +71,17 @@ SyncChannel::~SyncChannel()
 
 // static
 bool SyncChannel::sIsPumpingMessages = false;
 
 bool
 SyncChannel::Send(Message* msg, Message* reply)
 {
     AssertWorkerThread();
+    mMutex.AssertNotCurrentThreadOwns();
     NS_ABORT_IF_FALSE(!ProcessingSyncMessage(),
                       "violation of sync handler invariant");
     NS_ABORT_IF_FALSE(msg->is_sync(), "can only Send() sync messages here");
 
     MutexAutoLock lock(mMutex);
 
     if (!Connected()) {
         ReportConnectionError("SyncChannel");
@@ -172,27 +173,22 @@ SyncChannel::OnMessageReceived(const Mes
         NotifyWorkerThread();
     }
 }
 
 void
 SyncChannel::OnChannelError()
 {
     AssertIOThread();
-    {
-        MutexAutoLock lock(mMutex);
 
-        mChannelState = ChannelError;
+    AsyncChannel::OnChannelError();
 
-        if (AwaitingSyncReply()) {
-            NotifyWorkerThread();
-        }
-    }
-
-    return AsyncChannel::OnChannelError();
+    MutexAutoLock lock(mMutex);
+    if (AwaitingSyncReply())
+        NotifyWorkerThread();
 }
 
 //
 // Synchronization between worker and IO threads
 //
 
 // Windows versions of the following two functions live in
 // WindowsMessageLoop.cpp.
--- a/ipc/glue/SyncChannel.h
+++ b/ipc/glue/SyncChannel.h
@@ -52,16 +52,19 @@ protected:
     typedef uint16 MessageId;
 
 public:
     class /*NS_INTERFACE_CLASS*/ SyncListener : 
         public AsyncChannel::AsyncListener
     {
     public:
         virtual ~SyncListener() { }
+
+        virtual void OnChannelClose() = 0;
+        virtual void OnChannelError() = 0;
         virtual Result OnMessageReceived(const Message& aMessage) = 0;
         virtual Result OnMessageReceived(const Message& aMessage,
                                          Message*& aReply) = 0;
     };
 
     SyncChannel(SyncListener* aListener);
     virtual ~SyncChannel();
 
--- a/ipc/glue/WindowsMessageLoop.cpp
+++ b/ipc/glue/WindowsMessageLoop.cpp
@@ -168,16 +168,17 @@ ProcessOrDeferMessage(HWND hwnd,
   // Most messages ask for 0 to be returned if the message is processed.
   LRESULT res = 0;
 
   switch (uMsg) {
     // Messages that can be deferred as-is. These must not contain pointers in
     // their wParam or lParam arguments!
     case WM_ACTIVATE:
     case WM_ACTIVATEAPP:
+    case WM_CAPTURECHANGED:
     case WM_CHILDACTIVATE:
     case WM_DESTROY:
     case WM_IME_NOTIFY:
     case WM_IME_SETCONTEXT:
     case WM_KILLFOCUS:
     case WM_NCDESTROY:
     case WM_PARENTNOTIFY:
     case WM_SETFOCUS:
@@ -195,16 +196,22 @@ ProcessOrDeferMessage(HWND hwnd,
     }
 
     case WM_NCACTIVATE: {
       res = TRUE;
       deferred = new DeferredNCActivateMessage(hwnd, uMsg, wParam, lParam);
       break;
     }
 
+    case WM_MOUSEACTIVATE: {
+      res = MA_NOACTIVATE;
+      deferred = new DeferredSendMessage(hwnd, uMsg, wParam, lParam);
+      break;
+    }
+
     // These messages need to use the RedrawWindow function to generate the
     // right kind of message. We can't simply fake them as the MSDN docs say
     // explicitly that paint messages should not be sent by an application.
     case WM_ERASEBKGND: {
       UINT flags = RDW_INVALIDATE | RDW_ERASE | RDW_NOINTERNALPAINT |
                    RDW_NOFRAME | RDW_NOCHILDREN | RDW_ERASENOW;
       deferred = new DeferredRedrawMessage(hwnd, flags);
       break;
--- a/ipc/ipdl/Makefile.in
+++ b/ipc/ipdl/Makefile.in
@@ -39,33 +39,64 @@ topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 GARBAGE_DIRS += _ipdlheaders
 GARBAGE += ipdl_lextab.py ipdl_yacctab.py
 
-include $(topsrcdir)/config/rules.mk
+MODULE = ipdlgen
+LIBRARY_NAME = mozipdlgen_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+EXPORT_LIBRARY = 1
 
+##-----------------------------------------------------------------------------
+## When you add IPDL files to a source directory, list the directory here.
+##
 IPDLDIRS =  \
   dom/plugins  \
   ipc/ipdl/test/cxx  \
   $(NULL)
+##-----------------------------------------------------------------------------
+
+ifdef MOZ_IPDL_TESTS
+DIRS += test
+endif
 
 vpath %.ipdl $(topsrcdir)
 
 define ADD_IPDLDIR
 include $(topsrcdir)/$(IPDLDIR)/ipdl.mk
 ALL_IPDLSRCS += $$(IPDLSRCS:%=$(IPDLDIR)/%)
+PROTOCOLS += $$(IPDLSRCS)
 endef
 
 ALL_IPDLSRCS :=
+PROTOCOLS :=
 
 $(foreach IPDLDIR,$(IPDLDIRS),$(eval $(ADD_IPDLDIR)))
 
+
+CPPSRCS =					\
+  $(PROTOCOLS:%.ipdl=%Parent.cpp)		\
+  $(PROTOCOLS:%.ipdl=%Child.cpp)		\
+  $(NULL)
+
+LOCAL_INCLUDES += -I$(DEPTH)/ipc/ipdl/_ipdlheaders
+
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+include $(topsrcdir)/config/rules.mk
+
+
+# NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself,
+# which is why we don't have explicit .h/.cpp targets here
 export:: $(ALL_IPDLSRCS)
-	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
-	  -I$(topsrcdir)/other-licenses/ply \
-	  $(srcdir)/ipdl.py \
-	  -d _ipdlheaders \
-	  $(IPDLDIRS:%=-I$(topsrcdir)/%) \
+	$(PYTHON) $(topsrcdir)/config/pythonpath.py	\
+	  -I$(topsrcdir)/other-licenses/ply		\
+	  $(srcdir)/ipdl.py				\
+	  --outheaders-dir=_ipdlheaders			\
+	  --outcpp-dir=.				\
+	  $(IPDLDIRS:%=-I$(topsrcdir)/%)		\
 	  $^
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -37,35 +37,46 @@ import ipdl
 
 def log(minv, fmt, *args):
     if _verbosity >= minv:
         print >>sys.stderr, fmt % args
 
 # process command line
 
 op = optparse.OptionParser(usage='ipdl.py [options] IPDLfiles...')
-op.add_option('-d', '--output-dir', dest='outputdir', default='.',
-              help='Directory in which to put generated headers')
 op.add_option('-I', '--include', dest='includedirs', default=[ ],
               action='append',
               help='Additional directory to search for included protocol specifications')
 op.add_option('-v', '--verbose', dest='verbosity', default=1, action='count',
               help='Verbose logging (specify -vv or -vvv for very verbose logging)')
 op.add_option('-q', '--quiet', dest='verbosity', action='store_const', const=0,
               help="Suppress logging output")
+op.add_option('-d', '--outheaders-dir', dest='headersdir', default='.',
+              help="""Directory into which C++ headers will be generated.
+A protocol Foo in the namespace bar will cause the headers
+  dir/bar/Foo.h, dir/bar/FooParent.h, and dir/bar/FooParent.h
+to be generated""")
+op.add_option('-o', '--outcpp-dir', dest='cppdir', default='.',
+              help="""Directory into which C++ sources will be generated
+A protocol Foo in the namespace bar will cause the sources
+  cppdir/FooParent.cpp, cppdir/FooChild.cpp
+to be generated""")
+
 
 options, files = op.parse_args()
 _verbosity = options.verbosity
-codedir = options.outputdir
+headersdir = options.headersdir
+cppdir = options.cppdir
 includedirs = [ os.path.abspath(incdir) for incdir in options.includedirs ]
 
 if not len(files):
     op.error("No IPDL files specified")
 
-log(1, 'Generated headers will be placed in "%s"', codedir)
+log(1, 'Generated C++ headers will be generated relative to "%s"', headersdir)
+log(1, 'Generated C++ sources will be generated in "%s"', cppdir)
 
 allprotocols = []
 
 for f in files:
     log(1, 'Parsing specification %s', f)
     if f == '-':
         fd = sys.stdin
         filename = '<stdin>'
@@ -87,30 +98,37 @@ for f in files:
     if not ipdl.typecheck(ast):
         print >>sys.stderr, 'Specification is not well typed.'
         sys.exit(1)
 
     if _verbosity > 2:
         log(3, '  pretty printed code:')
         ipdl.genipdl(ast, codedir)
 
-    ipdl.gencxx(ast, codedir)
+    ipdl.gencxx(filename, ast, headersdir, cppdir)
 
 allprotocols.sort()
 
 ipcmsgstart = StringIO()
 
 print >>ipcmsgstart, """
 // CODE GENERATED by ipdl.py. Do not edit.
 
+#ifndef IPCMessageStart_h
+#define IPCMessageStart_h
+
 enum IPCMessageStart {
 """
 
 for name in allprotocols:
     print >>ipcmsgstart, "  %s," % name
 
 print >>ipcmsgstart, """
   LastMsgIndex
 };
+
+COMPILE_ASSERT(LastMsgIndex <= 64, need_to_update_IPC_MESSAGE_MACRO);
+
+#endif // ifndef IPCMessageStart_h
 """
 
 ipdl.writeifmodified(ipcmsgstart.getvalue(),
-                     os.path.join(codedir, 'IPCMessageStart.h'))
+                     os.path.join(headersdir, 'IPCMessageStart.h'))
--- a/ipc/ipdl/ipdl/__init__.py
+++ b/ipc/ipdl/ipdl/__init__.py
@@ -37,39 +37,53 @@ from cStringIO import StringIO
 
 from ipdl.cgen import IPDLCodeGen
 from ipdl.lower import LowerToCxx
 from ipdl.parser import Parser
 from ipdl.type import TypeCheck
 
 from ipdl.cxx.cgen import CxxCodeGen
 
+
 def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
     '''Return an IPDL AST if parsing was successful.  Print errors to |errout|
     if it is not.'''
     return Parser().parse(specstring, os.path.abspath(filename), includedirs, errout)
 
+
 def typecheck(ast, errout=sys.stderr):
     '''Return True iff |ast| is well typed.  Print errors to |errout| if
     it is not.'''
     return TypeCheck().check(ast, errout)
 
-def gencxx(ast, outdir):
-    for hdr in LowerToCxx().lower(ast):
-        file = os.path.join(
-            outdir,
-            *([ns.name for ns in ast.protocol.namespaces] + [hdr.name]))
+
+def gencxx(ipdlfilename, ast, outheadersdir, outcppdir):
+    headers, cpps = LowerToCxx().lower(ast)
 
+    def resolveHeader(hdr):
+        return [
+            hdr, 
+            os.path.join(
+                outheadersdir,
+                *([ns.name for ns in ast.protocol.namespaces] + [hdr.name]))
+        ]
+    def resolveCpp(cpp):
+        return [ cpp, os.path.join(outcppdir, cpp.name) ]
+
+    for ast, filename in ([ resolveHeader(hdr) for hdr in headers ]
+                          + [ resolveCpp(cpp) for cpp in cpps ]):
         tempfile = StringIO()
-        CxxCodeGen(tempfile).cgen(hdr)
-        writeifmodified(tempfile.getvalue(), file)
+        CxxCodeGen(tempfile).cgen(ast)
+        writeifmodified(tempfile.getvalue(), filename)
+
 
 def genipdl(ast, outdir):
     return IPDLCodeGen().cgen(ast)
 
+
 def writeifmodified(contents, file):
     dir = os.path.dirname(file)
     os.path.exists(dir) or os.makedirs(dir)
 
     oldcontents = None
     if os.path.exists(file):
         fd = open(file, 'rb')
         oldcontents = fd.read()
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -291,33 +291,39 @@ class MessageDecl(Node):
         self.inParams += inParamsList
 
     def addOutParams(self, outParamsList):
         self.outParams += outParamsList
 
     def hasReply(self):
         return self.sendSemantics is SYNC or self.sendSemantics is RPC
 
-class TransitionStmt(Node):
-    def __init__(self, loc, state, transitions):
-        Node.__init__(self, loc)
-        self.state = state
-        self.transitions = transitions
-
 class Transition(Node):
     def __init__(self, loc, trigger, msg, toStates):
         Node.__init__(self, loc)
         self.trigger = trigger
         self.msg = msg
         self.toStates = toStates
 
     @staticmethod
     def nameToTrigger(name):
         return { 'send': SEND, 'recv': RECV, 'call': CALL, 'answer': ANSWER }[name]
 
+Transition.NULL = Transition(Loc.NONE, None, None, [ ])
+
+class TransitionStmt(Node):
+    def __init__(self, loc, state, transitions):
+        Node.__init__(self, loc)
+        self.state = state
+        self.transitions = transitions
+
+    @staticmethod
+    def makeNullStmt(state):
+        return TransitionStmt(Loc.NONE, state, [ Transition.NULL ])
+
 class SEND:
     pretty = 'send'
     @classmethod
     def __hash__(cls): return hash(cls.pretty)
     @classmethod
     def direction(cls): return OUT
 class RECV:
     pretty = 'recv'
@@ -350,30 +356,34 @@ class State(Node):
     def __hash__(self):
         return hash(repr(self))
     def __ne__(self, o):
         return not (self == o)
     def __repr__(self): return '<State %r start=%r>'% (self.name, self.start)
     def __str__(self): return '<State %s start=%s>'% (self.name, self.start)
 
 State.ANY = State(Loc.NONE, '[any]', start=True)
-State.NONE = State(Loc.NONE, '[none]', start=False)
+State.DEAD = State(Loc.NONE, '[dead]', start=False)
 
 class Param(Node):
     def __init__(self, loc, typespec, name):
         Node.__init__(self, loc)
         self.name = name
         self.typespec = typespec
 
 class TypeSpec(Node):
-    def __init__(self, loc, spec, state=None, array=0):
+    def __init__(self, loc, spec, state=None, array=0, nullable=0,
+                 myChmod=None, otherChmod=None):
         Node.__init__(self, loc)
-        self.spec = spec
-        self.state = state
-        self.array = array
+        self.spec = spec                # QualifiedId
+        self.state = state              # None or State
+        self.array = array              # bool
+        self.nullable = nullable        # bool
+        self.myChmod = myChmod          # None or string
+        self.otherChmod = otherChmod    # None or string
 
     def basename(self):
         return self.spec.baseid
 
     def isActor(self):
         return self.state is not None
 
     def __str__(self):  return str(self.spec)
--- a/ipc/ipdl/ipdl/builtin.py
+++ b/ipc/ipdl/ipdl/builtin.py
@@ -51,24 +51,38 @@ Types = (
     'uint16_t',
     'int32_t',
     'uint32_t',
     'int64_t',
     'uint64_t',
     'intptr_t',
     'uintptr_t',
 
+    # NSPR types
+    'PRBool',
+    'PRPackedBool'
+    'PRInt8',
+    'PRUint8',
+    'PRInt16',
+    'PRUint16',
+    'PRInt32',
+    'PRUint32',
+    'PRInt64',
+    'PRUint64',
+    'PRSize',
+
     # Mozilla types: "less" standard things we know how serialize/deserialize
     'nsresult',
     'nsString',
     'nsCString',
 )
 
 
 Includes = (
     'base/basictypes.h',
     'prtime.h',
     'nscore.h',
+    'IPCMessageStart.h',
     'IPC/IPCMessageUtils.h',
     'nsStringGlue.h',
     'nsTArray.h',
     'mozilla/ipc/ProtocolUtils.h',
 )
--- a/ipc/ipdl/ipdl/cxx/ast.py
+++ b/ipc/ipdl/ipdl/cxx/ast.py
@@ -72,16 +72,21 @@ class Visitor:
         tdef.fromtype.accept(self)
 
     def visitForwardDecl(self, fd):
         pass
 
     def visitDecl(self, decl):
         decl.type.accept(self)
 
+    def visitParam(self, param):
+        self.visitDecl(param)
+        if param.default is not None:
+            param.default.accept(self)
+
     def visitClass(self, cls):
         for inherit in cls.inherits:
             inherit.accept(self)
         self.visitBlock(cls)
 
     def visitInherit(self, inh):
         pass
 
@@ -310,16 +315,17 @@ of pointer types that can be be construc
   ptrconst       => T* const
   ptrptr         => T**
   ptrconstptr    => T* const*
 
 Any type, naked or pointer, can be const (const T) or ref (T&).
 """
         assert isinstance(name, str)
         assert not isinstance(const, str)
+        assert not isinstance(T, str)
 
         Node.__init__(self)
         self.name = name
         self.const = const
         self.ptr = ptr
         self.ptrconst = ptrconst
         self.ptrptr = ptrptr
         self.ptrconstptr = ptrconstptr
@@ -333,16 +339,19 @@ Any type, naked or pointer, can be const
                     ptr=self.ptr, ptrconst=self.ptrconst,
                     ptrptr=self.ptrptr, ptrconstptr=self.ptrconstptr,
                     ref=self.ref,
                     T=copy.deepcopy(self.T, memo))
 Type.BOOL = Type('bool')
 Type.INT = Type('int')
 Type.INTPTR = Type('intptr_t')
 Type.UINT32 = Type('uint32')
+Type.SIZE = Type('size_t')
+Type.VOID = Type('void')
+Type.VOIDPTR = Type('void', ptr=1)
 
 class TypeArray(Node):
     def __init__(self, basetype, nmemb):
         '''the type |basetype DECLNAME[nmemb]|.  |nmemb| is an Expr'''
         self.basetype = basetype
         self.nmemb = nmemb
     def __deepcopy__(self, memo):
         return TypeArray(deepcopy(self.basetype, memo), nmemb)
@@ -390,16 +399,24 @@ class Decl(Node):
         assert isinstance(name, str)
 
         Node.__init__(self)
         self.type = type
         self.name = name
     def __deepcopy__(self, memo):
         return Decl(copy.deepcopy(self.type, memo), self.name)
 
+class Param(Decl):
+    def __init__(self, type, name, default=None):
+        Decl.__init__(self, type, name)
+        self.default = default
+    def __deepcopy__(self, memo):
+        return Param(copy.deepcopy(self.type, memo), self.name,
+                     copy.deepcopy(self.default, memo))
+
 ##------------------------------
 # class stuff
 class Class(Block):
     def __init__(self, name, inherits=[ ],
                  interface=0, abstract=0, final=0,
                  specializes=None, struct=0):
         assert not (interface and abstract)
         assert not (abstract and final)
@@ -431,37 +448,38 @@ class MethodDecl(Node):
     def __init__(self, name, params=[ ], ret=Type('void'),
                  virtual=0, const=0, pure=0, static=0,
                  typeop=None):
         assert not (virtual and static)
         assert not pure or virtual      # pure => virtual
         assert not (static and typeop)
         assert not (name and typeop)
         assert name is None or isinstance(name, str)
+        assert not isinstance(ret, list)
 
         if typeop is not None:
             ret = None
 
         Node.__init__(self)
         self.name = name
         self.params = params            # [ Param ]
         self.ret = ret                  # Type or None
         self.virtual = virtual          # bool
         self.const = const              # bool
         self.pure = pure                # bool
         self.static = static            # bool
         self.typeop = typeop            # Type or None
 
     def __deepcopy__(self, memo):
-        return MethodDecl(self.name,
-                          copy.deepcopy(self.params, memo),
-                          copy.deepcopy(self.ret, memo),
-                          self.virtual,
-                          self.const,
-                          self.pure)
+        return MethodDecl(
+            self.name,
+            copy.deepcopy(self.params, memo),
+            copy.deepcopy(self.ret, memo),
+            self.virtual, self.const, self.pure, self.static,
+            copy.deepcopy(self.typeop, memo))
 
 class MethodDefn(Block):
     def __init__(self, decl):
         Block.__init__(self)
         self.decl = decl
 
 class ConstructorDecl(MethodDecl):
     def __init__(self, name, params=[ ], explicit=0):
@@ -477,16 +495,21 @@ class ConstructorDefn(MethodDefn):
     def __init__(self, decl, memberinits=[ ]):
         MethodDefn.__init__(self, decl)
         self.memberinits = memberinits
 
 class DestructorDecl(MethodDecl):
     def __init__(self, name, virtual=0):
         MethodDecl.__init__(self, name, params=[ ], ret=None,
                             virtual=virtual)
+
+    def __deepcopy__(self, memo):
+        return DestructorDecl(self.name, self.virtual)
+
+        
 class DestructorDefn(MethodDefn):
     def __init__(self, decl):  MethodDefn.__init__(self, decl)
 
 ##------------------------------
 # expressions
 class ExprVar(Node):
     def __init__(self, name):
         assert isinstance(name, str)
--- a/ipc/ipdl/ipdl/cxx/cgen.py
+++ b/ipc/ipdl/ipdl/cxx/cgen.py
@@ -131,16 +131,22 @@ class CxxCodeGen(CodePrinter, Visitor):
         if d.name:
             self.write(' '+ d.name)
 
         if isinstance(d.type, TypeArray):
             self.write('[')
             d.type.nmemb.accept(self)
             self.write(']')
 
+    def visitParam(self, p):
+        self.visitDecl(p)
+        if p.default is not None:
+            self.write(' = ')
+            p.default.accept(self)
+
     def visitClass(self, c):
         if c.specializes is not None:
             self.printdentln('template<>')
         
         if c.struct:
             self.printdent('struct')
         else:
             self.printdent('class')
@@ -191,17 +197,18 @@ class CxxCodeGen(CodePrinter, Visitor):
         assert not (md.static and md.virtual)
 
         if md.static:
             self.write('static ')
         if md.virtual:
             self.write('virtual ')
         if md.ret:
             md.ret.accept(self)
-            self.write(' ')
+            self.println()
+            self.printdent()
         if md.typeop is not None:
             self.write('operator ')
             md.typeop.accept(self)
         else:
             self.write(md.name)
 
         self.write('(')
         self.writeDeclList(md.params)
@@ -252,17 +259,22 @@ class CxxCodeGen(CodePrinter, Visitor):
 
         self.dedent()
         self.printdentln('}')
 
 
     def visitDestructorDecl(self, dd):
         if dd.virtual:
             self.write('virtual ')
-        self.write('~'+ dd.name +'()')
+
+        # hack alert
+        parts = dd.name.split('::')
+        parts[-1] = '~'+ parts[-1]
+
+        self.write('::'.join(parts) +'()')
 
     def visitDestructorDefn(self, dd):
         self.printdent()
         dd.decl.accept(self)
         self.println()
 
         self.printdentln('{')
         self.indent()
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -43,43 +43,54 @@ from ipdl.type import TypeVisitor
 # this code will remain off until the chromium base lib is replaced
 EMIT_LOGGING_CODE = ('win32' == sys.platform)
 
 ##-----------------------------------------------------------------------------
 ## "Public" interface to lowering
 ##
 class LowerToCxx:
     def lower(self, tu):
-        '''returns a list of File representing the lowered form of |tu|'''
+        '''returns |[ header: File ], [ cpp : File ]| representing the
+lowered form of |tu|'''
         # annotate the AST with IPDL/C++ IR-type stuff used later
         tu.accept(_DecorateWithCxxStuff())
 
         pname = tu.protocol.name
 
         pheader = File(pname +'.h')
         _GenerateProtocolHeader().lower(tu, pheader)
 
-        parentheader = File(pname +'Parent.h')
-        _GenerateProtocolParentHeader().lower(tu, pname+'Parent', parentheader)
-
-        childheader = File(pname +'Child.h')
-        _GenerateProtocolChildHeader().lower(tu, pname+'Child', childheader)
-
-        return pheader, parentheader, childheader
+        parentheader, parentcpp = File(pname +'Parent.h'), File(pname +'Parent.cpp')
+        _GenerateProtocolParentCode().lower(
+            tu, pname+'Parent', parentheader, parentcpp)
+
+        childheader, childcpp = File(pname +'Child.h'), File(pname +'Child.cpp')
+        _GenerateProtocolChildCode().lower(
+            tu, pname+'Child', childheader, childcpp)
+
+        return [ pheader, parentheader, childheader ], [ parentcpp, childcpp ]
 
 
 ##-----------------------------------------------------------------------------
 ## Helper code
 ##
+
+_NULL_ACTOR_ID = ExprLiteral.ZERO
+_FREED_ACTOR_ID = ExprLiteral.ONE
+
 class _struct: pass
 
-def _protocolHeaderBaseFilename(p):
+def _protocolHeaderName(p, side=''):
+    if side: side = side.title()
+    base = p.name + side
+
+    
     pfx = '/'.join([ ns.name for ns in p.namespaces ])
-    if pfx: return pfx +'/'+ p.name
-    else:   return p.name
+    if pfx: return pfx +'/'+ base
+    else:   return base
 
 def _includeGuardMacroName(headerfile):
     return re.sub(r'[./]', '_', headerfile.name)
 
 def _includeGuardStart(headerfile):
     guard = _includeGuardMacroName(headerfile)
     return [ CppDirective('ifndef', guard),
              CppDirective('define', guard)  ]
@@ -92,52 +103,151 @@ def _actorName(pname, side):
     """|pname| is the protocol name. |side| is 'Parent' or 'Child'."""
     tag = side
     if not tag[0].isupper():  tag = side.title()
     return pname + tag
 
 def _actorIdType():
     return Type('int32')
 
-def _safeActorId(actor):
-    return ExprConditional(actor, _actorId(actor), ExprLiteral.ZERO)
-
 def _actorId(actor):
     return ExprSelect(actor, '->', 'mId')
 
 def _actorHId(actorhandle):
     return ExprSelect(actorhandle, '.', 'mId')
 
 def _actorChannel(actor):
     return ExprSelect(actor, '->', 'mChannel')
 
 def _actorManager(actor):
     return ExprSelect(actor, '->', 'mManager')
 
-def _safeLookupActor(idexpr, actortype):
-    return ExprCast(
-        ExprConditional(
-            ExprBinary(idexpr, '==', ExprLiteral.ZERO),
-            ExprLiteral.NULL,
-            _lookupListener(idexpr)),
-        actortype,
-        reinterpret=1)
-
-def _safeLookupActorHandle(handle, actortype):
-    return _safeLookupActor(_actorHId(handle), actortype)
-
-def _lookupActor(idexpr, actortype):
-    return ExprCast(idexpr, actortype, reinterpret=1)
-
-def _lookupActorHandle(handle, actortype):
-    return _lookupActor(_actorHId(handle), actortype)
+def _getActorId(actorexpr, outid, actortype, errfn):
+    # if (!actorexpr)
+    #   #ifdef NULLABLE
+    #     abort()
+    #   #else
+    #     outid = 0;
+    #   #endif
+    # else if (id == FREED)
+    #     abort()
+    # else
+    #     outid = _actorId(actorexpr)
+    ifnull = StmtIf(ExprNot(actorexpr))
+    if not actortype.nullable:
+        ifnull.addifstmts(
+            errfn("NULL actor value passed to non-nullable param"))
+    else:
+        ifnull.addifstmt(StmtExpr(ExprAssn(outid, ExprLiteral.ZERO)))
+
+    iffreed = StmtIf(ExprBinary(_FREED_ACTOR_ID, '==', _actorId(actorexpr)))
+    ifnull.addelsestmt(iffreed)
+
+    # this is always a hard-abort, because it means that some C++ code
+    # has a live pointer to a freed actor, so we're playing Russian
+    # roulette with invalid memory
+    iffreed.addifstmt(_runtimeAbort("actor has been delete'd"))
+    iffreed.addelsestmt(StmtExpr(ExprAssn(outid, _actorId(actorexpr))))
+
+    return ifnull
+
+
+def _lookupActor(idexpr, outactor, actortype, cxxactortype, errfn):
+    # if (NULLID == idexpr)
+    #   #ifndef NULLABLE
+    #     abort()
+    #   #else
+    #     actor = 0;
+    #   #endif
+    # else if (FREEDID == idexpr)
+    #     abort()
+    # else {
+    #     actor = (cxxactortype*)_lookupListener(idexpr);
+    #     // bad actor ID.  always an error
+    #     if (!actor) abort();
+    # }
+    ifzero = StmtIf(ExprBinary(_NULL_ACTOR_ID, '==', idexpr))
+    if not actortype.nullable:
+        ifzero.addifstmts(errfn("NULL actor ID for non-nullable param"))
+    else:
+        ifzero.addifstmt(StmtExpr(ExprAssn(outactor, ExprLiteral.NULL)))
+
+    iffreed = StmtIf(ExprBinary(_FREED_ACTOR_ID, '==', idexpr))
+    ifzero.addelsestmt(iffreed)
+
+    iffreed.addifstmts(errfn("received FREED actor ID, evidence that the other side is malfunctioning"))
+    iffreed.addelsestmt(
+        StmtExpr(ExprAssn(
+            outactor,
+            ExprCast(_lookupListener(idexpr), cxxactortype, static=1))))
+
+    ifnotactor = StmtIf(ExprNot(outactor))
+    ifnotactor.addifstmts(errfn("invalid actor ID, evidence that the other side is malfunctioning"))
+    iffreed.addelsestmt(ifnotactor)
+
+    return ifzero
+
+
+def _lookupActorHandle(handle, outactor, actortype, cxxactortype, errfn):
+    return _lookupActor(_actorHId(handle), outactor, actortype, cxxactortype,
+                        errfn)
 
 def _lookupListener(idexpr):
     return ExprCall(ExprVar('Lookup'), args=[ idexpr ])
 
+def _shmemType(ptr=0):
+    return Type('Shmem', ptr=ptr)
+
+def _rawShmemType(ptr=0):
+    return Type('Shmem::SharedMemory', ptr=ptr)
+
+def _shmemIdType():
+    return Type('Shmem::id_t')
+
+def _shmemHandleType():
+    return Type('Shmem::SharedMemoryHandle')
+
+def _shmemBackstagePass():
+    return ExprCall(ExprVar(
+        'Shmem::IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead'))
+
+def _shmemCtor(rawmem, idexpr):
+    return ExprCall(ExprVar('Shmem'),
+                    args=[ _shmemBackstagePass(), rawmem, idexpr ])
+
+def _shmemId(shmemexpr):
+    return ExprCall(ExprSelect(shmemexpr, '.', 'Id'),
+                    args=[ _shmemBackstagePass() ])
+
+def _shmemAlloc(size):
+    # starts out UNprotected
+    return ExprCall(ExprVar('Shmem::Alloc'),
+                    args=[ _shmemBackstagePass(), size ])
+
+def _shmemOpenExisting(size, handle):
+    # starts out protected
+    return ExprCall(ExprVar('Shmem::OpenExisting'),
+                    args=[ _shmemBackstagePass(),
+                           # true => protect
+                           handle, size, ExprLiteral.TRUE ])
+
+def _shmemForget(shmemexpr):
+    return ExprCall(ExprSelect(shmemexpr, '.', 'forget'),
+                    args=[ _shmemBackstagePass() ])
+
+def _shmemRevokeRights(shmemexpr):
+    return ExprCall(ExprSelect(shmemexpr, '.', 'RevokeRights'),
+                    args=[ _shmemBackstagePass() ])
+
+def _shmemCreatedMsgVar():
+    return ExprVar('mozilla::ipc::__internal__ipdl__ShmemCreated')
+
+def _lookupShmem(idexpr):
+    return ExprCall(ExprVar('LookupShmem'), args=[ idexpr ])
+
 def _makeForwardDecl(ptype, side):
     clsname = _actorName(ptype.qname.baseid, side)
 
     fd = ForwardDecl(clsname, cls=1)
     if 0 == len(ptype.qname.quals):
         return fd
 
     outerns = Namespace(ptype.qname.quals[0])
@@ -200,36 +310,126 @@ def _abortIfFalse(cond, msg):
     return StmtExpr(ExprCall(
         ExprVar('NS_ABORT_IF_FALSE'),
         [ cond, ExprLiteral.String(msg) ]))
 
 def _runtimeAbort(msg):
     return StmtExpr(ExprCall(ExprVar('NS_RUNTIMEABORT'),
                                      [ ExprLiteral.String(msg) ]))
 
-def _cxxArrayType(basetype):
-    return Type('nsTArray', T=basetype)
+def _autoptr(T):
+    return Type('nsAutoPtr', T=T)
+
+def _autoptrForget(expr):
+    return ExprCall(ExprSelect(expr, '.', 'forget'))
+
+def _cxxArrayType(basetype, const=0, ref=0):
+    return Type('nsTArray', T=basetype, const=const, ref=ref)
 
 def _callCxxArrayLength(arr):
     return ExprCall(ExprSelect(arr, '.', 'Length'))
 
 def _callCxxArraySetLength(arr, lenexpr):
     return ExprCall(ExprSelect(arr, '.', 'SetLength'),
                     args=[ lenexpr ])
 
+def _callCxxArrayInsertSorted(arr, elt):
+    return ExprCall(ExprSelect(arr, '.', 'InsertElementSorted'),
+                    args=[ elt ])
+
+def _callCxxArrayRemoveSorted(arr, elt):
+    return ExprCall(ExprSelect(arr, '.', 'RemoveElementSorted'),
+                    args=[ elt ])
+
+def _callCxxArrayClear(arr):
+    return ExprCall(ExprSelect(arr, '.', 'Clear'))
+
 def _otherSide(side):
     if side == 'child':  return 'parent'
     if side == 'parent':  return 'child'
     assert 0
 
 def _ifLogging(stmts):
     iflogging = StmtIf(ExprCall(ExprVar('mozilla::ipc::LoggingEnabled')))
     iflogging.addifstmts(stmts)
     return iflogging
 
+# XXX we need to remove these and install proper error handling
+def _printErrorMessage(msg):
+    if isinstance(msg, str):
+        msg = ExprLiteral.String(msg)
+    return StmtExpr(
+        ExprCall(ExprVar('NS_ERROR'), args=[ msg ]))
+
+def _fatalError(msg):
+    return StmtExpr(
+        ExprCall(ExprVar('FatalError'), args=[ ExprLiteral.String(msg) ]))
+
+def _killProcess(pid):
+    return ExprCall(
+        ExprVar('base::KillProcess'),
+        args=[ pid,
+               # XXX this is meaningless on POSIX
+               ExprVar('base::PROCESS_END_KILLED_BY_USER'),
+               ExprLiteral.FALSE ])
+
+# Results that IPDL-generated code returns back to *Channel code.
+# Users never see these
+class _Result:
+    @staticmethod
+    def Type():
+        return Type('Result')
+
+    Processed = ExprVar('MsgProcessed')
+    NotKnown = ExprVar('MsgNotKnown')
+    NotAllowed = ExprVar('MsgNotAllowed')
+    PayloadError = ExprVar('MsgPayloadError')
+    RouteError = ExprVar('MsgRouteError')
+    ValuError = ExprVar('MsgValueError') # [sic]
+
+# these |errfn*| are functions that generate code to be executed on an
+# error, such as "bad actor ID".  each is given a Python string
+# containing a description of the error
+
+# used in user-facing Send*() methods
+def errfnSend(msg, errcode=ExprLiteral.FALSE):
+    return [
+        _fatalError(msg),
+        StmtReturn(errcode)
+    ]
+
+def errfnSendCtor(msg):  return errfnSend(msg, errcode=ExprLiteral.NULL)
+
+# TODO should this error handling be strengthened for dtors?
+def errfnSendDtor(msg):
+    return [
+        _printErrorMessage(msg),
+        StmtReturn(ExprLiteral.FALSE)
+    ]
+
+# used in |OnMessage*()| handlers that hand in-messages off to Recv*()
+# interface methods
+def errfnRecv(msg, errcode=_Result.ValuError):
+    return [
+        _fatalError(msg),
+        StmtReturn(errcode)
+    ]
+
+def _destroyMethod():
+    return ExprVar('ActorDestroy')
+
+class _DestroyReason:
+    @staticmethod
+    def Type():  return Type('ActorDestroyReason')
+
+    Deletion = ExprVar('Deletion')
+    AncestorDeletion = ExprVar('AncestorDeletion')
+    NormalShutdown = ExprVar('NormalShutdown')
+    AbnormalShutdown = ExprVar('AbnormalShutdown')
+
 ##-----------------------------------------------------------------------------
 ## Intermediate representation (IR) nodes used during lowering
 
 class _ConvertToCxxType(TypeVisitor):
     def __init__(self, side):  self.side = side
     
     def visitBuiltinCxxType(self, t):
         return Type(t.name())
@@ -242,21 +442,29 @@ class _ConvertToCxxType(TypeVisitor):
 
     def visitUnionType(self, u):
         return Type(u.name())
 
     def visitArrayType(self, a):
         basecxxtype = a.basetype.accept(self)
         return _cxxArrayType(basecxxtype)
 
+    def visitShmemType(self, s):
+        return Type(s.name())
+
     def visitProtocolType(self, p): assert 0
     def visitMessageType(self, m): assert 0
     def visitVoidType(self, v): assert 0
     def visitStateType(self, st): assert 0
 
+def _allocMethod(ptype):
+    return ExprVar('Alloc'+ ptype.name())
+
+def _deallocMethod(ptype):
+    return ExprVar('Dealloc'+ ptype.name())
 
 class _ConvertToSerializableCxxType(TypeVisitor):
     def visitBuiltinCxxType(self, t):
         return Type(t.name())
 
     def visitImportedCxxType(self, t):
         return Type(t.name())
 
@@ -265,16 +473,19 @@ class _ConvertToSerializableCxxType(Type
 
     def visitUnionType(self, u):
         return Type(u.name())
 
     def visitArrayType(self, a):
         basecxxtype = a.basetype.accept(self)
         return _cxxArrayType(basecxxtype)
 
+    def visitShmemType(self, s):
+        return Type(s.name())
+
     def visitProtocolType(self, p): assert 0
     def visitMessageType(self, m): assert 0
     def visitVoidType(self, v): assert 0
     def visitStateType(self): assert 0
 
 ##
 ## A _HybridDecl straddles IPDL and C++ decls.  It knows which C++
 ## types correspond to which IPDL types, and it also knows how
@@ -313,16 +524,19 @@ necessarily a C++ reference."""
         return t
 
     def constRefType(self, side):
         """Return this decl's C++ type as a const, 'reference' type."""
         t = self.bareType(side)
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
             t.const = 1                 # const Actor*
             return t
+        if self.ipdltype.isIPDL() and self.ipdltype.isShmem():
+            t.ref = 1
+            return t
         t.const = 1
         t.ref = 1
         return t
 
     def ptrToType(self, side):
         t = self.bareType(side)
         if self.ipdltype.isIPDL() and self.ipdltype.isActor():
             t.ptr = 0
@@ -371,69 +585,70 @@ necessarily a C++ reference."""
     def outPipeType(self):
         """Return this decl's serializable C++ type with outparam semantics"""
         t = self.barePipeType()
         t.ptr = 1
         return t
 
     # the biggies: serialization/deserialization
 
-    def serialize(self, expr, side):
-        if not ipdl.type.hasactor(self.ipdltype):
+    def serialize(self, expr, side, errfn):
+        if not self.speciallySerialized(self.ipdltype):
             return expr, [ ]
         # XXX could use TypeVisitor, but it doesn't feel right here
-        _, sexpr, stmts = self._serialize(self.ipdltype, expr, side)
+        _, sexpr, stmts = self._serialize(self.ipdltype, expr, side, errfn)
         return sexpr, stmts
 
-    def _serialize(self, etype, expr, side):
+    def _serialize(self, etype, expr, side, errfn):
         '''Serialize |expr| of type |etype|, which has some actor type
 buried in it.  Return |pipetype, serializedExpr, serializationStmts|.'''
         assert etype.isIPDL()           # only IPDL types may contain actors
 
         if etype.isActor():
-            return self._serializeActor(etype, expr)
+            return self._serializeActor(etype, expr, errfn)
         elif etype.isArray():
-            return self._serializeArray(etype, expr, side)
+            return self._serializeArray(etype, expr, side, errfn)
         elif etype.isUnion():
-            return self._serializeUnion(etype, expr, side)
+            return self._serializeUnion(etype, expr, side, errfn)
+        elif etype.isShmem() or etype.isChmod():
+            return self._serializeShmem(etype, expr, side, errfn)
         else: assert 0
 
-
-    def _serializeActor(self, actortype, expr):
+    def speciallySerialized(self, type):
+        return ipdl.type.hasactor(type) or ipdl.type.hasshmem(type)
+
+    def _serializeActor(self, actortype, expr, errfn):
         actorhandlevar = ExprVar(self._nextuid('handle'))
         pipetype = Type('ActorHandle')
-        # TODO nullability
+
         stmts = [
             Whitespace('// serializing actor type\n', indent=1),
             StmtDecl(Decl(pipetype, actorhandlevar.name)),
-            StmtExpr(ExprAssn(
-                _actorHId(actorhandlevar),
-                ExprConditional(ExprNot(expr),
-                                ExprLiteral.NULL, _actorId(expr)))),
+            _getActorId(expr, _actorHId(actorhandlevar), actortype, errfn),
             Whitespace.NL
         ]
         return pipetype, actorhandlevar, stmts
 
 
-    def _serializeArray(self, arraytype, expr, side):
+    def _serializeArray(self, arraytype, expr, side, errfn):
         newarrayvar = ExprVar(self._nextuid('serArray'))
         lenvar = ExprVar(self._nextuid('length'))
         ivar = ExprVar(self._nextuid('i'))
 
         # FIXME hacky init of |i|
         forloop = StmtFor(init=ExprAssn(Decl(Type.UINT32, ivar.name),
                                         ExprLiteral.ZERO),
                           cond=ExprBinary(ivar, '<', lenvar),
                           update=ExprPrefixUnop(ivar, '++'))
 
         ithNewElt = ExprIndex(newarrayvar, ivar)
         ithOldElt = ExprIndex(expr, ivar)
 
         eltType, serializedExpr, forbodystmts = self._serialize(
-            arraytype.basetype, ithOldElt, side)
+            arraytype.basetype, ithOldElt, side, errfn)
 
         forloop.addstmts(forbodystmts)
         forloop.addstmt(StmtExpr(ExprAssn(ithNewElt, serializedExpr)))
 
         pipetype = _cxxArrayType(eltType)
         stmts = [
             Whitespace('// serializing array type\n', indent=1),
             StmtDecl(Decl(Type.UINT32, lenvar.name),
@@ -441,22 +656,27 @@ buried in it.  Return |pipetype, seriali
             StmtDecl(Decl(pipetype, newarrayvar.name)),
             StmtExpr(_callCxxArraySetLength(newarrayvar, lenvar)),
             forloop,
             Whitespace.NL
         ]
         return pipetype, newarrayvar, stmts
 
 
-    def _serializeUnion(self, uniontype, expr, side):
-        def insaneActorCast(actor, actortype):
-            return ExprCast(
-                ExprCast(_safeActorId(actor), Type.INTPTR, static=1),
-                actortype,
-                reinterpret=1)
+    def _serializeUnion(self, uniontype, expr, side, errfn):
+        def insaneActorCast(actor, actortype, cxxactortype):
+            idvar = ExprVar(self._nextuid('actorid'))
+            return (
+                [ StmtDecl(Decl(_actorIdType(), idvar.name)),
+                  _getActorId(actor, idvar, actortype, errfn),
+                ],
+                ExprCast(ExprCast(idvar, Type.INTPTR, static=1),
+                         cxxactortype,
+                         reinterpret=1)
+                )
 
         pipetype = Type(uniontype.name())
         serunionvar = ExprVar(self._nextuid('serUnion'))
         ud = uniontype._ud
 
         switch = StmtSwitch(ud.callType(expr))
         for c in ud.components:
             ct = c.ipdltype
@@ -469,52 +689,60 @@ buried in it.  Return |pipetype, seriali
             case = StmtBlock()
             getvalue = ExprCall(ExprSelect(expr, '.', c.getConstTypeName()))
 
             if ct.isActor():
                 if c.side != side:
                     case.addstmt(_runtimeAbort('wrong side!'))
                 else:
                     # may god have mercy on our souls
-                    case.addstmt(StmtExpr(ExprAssn(
-                        serunionvar,
-                        insaneActorCast(getvalue, c.bareType()))))
+                    getidstmts, castexpr = insaneActorCast(
+                        getvalue, ct, c.bareType())
+                    case.addstmts(
+                        getidstmts
+                        + [ StmtExpr(ExprAssn(serunionvar, castexpr)) ])
+
             elif ct.isArray() and ct.basetype.isActor():
                 if c.side != side:
                     case.addstmt(_runtimeAbort('wrong side!'))
                 else:
                     # no more apologies
-                    actortype = ct.basetype.accept(_ConvertToCxxType(c.side))
+                    cxxactortype = ct.basetype.accept(
+                        _ConvertToCxxType(c.side))
                     lenvar = ExprVar(self._nextuid('len'))
                     newarrvar = ExprVar(self._nextuid('idarray'))
 
                     ivar = ExprVar(self._nextuid('i'))
                     ithOldElt = ExprIndex(getvalue, ivar)
                     ithNewElt = ExprIndex(newarrvar, ivar)
                     loop = StmtFor(init=ExprAssn(Decl(Type.UINT32, ivar.name),
                                           ExprLiteral.ZERO),
                                    cond=ExprBinary(ivar, '<', lenvar),
                                    update=ExprPrefixUnop(ivar, '++'))
-                    loop.addstmt(StmtExpr(ExprAssn(
-                        ithNewElt,
-                        insaneActorCast(ithOldElt, actortype))))
+                    # loop body
+                    getidstmts, castexpr = insaneActorCast(
+                        ithOldElt, ct.basetype, cxxactortype)
+                    loop.addstmts(
+                        getidstmts
+                        + [ StmtExpr(ExprAssn(ithNewElt, castexpr)) ])
 
                     case.addstmts([
                         StmtDecl(Decl(Type.UINT32, lenvar.name),
                                  init=_callCxxArrayLength(getvalue)),
                         StmtDecl(Decl(c.bareType(), newarrvar.name)),
                         StmtExpr(_callCxxArraySetLength(newarrvar, lenvar)),
                         Whitespace.NL,
                         loop,
                         StmtExpr(ExprAssn(serunionvar, newarrvar))
                     ])
             else:
                 # NB: here we rely on the serialized expression
                 # coming back with the same type
-                _, newexpr, sstmts = self._serialize(ct, getvalue, side)
+                _, newexpr, sstmts = self._serialize(ct, getvalue, side,
+                                                     errfn)
                 case.addstmts(sstmts
                               + [ Whitespace.NL,
                                   StmtExpr(ExprAssn(serunionvar, newexpr)) ])
 
             case.addstmt(StmtBreak())
             switch.addcase(CaseLabel(c.pqEnum()), case)
 
         switch.addcase(
@@ -526,67 +754,87 @@ buried in it.  Return |pipetype, seriali
             Whitespace('// serializing union type\n', indent=1),
             StmtDecl(Decl(pipetype, serunionvar.name)),
             Whitespace.NL,
             switch
         ]
         return pipetype, serunionvar, stmts
 
 
+    def _serializeShmem(self, shmemtype, expr, side, errfn):
+        pipetype = _shmemType()
+        pipevar = ExprVar(self._nextuid('serShmem'))
+        stmts = [
+            Whitespace('// serializing shmem type\n', indent=1),
+            StmtDecl(Decl(_shmemType(), pipevar.name),
+                     init=ExprCall(pipetype, args=[ expr ])),
+            StmtExpr(_shmemRevokeRights(expr)),
+            StmtExpr(_shmemForget(expr)),
+        ]
+        return pipetype, pipevar, stmts
+
+
     def makePipeDecls(self, toExpr):
         if not ipdl.type.hasactor(self.ipdltype):
             return 0, toExpr, [ ]
         tempvar = ExprVar(self._nextuid('deTemp'))
         return (1,
                 tempvar,
                 [ StmtDecl(Decl(self.barePipeType(), tempvar.name)) ])
 
     def makeDeserializedDecls(self, side):
         return self.var(), [ StmtDecl(Decl(self.bareType(side),
                                            self.var().name)) ]
 
-    def deserialize(self, expr, side, sems):
+    def speciallyDeserialized(self, type):
+        return ipdl.type.hasactor(type) or ipdl.type.hasshmem(type)
+
+    def deserialize(self, expr, side, sems, errfn):
         """|expr| is a pointer the return type."""
-        if not ipdl.type.hasactor(self.ipdltype):
+        if not self.speciallyDeserialized(self.ipdltype):
             return [ ]
         if sems == 'in':
             toexpr = self.var()
         elif sems == 'out':
             toexpr = ExprDeref(self.var())
         else: assert 0
-        _, stmts = self._deserialize(expr, self.ipdltype, toexpr, side)
+        _, stmts = self._deserialize(
+            expr, self.ipdltype, toexpr, side, errfn)
         return stmts
 
-    def _deserialize(self, pipeExpr, targetType, targetExpr, side):
-        if not ipdl.type.hasactor(targetType):
+    def _deserialize(self, pipeExpr, targetType, targetExpr, side, errfn):
+        if not self.speciallyDeserialized(targetType):
             return targetType, [ ]
         elif targetType.isActor():
             return self._deserializeActor(
-                pipeExpr, targetType, targetExpr, side)
+                pipeExpr, targetType, targetExpr, side, errfn)
         elif targetType.isArray():
             return self._deserializeArray(
-                pipeExpr, targetType, targetExpr, side)
+                pipeExpr, targetType, targetExpr, side, errfn)
         elif targetType.isUnion():
             return self._deserializeUnion(
-                pipeExpr, targetType, targetExpr, side)
+                pipeExpr, targetType, targetExpr, side, errfn)
+        elif targetType.isShmem():
+            return self._deserializeShmem(
+                pipeExpr, targetType, targetExpr, side, errfn)
         else: assert 0
 
-    def _deserializeActor(self, actorhandle, actortype, outactor, side):
+    def _deserializeActor(self, actorhandle, actortype, outactor, side,
+                          errfn):
         cxxtype = actortype.accept(_ConvertToCxxType(side))
         return (
             cxxtype,
-            [
-                Whitespace('// deserializing actor type\n', indent=1),
-                StmtExpr(ExprAssn(
-                    outactor,
-                    _safeLookupActorHandle(actorhandle, cxxtype)))
+            [ Whitespace('// deserializing actor type\n', indent=1),
+              _lookupActorHandle(actorhandle, outactor, actortype, cxxtype,
+                                 errfn)
             ])
 
 
-    def _deserializeArray(self, pipearray, arraytype, outarray, side):
+    def _deserializeArray(self, pipearray, arraytype, outarray, side,
+                          errfn):
         cxxArrayType = arraytype.accept(_ConvertToCxxType(side))
         lenvar = ExprVar(self._nextuid('length'))
 
         stmts = [
             Whitespace('// deserializing array type\n', indent=1),
             StmtDecl(Decl(Type.UINT32, lenvar.name),
                      _callCxxArrayLength(pipearray)),
             StmtExpr(ExprCall(ExprSelect(outarray, '.', 'SetLength'),
@@ -597,96 +845,99 @@ buried in it.  Return |pipetype, seriali
         forloop = StmtFor(init=ExprAssn(Decl(Type.UINT32, ivar.name),
                                         ExprLiteral.ZERO),
                           cond=ExprBinary(ivar, '<', lenvar),
                           update=ExprPrefixUnop(ivar, '++'))       
         ithNewElt = ExprIndex(outarray, ivar)
         ithOldElt = ExprIndex(pipearray, ivar)
 
         outelttype, forstmts = self._deserialize(
-            ithOldElt, arraytype.basetype, ithNewElt, side)
+            ithOldElt, arraytype.basetype, ithNewElt, side, errfn)
         forloop.addstmts(forstmts)
 
         stmts.append(forloop)
 
         return cxxArrayType, stmts
 
 
-    def _deserializeUnion(self, pipeunion, uniontype, outunion, side):
+    def _deserializeUnion(self, pipeunion, uniontype, outunion, side,
+                          errfn):
         def actorIdCast(expr):
             return ExprCast(
                 ExprCast(expr, Type.INTPTR, reinterpret=1),
                 _actorIdType(),
                 static=1)
 
         cxxUnionType = Type(uniontype.name())
         ud = uniontype._ud
 
         switch = StmtSwitch(ud.callType(pipeunion))
         for c in ud.components:
             ct = c.ipdltype
-            if not ipdl.type.hasactor(ct):
+            if not self.speciallyDeserialized(ct):
                 continue
             assert ct.isIPDL()
 
             # like in _serializeUnion, we special-case actor's and
             # actor[]'s.  we look up the actors that correspond to the
             # actor ID's we, sigh, packed into the actor pointers
             case = StmtBlock()
             getvalue = ExprCall(ExprSelect(pipeunion, '.', c.getTypeName()))
 
             if ct.isActor():
                 # ParamTraits<union>::Read() magically flips the side on
                 # our behalf
                 if c.side != side:
                     case.addstmt(_runtimeAbort('wrong side!'))
                 else:
                     idvar = ExprVar(self._nextuid('id'))
+                    outactorvar = ExprVar(self._nextuid('actor'))
+                    actorcxxtype = c.bareType()
                     case.addstmts([
                         StmtDecl(Decl(_actorIdType(), idvar.name),
                                  actorIdCast(getvalue)),
-                        StmtExpr(ExprAssn(
-                            outunion,
-                            _safeLookupActor(idvar, c.bareType())))
+                        StmtDecl(Decl(actorcxxtype, outactorvar.name)),
+                        _lookupActor(idvar, outactorvar, ct, actorcxxtype,
+                                     errfn),
+                        StmtExpr(ExprAssn(outunion, outactorvar))
                     ])
             elif ct.isArray() and ct.basetype.isActor():
                 if c.side != side:
                     case.addstmt(_runtimeAbort('wrong side!'))
                 else:
                     idvar = ExprVar(self._nextuid('id'))
                     arrvar = ExprVar(self._nextuid('arr'))
                     ivar = ExprVar(self._nextuid('i'))
                     ithElt = ExprIndex(arrvar, ivar)
+                    actortype = ct.basetype
+                    actorcxxtype = ct.basetype.accept(_ConvertToCxxType(side))
 
                     loop = StmtFor(
                         init=ExprAssn(Decl(Type.UINT32, ivar.name),
                                       ExprLiteral.ZERO),
                         cond=ExprBinary(ivar, '<',
                                         _callCxxArrayLength(arrvar)),
                         update=ExprPrefixUnop(ivar, '++'))
                     loop.addstmts([
                         StmtDecl(Decl(_actorIdType(), idvar.name),
                                  actorIdCast(ithElt)),
-                        StmtExpr(ExprAssn(
-                            ithElt,
-                            _safeLookupActor(
-                                idvar,
-                                ct.basetype.accept(_ConvertToCxxType(side)))))
+                        _lookupActor(idvar, ithElt, actortype, actorcxxtype,
+                                     errfn),
                     ])
                 
                     case.addstmts([
                         StmtDecl(Decl(c.refType(), arrvar.name),
                                  getvalue),
                         loop,
                         StmtExpr(ExprAssn(outunion, arrvar))
                     ])
             else:
                 tempvar = ExprVar('tempUnionElt')
                 elttype, dstmts = self._deserialize(
-                    getvalue, ct, tempvar, side)
+                    getvalue, ct, tempvar, side, errfn)
                 case.addstmts(
                     [ StmtDecl(Decl(elttype, tempvar.name)),
                       Whitespace.NL ]
                     + dstmts
                     + [ Whitespace.NL,
                         StmtExpr(ExprAssn(outunion, tempvar)) ])
 
             case.addstmt(StmtBreak())
@@ -700,16 +951,40 @@ buried in it.  Return |pipetype, seriali
         stmts = [
             Whitespace('// deserializing union type\n', indent=1),
             switch
         ]
 
         return cxxUnionType, stmts
 
 
+    def _deserializeShmem(self, pipeshmem, shmemtype, outshmem, side,
+                          errfn):
+        # Shmem::id_t id = inshmem.mId
+        # Shmem::shmem_t* raw = Lookup(id)
+        # if (raw)
+        #   outshmem = Shmem(raw, id)
+        idvar = ExprVar(self._nextuid('shmemid'))
+        rawvar = ExprVar(self._nextuid('rawshmem'))
+        iffound = StmtIf(rawvar)
+        iffound.addifstmt(StmtExpr(ExprAssn(
+            outshmem, _shmemCtor(rawvar, idvar))))
+
+        cxxShmemType = _shmemType()
+        stmts = [
+            Whitespace('// deserializing shmem type\n', indent=1),
+            StmtDecl(Decl(_shmemIdType(), idvar.name),
+                     init=_shmemId(pipeshmem)),
+            StmtDecl(Decl(_rawShmemType(ptr=1), rawvar.name),
+                     init=_lookupShmem(idvar)),
+            iffound
+        ]
+        return cxxShmemType, stmts
+
+
     def _nextuid(self, descr):
         """Return an identifier that's unique wrt to |self| and |self.name|."""
         self.idnum += 1
         return '%s_%s_%d'% (self.name, descr, self.idnum)
 
 ##--------------------------------------------------
 
 class UnionDecl(ipdl.ast.UnionDecl):
@@ -841,71 +1116,58 @@ IPDL union type."""
         elif it.isActor():
             return _HybridDecl.bareType(self, otherside)
         else: assert 0
 
 ##--------------------------------------------------
 
 class MessageDecl(ipdl.ast.MessageDecl):
     def baseName(self):
-        if self.decl.type.isDtor():
-            return self.name[1:]
         return self.name
     
     def recvMethod(self):
         name = _recvPrefix(self.decl.type) + self.baseName()
         if self.decl.type.isCtor():
             name += 'Constructor'
-        elif self.decl.type.isDtor():
-            name += 'Destructor'
         return ExprVar(name)
 
     def sendMethod(self):
         name = _sendPrefix(self.decl.type) + self.baseName()
         if self.decl.type.isCtor():
             name += 'Constructor'
-        elif self.decl.type.isDtor():
-            name += 'Destructor'
         return ExprVar(name)
 
     def hasReply(self):
         return (self.decl.type.hasReply()
                 or self.decl.type.isCtor()
                 or self.decl.type.isDtor())
 
-    # XXX best place for this?
-    def allocMethod(self):
-        return ExprVar('Alloc'+ self.baseName())
-
-    def deallocMethod(self):
-        return ExprVar('Dealloc'+ self.baseName())
-
     def msgClass(self):
         return 'Msg_%s'% (self.decl.progname)
 
     def pqMsgClass(self):
         return '%s::%s'% (self.namespace, self.msgClass())
 
     def msgCast(self, msgexpr):
         return ExprCast(msgexpr, Type(self.pqMsgClass(), const=1, ptr=1),
-                        reinterpret=1)
+                        static=1)
 
     def msgId(self):  return self.msgClass()+ '__ID'
     def pqMsgId(self):
         return '%s::%s'% (self.namespace, self.msgId())
 
     def replyClass(self):
         return 'Reply_%s'% (self.decl.progname)
 
     def pqReplyClass(self):
         return '%s::%s'% (self.namespace, self.replyClass())
 
     def replyCast(self, replyexpr):
         return ExprCast(replyexpr, Type(self.pqReplyClass(), const=1, ptr=1),
-                        reinterpret=1)
+                        static=1)
 
     def replyId(self):  return self.replyClass()+ '__ID'
     def pqReplyId(self):
         return '%s::%s'% (self.namespace, self.replyId())
 
     def actorDecl(self):
         return self.params[0]
 
@@ -1017,76 +1279,169 @@ class Protocol(ipdl.ast.Protocol):
         return '/'.join(_semsToChannelParts(self.sendSems())) +'.h'
 
     def listenerName(self):
         return _semsToListener(self.sendSems())
 
     def fqListenerName(self):
         return self.channelName() +'::'+ _semsToListener(self.sendSems())
 
-    def managerCxxType(self, ptr=0):
+    def managerInterfaceType(self, ptr=0):
         return Type('mozilla::ipc::IProtocolManager',
                     ptr=ptr,
                     T=Type(self.fqListenerName()))
 
+    def managerActorType(self, side, ptr=0):
+        return Type(_actorName(self.decl.type.manager.name(), side),
+                    ptr=ptr)
+
+    def managerMethod(self, actorThis=None):
+        if actorThis is not None:
+            return ExprSelect(actorThis, '->', 'Manager')
+        return ExprVar('Manager');
+
+    # FIXME/bug 525181: implement
+    def stateMethod(self):
+        return ExprVar('state');
+
     def registerMethod(self):
         return ExprVar('Register')
 
     def registerIDMethod(self):
         return ExprVar('RegisterID')
 
     def lookupIDMethod(self):
         return ExprVar('Lookup')
 
-    def unregisterMethod(self):
+    def unregisterMethod(self, actorThis=None):
+        if actorThis is not None:
+            return ExprSelect(actorThis, '->', 'Unregister')
         return ExprVar('Unregister')
 
     def otherProcessMethod(self):
         return ExprVar('OtherProcess')
 
     def nextActorIdExpr(self, side):
         assert self.decl.type.isToplevel()
         if side is 'parent':   op = '++'
         elif side is 'child':  op = '--'
+        else: assert 0
         return ExprPrefixUnop(self.lastActorIdVar(), op)
 
+    def actorIdInit(self, side):
+        assert self.decl.type.isToplevel()
+
+        # parents go up from FREED, children go down from NULL
+        if side is 'parent':  return _FREED_ACTOR_ID
+        elif side is 'child': return _NULL_ACTOR_ID
+        else: assert 0
+
     # an actor's C++ private variables
     def lastActorIdVar(self):
         assert self.decl.type.isToplevel()
         return ExprVar('mLastRouteId')
 
     def actorMapVar(self):
         assert self.decl.type.isToplevel()
         return ExprVar('mActorMap')
 
-    def channelVar(self):
+    def channelVar(self, actorThis=None):
+        if actorThis is not None:
+            return ExprSelect(actorThis, '->', 'mChannel')
         return ExprVar('mChannel')
 
     def channelForSubactor(self):
         if self.decl.type.isToplevel():
             return ExprAddrOf(self.channelVar())
         return self.channelVar()
 
-    def routingId(self):
+    def routingId(self, actorThis=None):
         if self.decl.type.isToplevel():
             return ExprVar('MSG_ROUTING_CONTROL')
+        if actorThis is not None:
+            return ExprSelect(actorThis, '->', self.idVar().name)
         return self.idVar()
 
     def idVar(self):
         assert not self.decl.type.isToplevel()
         return ExprVar('mId')
 
     def managerVar(self):
         assert not self.decl.type.isToplevel()
         return ExprVar('mManager')
 
     def otherProcessVar(self):
         assert self.decl.type.isToplevel()
         return ExprVar('mOtherProcess')
 
+    def managedCxxType(self, actortype, side):
+        assert self.decl.type.isManagerOf(actortype)
+        return Type(_actorName(actortype.name(), side), ptr=1)
+
+    def managedMethod(self, actortype, side):
+        assert self.decl.type.isManagerOf(actortype)
+        return ExprVar('Managed'+  _actorName(actortype.name(), side))
+
+    def managedVar(self, actortype, side):
+        assert self.decl.type.isManagerOf(actortype)
+        return ExprVar('mManaged'+ _actorName(actortype.name(), side))
+
+    def managedVarType(self, actortype, side, const=0, ref=0):
+        assert self.decl.type.isManagerOf(actortype)
+        return _cxxArrayType(self.managedCxxType(actortype, side),
+                             const=const, ref=ref)
+
+    def managerArrayExpr(self, thisvar, side):
+        """The member var my manager keeps of actors of my type."""
+        assert self.decl.type.isManaged()
+        return ExprSelect(
+            ExprCall(self.managerMethod(thisvar)),
+            '->', 'mManaged'+ _actorName(self.decl.type.name(), side))
+
+    # shmem stuff
+    def shmemMapVar(self):
+        assert self.usesShmem()
+        return ExprVar('mShmemMap')
+
+    def lastShmemIdVar(self):
+        assert self.usesShmem()
+        return ExprVar('mLastShmemId')
+
+    def nextShmemIdExpr(self, side):
+        assert self.usesShmem()
+        if side is 'parent':   op = '++'
+        elif side is 'child':  op = '--'
+        return ExprPrefixUnop(self.lastShmemIdVar(), op)
+
+    def lookupShmemVar(self):
+        assert self.usesShmem()
+        return ExprVar('LookupShmem')
+
+    def registerShmemVar(self):
+        assert self.usesShmem()
+        return ExprVar('RegisterShmem')
+
+    def registerShmemIdVar(self):
+        assert self.usesShmem()
+        return ExprVar('RegisterShmemId')
+
+    def unregisterShmemVar(self):
+        assert self.usesShmem()
+        return ExprVar('UnregisterShmem')
+
+    def usesShmem(self):
+        for md in self.messageDecls:
+            for param in md.inParams:
+                if ipdl.type.hasshmem(param.type):
+                    return True
+            for ret in md.outParams:
+                if ipdl.type.hasshmem(ret.type):
+                    return True
+        return False
+
     @staticmethod
     def upgrade(protocol):
         assert isinstance(protocol, ipdl.ast.Protocol)
         protocol.__class__ = Protocol
         return protocol
 
 ##-----------------------------------------------------------------------------
 
@@ -1097,18 +1452,19 @@ relevant to C++ code generation.
 This pass results in an AST that is a poor man's "IR"; in reality, a
 "hybrid" AST mainly consisting of IPDL nodes with new C++ info along
 with some new IPDL/C++ nodes that are tuned for C++ codegen."""
 
     def __init__(self):
         # the set of typedefs that allow generated classes to
         # reference known C++ types by their "short name" rather than
         # fully-qualified name. e.g. |Foo| rather than |a::b::Foo|.
-        self.typedefs = [ Typedef(Type('mozilla::ipc::ActorHandle'),
-                                  'ActorHandle') ]
+        self.typedefs = [ 
+            Typedef(Type('mozilla::ipc::ActorHandle'), 'ActorHandle')
+        ]
         self.protocolName = None
 
     def visitProtocol(self, pro):
         self.protocolName = pro.name
         pro.decl.cxxtypedefs = self.typedefs
         Protocol.upgrade(pro)
         return ipdl.ast.Visitor.visitProtocol(self, pro)
 
@@ -1131,17 +1487,17 @@ with some new IPDL/C++ nodes that are tu
                 newcomponents.append(_UnionMember(ctype, ud, side='child'))
             else:
                 newcomponents.append(_UnionMember(ctype, ud))
         ud.components = newcomponents
         UnionDecl.upgrade(ud)
 
         if ud.decl.fullname is not None:
             self.typedefs.append(Typedef(Type(ud.fqClassName()), ud.name))
-            
+
 
     def visitDecl(self, decl):
         return _HybridDecl(decl.type, decl.progname)
 
     def visitMessageDecl(self, md):
         md.namespace = self.protocolName
         md.params = [ param.accept(self) for param in md.inParams ]
         md.returns = [ ret.accept(self) for ret in md.outParams ]
@@ -1287,17 +1643,17 @@ def _generateMessageClass(clsname, msgid
     msgvar = ExprVar('msg')
     msgdecl = Decl(Type('Message', ptr=1, const=1), msgvar.name)
     reader = MethodDefn(MethodDecl(
         'Read', params=[ msgdecl ] + outparams, ret=Type.BOOL, static=1))
 
     itervar = ExprVar('iter')
     if len(outparams):
         reader.addstmts([
-            StmtDecl(Decl(Type('void', ptr=True), itervar.name),
+            StmtDecl(Decl(Type.VOIDPTR, itervar.name),
                      ExprLiteral.ZERO),
             Whitespace.NL ])
 
     for oparam in outparams:
         failif = StmtIf(ExprNot(ExprCall(
             ExprVar('IPC::ReadParam'),
             args=[ msgvar, ExprAddrOf(itervar), ExprVar(oparam.name) ])))
         failif.addifstmt(StmtReturn(ExprLiteral.FALSE))
@@ -1552,29 +1908,29 @@ def _generateCxxUnionStuff(ud):
         dtorswitch,
         StmtReturn(ExprLiteral.TRUE)
     ])
     cls.addstmts([ maybedtor, Whitespace.NL ])
 
     # add helper methods that ensure the discunion has a
     # valid type
     sanity = MethodDefn(MethodDecl(
-        assertsanityvar.name, ret=Type('void'), const=1))
+        assertsanityvar.name, ret=Type.VOID, const=1))
     sanity.addstmts([
         _abortIfFalse(ExprBinary(tfirstvar, '<=', mtypevar),
                       'invalid type tag'),
         _abortIfFalse(ExprBinary(mtypevar, '<=', tlastvar),
                       'invalid type tag') ])
     cls.addstmt(sanity)
 
     atypevar = ExprVar('aType')
     sanity2 = MethodDefn(
         MethodDecl(assertsanityvar.name,
                        params=[ Decl(typetype, atypevar.name) ],
-                       ret=Type('void'),
+                       ret=Type.VOID,
                        const=1))
     sanity2.addstmts([
         StmtExpr(ExprCall(assertsanityvar)),
         _abortIfFalse(ExprBinary(mtypevar, '==', atypevar),
                       'unexpected type tag') ])
     cls.addstmts([ sanity2, Whitespace.NL ])
 
     ## ---- begin public methods -----
@@ -1952,26 +2308,20 @@ def _generateCxxUnionStuff(ud):
 class _FindFriends(ipdl.ast.Visitor):
     def __init__(self):
         self.mytype = None              # ProtocolType
         self.vtype = None               # ProtocolType
         self.friends = set()            # set<ProtocolType>
 
     def findFriends(self, ptype):
         self.mytype = ptype
-        toplevel = self.findToplevel(ptype)
-        self.walkDownTheProtocolTree(toplevel)
+        self.walkDownTheProtocolTree(ptype.toplevel())
         return self.friends
 
     # TODO could make this into a _iterProtocolTreeHelper ...
-    def findToplevel(self, ptype):
-        if ptype.isToplevel():
-            return ptype
-        return self.findToplevel(ptype.manager)
-
     def walkDownTheProtocolTree(self, ptype):
         if ptype != self.mytype:
             # don't want to |friend| ourself!
             self.visit(ptype)
         for mtype in ptype.manages:
             self.walkDownTheProtocolTree(mtype)
 
     def visit(self, ptype):
@@ -1990,194 +2340,271 @@ class _FindFriends(ipdl.ast.Visitor):
         for param in md.inParams:
             for actor in ipdl.type.iteractortypes(param.type):
                 yield actor
         for ret in md.outParams:
             for actor in ipdl.type.iteractortypes(ret.type):
                 yield actor
 
 
-class _Result:
-    Type = Type('Result')
-
-    Processed = ExprVar('MsgProcessed')
-    NotKnown = ExprVar('MsgNotKnown')
-    NotAllowed = ExprVar('MsgNotAllowed')
-    PayloadError = ExprVar('MsgPayloadError')
-    RouteError = ExprVar('MsgRouteError')
-    ValuError = ExprVar('MsgValueError') # [sic]
-
-class _GenerateProtocolActorHeader(ipdl.ast.Visitor):
+class _GenerateProtocolActorCode(ipdl.ast.Visitor):
     def __init__(self, myside):
         self.side = myside              # "parent" or "child"
         self.prettyside = myside.title()
         self.clsname = None
         self.protocol = None
-        self.file = None
+        self.hdrfile = None
+        self.cppfile = None
         self.ns = None
         self.cls = None
         self.includedActorTypedefs = [ ]
-
-    def lower(self, tu, clsname, cxxHeaderFile):
+        self.protocolCxxIncludes = [ ]
+
+    def lower(self, tu, clsname, cxxHeaderFile, cxxFile):
         self.clsname = clsname
-        self.file = cxxHeaderFile
+        self.hdrfile = cxxHeaderFile
+        self.cppfile = cxxFile
         tu.accept(self)
 
+    def standardTypedefs(self):
+        return [
+            Typedef(Type('IPC::Message'), 'Message'),
+            Typedef(Type(self.protocol.channelName()), 'Channel'),
+            Typedef(Type(self.protocol.fqListenerName()), 'ChannelListener'),
+            Typedef(Type('base::ProcessHandle'), 'ProcessHandle')
+        ]
+
+
     def visitTranslationUnit(self, tu):
-        f = self.file
-
-        f.addthing(Whitespace('''//
+        self.protocol = tu.protocol
+
+        hf = self.hdrfile
+        cf = self.cppfile
+
+        disclaimer = Whitespace('''//
 // Automatically generated by ipdlc.
 // Edit at your own risk
 //
 
-'''))
-        f.addthings(_includeGuardStart(f))
-        f.addthings([
-            Whitespace.NL,
-            CppDirective(
-                'include',
-                '"'+ _protocolHeaderBaseFilename(tu.protocol) +'.h"') ])
-
-        self.protocol = tu.protocol
+''')
+        # make the C++ header
+        hf.addthings(
+            [ disclaimer ]
+            + _includeGuardStart(hf)
+            +[
+                Whitespace.NL,
+                CppDirective(
+                    'include',
+                    '"'+ _protocolHeaderName(tu.protocol) +'.h"')
+            ])
 
         for pinc in tu.protocolIncludes:
             pinc.accept(self)
 
+        # this generates the actor's full impl in self.cls
         tu.protocol.accept(self)
 
-        f.addthing(Whitespace.NL)
-        f.addthings(_includeGuardEnd(f))
+        clsdecl, clsdefn = _ClassDeclDefn().split(self.cls)
+
+        # XXX damn C++ ... return types in the method defn aren't in
+        # class scope
+        for stmt in clsdefn.stmts:
+            if isinstance(stmt, MethodDefn):
+                if stmt.decl.ret and stmt.decl.ret.name == 'Result':
+                    stmt.decl.ret.name = clsdecl.name +'::'+ stmt.decl.ret.name
+
+        def makeNamespace(p, file):
+            if 0 == len(p.namespaces):
+                return file
+            ns = Namespace(p.namespaces[-1].name)
+            outerns = _putInNamespaces(ns, p.namespaces[:-1])
+            file.addthing(outerns)
+            return ns
+
+        hdrns = makeNamespace(self.protocol, self.hdrfile)
+        hdrns.addstmts([
+            Whitespace.NL,
+            Whitespace.NL,
+            clsdecl,
+            Whitespace.NL,
+            Whitespace.NL
+        ])
+
+        self.hdrfile.addthings(
+            ([
+                Whitespace.NL,
+                CppDirective('if', '0') ])
+            + _GenerateSkeletonImpl(
+                _actorName(self.protocol.name, self.side)[1:],
+                self.protocol.namespaces).fromclass(self.cls)
+            +([
+                CppDirective('endif', '// if 0'),
+                Whitespace.NL ])
+            + _includeGuardEnd(hf))
+
+        # make the .cpp file
+        cf.addthings((
+            [ disclaimer,
+              Whitespace.NL,
+              CppDirective(
+                  'include',
+                  '"'+ _protocolHeaderName(self.protocol, self.side) +'.h"'),
+              Whitespace.NL
+            ]
+            + self.protocolCxxIncludes
+            + [ Whitespace.NL ]
+            + self.standardTypedefs()
+            + self.includedActorTypedefs
+            + tu.protocol.decl.cxxtypedefs
+            + [ Whitespace.NL ]))
+
+        cppns = makeNamespace(self.protocol, cf)
+        cppns.addstmts([
+            Whitespace.NL,
+            Whitespace.NL,
+            clsdefn,
+            Whitespace.NL,
+            Whitespace.NL
+        ])
 
 
     def visitProtocolInclude(self, pi):
         ip = pi.tu.protocol
 
-        if self.protocol.decl.type.isManagerOf(ip.decl.type):
-            self.file.addthing(
-                CppDirective(
-                    'include',
-                    '"%s%s.h"'% (_protocolHeaderBaseFilename(ip),
-                                 self.prettyside)))
+        self.hdrfile.addthings([
+            _makeForwardDecl(ip.decl.type, self.side),
+            Whitespace.NL
+        ])
+        self.protocolCxxIncludes.append(
+            CppDirective(
+                'include',
+                '"%s.h"'% (_protocolHeaderName(ip, self.side))))
 
         if ip.decl.fullname is not None:
             self.includedActorTypedefs.append(Typedef(
                 Type(_actorName(ip.decl.fullname, self.prettyside)),
                 _actorName(ip.decl.shortname, self.prettyside)))
 
 
     def visitProtocol(self, p):
-        self.file.addthings([
+        self.hdrfile.addthings([
             CppDirective('ifdef', 'DEBUG'),
             CppDirective('include', '"prenv.h"'),
             CppDirective('endif', '// DEBUG')
         ])
 
         self.protocol = p
 
         # FIXME: all actors impl Iface for now
         if p.decl.type.isManager() or 1:
-            self.file.addthing(CppDirective('include', '"base/id_map.h"'))
-
-        self.file.addthings([
+            self.hdrfile.addthing(CppDirective('include', '"base/id_map.h"'))
+
+        self.hdrfile.addthings([
             CppDirective('include', '"'+ p.channelHeaderFile() +'"'),
             Whitespace.NL ])
 
-        inherits = [ Inherit(Type(p.fqListenerName())) ]
-        if p.decl.type.isManager():
-            inherits.append(Inherit(p.managerCxxType()))
-        self.cls = Class(self.clsname, inherits=inherits, abstract=True)
+        self.cls = Class(
+            self.clsname,
+            inherits=[ Inherit(Type(p.fqListenerName()), viz='protected'),
+                       Inherit(p.managerInterfaceType(), viz='protected') ],
+            abstract=True)
 
         friends = _FindFriends().findFriends(p.decl.type)
         if p.decl.type.isManaged():
             friends.add(p.decl.type.manager)
 
+        # |friend| managed actors so that they can call our Dealloc*()
+        friends.update(p.decl.type.manages)
+
         for friend in friends:
-            self.file.addthings([
+            self.hdrfile.addthings([
                 Whitespace.NL,
                 _makeForwardDecl(friend, self.prettyside),
                 Whitespace.NL
             ])
             self.cls.addstmts([
                 FriendClassDecl(_actorName(friend.fullname(),
                                            self.prettyside)),
                 Whitespace.NL ])
 
-        # construct the namespace into which we'll stick all our decls
-        if 0 == len(p.namespaces):
-            self.ns = self.file
-        else:
-            self.ns = Namespace(p.namespaces[-1].name)
-            outerns = _putInNamespaces(self.ns, p.namespaces[:-1])
-            self.file.addthing(outerns)
-        self.ns.addstmts([ Whitespace.NL, Whitespace.NL ])
-
         self.cls.addstmt(Label.PROTECTED)
         for typedef in p.cxxTypedefs():
             self.cls.addstmt(typedef)
         for typedef in self.includedActorTypedefs:
             self.cls.addstmt(typedef)
         self.cls.addstmt(Whitespace.NL)
 
         # interface methods that the concrete subclass has to impl
         for md in p.messageDecls:
             isctor, isdtor = md.decl.type.isCtor(), md.decl.type.isDtor()
-            if isctor:
-                self.cls.addstmt(StmtDecl(MethodDecl(
-                    md.allocMethod().name,
-                    params=md.makeCxxParams(paramsems='in', returnsems='out',
-                                            side=self.side,
-                                            implicit=0),
-                    ret=md.actorDecl().bareType(self.side),
-                    virtual=1, pure=1)))
-            elif isdtor:
-                self.cls.addstmt(StmtDecl(MethodDecl(
-                    md.deallocMethod().name,
-                    params=md.makeCxxParams(paramsems='in', returnsems='out',
-                                            side=self.side,
-                                            implicit=1),
-                    ret=Type.BOOL,
-                    virtual=1, pure=1)))
 
             if self.receivesMessage(md):
                 # generate Recv/Answer* interface
+                implicit = (not isdtor)
                 recvDecl = MethodDecl(
                     md.recvMethod().name,
                     params=md.makeCxxParams(paramsems='in', returnsems='out',
-                                            side=self.side, implicit=1),
+                                            side=self.side, implicit=implicit),
                     ret=Type.BOOL, virtual=1)
 
                 if isctor or isdtor:
                     defaultRecv = MethodDefn(recvDecl)
                     defaultRecv.addstmt(StmtReturn(ExprLiteral.TRUE))
                     self.cls.addstmt(defaultRecv)
                 else:
                     recvDecl.pure = 1
                     self.cls.addstmt(StmtDecl(recvDecl))
 
-        self.cls.addstmt(Whitespace.NL)
-
+        for md in p.messageDecls:
+            managed = md.decl.type.constructedType()
+            if not p.decl.type.isManagerOf(managed):
+                continue
+
+            # add the Alloc/Dealloc interface for managed actors
+            actortype = md.actorDecl().bareType(self.side)
+            
+            self.cls.addstmt(StmtDecl(MethodDecl(
+                _allocMethod(managed).name,
+                params=md.makeCxxParams(side=self.side, implicit=0),
+                ret=actortype,
+                virtual=1, pure=1)))
+
+            self.cls.addstmt(StmtDecl(MethodDecl(
+                _deallocMethod(managed).name,
+                params=[ Decl(actortype, 'actor') ],
+                ret=Type.BOOL,
+                virtual=1, pure=1)))
+
+        # optional Shutdown() method; default is no-op
         self.cls.addstmts([
-            Label.PRIVATE,
-            Typedef(Type('IPC::Message'), 'Message'),
-            Typedef(Type(p.channelName()), 'Channel'),
-            Typedef(Type(p.fqListenerName()), 'ChannelListener'),
-            Typedef(Type('base::ProcessHandle'), 'ProcessHandle'),
             Whitespace.NL,
+            MethodDefn(MethodDecl(
+                _destroyMethod().name,
+                params=[ Decl(_DestroyReason.Type(), 'why') ],
+                virtual=1))
         ])
 
+        self.cls.addstmt(Whitespace.NL)
+
+        self.cls.addstmts((
+            [ Label.PRIVATE ]
+            + self.standardTypedefs()
+            + [ Whitespace.NL ]
+        ))
+
         self.cls.addstmt(Label.PUBLIC)
         # Actor()
         ctor = ConstructorDefn(ConstructorDecl(self.clsname))
         if p.decl.type.isToplevel():
             ctor.memberinits = [
                 ExprMemberInit(p.channelVar(), [
                     ExprCall(ExprVar('ALLOW_THIS_IN_INITIALIZER_LIST'),
                              [ ExprVar.THIS ]) ]),
-                ExprMemberInit(p.lastActorIdVar(), [ ExprLiteral.ZERO ])
+                ExprMemberInit(p.lastActorIdVar(),
+                               [ p.actorIdInit(self.side) ])
             ]
         else:
             ctor.memberinits = [
                 ExprMemberInit(p.idVar(), [ ExprLiteral.ZERO ]) ]
 
         ctor.addstmt(StmtExpr(ExprCall(ExprVar('MOZ_COUNT_CTOR'),
                                        [ ExprVar(self.clsname) ])))
         self.cls.addstmts([ ctor, Whitespace.NL ])
@@ -2196,18 +2623,19 @@ class _GenerateProtocolActorHeader(ipdl.
             aThreadVar = ExprVar('aThread')
             processvar = ExprVar('aOtherProcess')
             openmeth = MethodDefn(
                 MethodDecl(
                     'Open',
                     params=[ Decl(Type('Channel::Transport', ptr=True),
                                       aTransportVar.name),
                              Decl(Type('ProcessHandle'), processvar.name),
-                             Decl(Type('MessageLoop', ptr=True),
-                                      aThreadVar.name +' = 0') ],
+                             Param(Type('MessageLoop', ptr=True),
+                                   aThreadVar.name,
+                                   default=ExprLiteral.NULL) ],
                     ret=Type.BOOL))
 
             openmeth.addstmts([
                 StmtExpr(ExprAssn(p.otherProcessVar(), processvar)),
                 StmtReturn(ExprCall(ExprSelect(p.channelVar(), '.', 'Open'),
                                     [ aTransportVar, aThreadVar ]))
             ])
             self.cls.addstmts([
@@ -2215,16 +2643,37 @@ class _GenerateProtocolActorHeader(ipdl.
                 Whitespace.NL ])
 
             # Close()
             closemeth = MethodDefn(MethodDecl('Close'))
             closemeth.addstmt(StmtExpr(
                 ExprCall(ExprSelect(p.channelVar(), '.', 'Close'))))
             self.cls.addstmts([ closemeth, Whitespace.NL ])
 
+        if not p.decl.type.isToplevel():
+            ## manager()
+            managertype = p.managerActorType(self.side, ptr=1)
+            managermeth = MethodDefn(MethodDecl(
+                p.managerMethod().name, ret=managertype))
+            managermeth.addstmt(StmtReturn(p.managerVar()))
+
+            self.cls.addstmts([ managermeth, Whitespace.NL ])
+
+        ## managed[T]()
+        for managed in p.decl.type.manages:
+            arrvar = ExprVar('aArr')
+            meth = MethodDefn(MethodDecl(
+                p.managedMethod(managed, self.side).name,
+                params=[ Decl(p.managedVarType(managed, self.side, ref=1),
+                              arrvar.name) ],
+                const=1))
+            meth.addstmt(StmtExpr(ExprAssn(
+                arrvar, p.managedVar(managed, self.side))))
+            self.cls.addstmts([ meth, Whitespace.NL ])
+
         ## OnMessageReceived()/OnCallReceived()
 
         # save these away for use in message handler case stmts
         msgvar = ExprVar('msg')
         self.msgvar = msgvar
         replyvar = ExprVar('reply')
         self.replyvar = replyvar
         
@@ -2235,16 +2684,23 @@ class _GenerateProtocolActorHeader(ipdl.
             if p.decl.type.toplevel().talksRpc():
                 self.rpcSwitch = StmtSwitch(msgtype)
 
         # implement Send*() methods and add dispatcher cases to
         # message switch()es
         for md in p.messageDecls:
             self.visitMessageDecl(md)
 
+        # "hidden" message that passes shmem mappings from one process
+        # to the other
+        if p.usesShmem():
+            self.asyncSwitch.addcase(
+                CaseLabel('SHMEM_CREATED_MESSAGE_TYPE'),
+                self.genShmemCreatedHandler())
+
         # add default cases
         default = StmtBlock()
         default.addstmt(StmtReturn(_Result.NotKnown))
         self.asyncSwitch.addcase(DefaultLabel(), default)
         if p.decl.type.toplevel().talksSync():
             self.syncSwitch.addcase(DefaultLabel(), default)
             if p.decl.type.toplevel().talksRpc():
                 self.rpcSwitch.addcase(DefaultLabel(), default)
@@ -2252,17 +2708,17 @@ class _GenerateProtocolActorHeader(ipdl.
 
         def makeHandlerMethod(name, switch, hasReply, dispatches=0):
             params = [ Decl(Type('Message', const=1, ref=1), msgvar.name) ]
             if hasReply:
                 params.append(Decl(Type('Message', ref=1, ptr=1),
                                    replyvar.name))
             
             method = MethodDefn(MethodDecl(name, virtual=True,
-                                           params=params, ret=_Result.Type))
+                                           params=params, ret=_Result.Type()))
             if dispatches:
                 routevar = ExprVar('__route')
                 routedecl = StmtDecl(
                     Decl(_actorIdType(), routevar.name),
                     init=ExprCall(ExprSelect(msgvar, '.', 'routing_id')))
 
                 routeif = StmtIf(ExprBinary(
                     ExprVar('MSG_ROUTING_CONTROL'), '!=', routevar))
@@ -2304,50 +2760,203 @@ class _GenerateProtocolActorHeader(ipdl.
             ])
             if p.decl.type.toplevel().talksRpc():
                 self.cls.addstmts([
                     makeHandlerMethod('OnCallReceived', self.rpcSwitch,
                                       hasReply=1, dispatches=dispatches),
                     Whitespace.NL
                 ])
 
+        destroysubtreevar = ExprVar('DestroySubtree')
+        deallocsubtreevar = ExprVar('DeallocSubtree')
+
+        # OnChannelClose()
+        onclose = MethodDefn(MethodDecl('OnChannelClose'))
+        onclose.addstmt(StmtExpr(ExprCall(
+            destroysubtreevar,
+            args=[ _DestroyReason.NormalShutdown ])))
+        self.cls.addstmts([ onclose, Whitespace.NL ])
+
+        # OnChannelClose()
+        onerror = MethodDefn(MethodDecl('OnChannelError'))
+        onerror.addstmt(StmtExpr(ExprCall(
+            destroysubtreevar,
+            args=[ _DestroyReason.AbnormalShutdown ])))
+        self.cls.addstmts([ onerror, Whitespace.NL ])
+
         # FIXME: only manager protocols and non-manager protocols with
         # union types need Lookup().  we'll give it to all for the
         # time being (simpler)
         if 1 or p.decl.type.isManager():
             self.cls.addstmts(self.implementManagerIface())
 
-        # private: members and methods
-        self.cls.addstmts([ Label.PRIVATE,
-                            StmtDecl(Decl(p.channelType(), 'mChannel')) ])
+        if p.usesShmem():
+            self.cls.addstmts(self.makeShmemIface())
+
+        ## private methods
+        self.cls.addstmt(Label.PRIVATE)
+
+        ## FatalError()       
+        msgvar = ExprVar('msg')
+        fatalerror = MethodDefn(MethodDecl(
+            'FatalError',
+            params=[ Decl(Type('char', const=1, ptrconst=1), msgvar.name) ],
+            const=1))
+        fatalerror.addstmts([
+            _printErrorMessage('IPDL error:'),
+            _printErrorMessage(msgvar),
+            Whitespace.NL
+        ])
+        actorname = _actorName(p.name, self.side)
+        if self.side is 'parent':
+            # if the error happens on the parent side, the parent
+            # kills off the child
+            fatalerror.addstmts([
+                _printErrorMessage(
+                    '['+ actorname +'] killing child side as a result'),
+                Whitespace.NL
+            ])
+
+            ifkill = StmtIf(ExprNot(
+                _killProcess(ExprCall(p.otherProcessMethod()))))
+            ifkill.addifstmt(
+                _printErrorMessage("  may have failed to kill child!"))
+            fatalerror.addstmt(ifkill)
+        else:
+            # and if it happens on the child side, the child commits
+            # seppuko
+            fatalerror.addstmt(
+                _runtimeAbort('['+ actorname +'] abort()ing as a result'))
+        self.cls.addstmts([ fatalerror, Whitespace.NL ])
+
+        ## DestroySubtree(bool normal)
+        whyvar = ExprVar('why')
+        subtreewhyvar = ExprVar('subtreewhy')
+        kidsvar = ExprVar('kids')
+        ivar = ExprVar('i')
+        ithkid = ExprIndex(kidsvar, ivar)
+
+        destroysubtree = MethodDefn(MethodDecl(
+            destroysubtreevar.name,
+            params=[ Decl(_DestroyReason.Type(), whyvar.name) ]))
+
+        if p.decl.type.isManager():
+            # only declare this for managers to avoid unused var warnings
+            destroysubtree.addstmts([
+                StmtDecl(
+                    Decl(_DestroyReason.Type(), subtreewhyvar.name),
+                    init=ExprConditional(
+                        ExprBinary(_DestroyReason.Deletion, '==', whyvar),
+                        _DestroyReason.AncestorDeletion, whyvar)),
+                Whitespace.NL
+            ])
+
+        for managed in p.decl.type.manages:
+            foreachdestroy = StmtFor(
+                init=Param(Type.UINT32, ivar.name, ExprLiteral.ZERO),
+                cond=ExprBinary(ivar, '<', _callCxxArrayLength(kidsvar)),
+                update=ExprPrefixUnop(ivar, '++'))
+            foreachdestroy.addstmt(StmtExpr(ExprCall(
+                ExprSelect(ithkid, '->', destroysubtreevar.name),
+                args=[ subtreewhyvar ])))
+
+            block = StmtBlock()
+            block.addstmts([
+                Whitespace(
+                    '// Recursively shutting down %s kids\n'% (managed.name()),
+                    indent=1),
+                StmtDecl(
+                    Decl(p.managedVarType(managed, self.side), kidsvar.name),
+                    init=p.managedVar(managed, self.side)),
+                foreachdestroy,
+            ])
+            destroysubtree.addstmt(block)
+        # finally, destroy "us"
+        destroysubtree.addstmt(StmtExpr(
+            ExprCall(_destroyMethod(), args=[ whyvar ])))
+
+        # XXX kick off DeallocSubtree() here rather than in a new
+        # event because that may be tricky on shutdown.  revisit if
+        # need be
+        if p.decl.type.isToplevel():
+            destroysubtree.addstmt(StmtExpr(ExprCall(deallocsubtreevar)))
+        
+        self.cls.addstmts([ destroysubtree, Whitespace.NL ])
+
+        ## DeallocSubtree()
+        deallocsubtree = MethodDefn(MethodDecl(deallocsubtreevar.name))
+        for managed in p.decl.type.manages:
+            foreachrecurse = StmtFor(
+                init=Param(Type.UINT32, ivar.name, ExprLiteral.ZERO),
+                cond=ExprBinary(ivar, '<', _callCxxArrayLength(kidsvar)),
+                update=ExprPrefixUnop(ivar, '++'))
+            foreachrecurse.addstmt(StmtExpr(ExprCall(
+                ExprSelect(ithkid, '->', deallocsubtreevar.name))))
+
+            foreachdealloc = StmtFor(
+                init=Param(Type.UINT32, ivar.name, ExprLiteral.ZERO),
+                cond=ExprBinary(ivar, '<', _callCxxArrayLength(kidsvar)),
+                update=ExprPrefixUnop(ivar, '++'))
+            foreachdealloc.addstmts([
+                StmtExpr(ExprCall(_deallocMethod(managed),
+                                  args=[ ithkid ]))
+            ])
+
+            block = StmtBlock()
+            block.addstmts([
+                Whitespace(
+                    '// Recursively deleting %s kids\n'% (managed.name()),
+                    indent=1),
+                StmtDecl(
+                    Decl(p.managedVarType(managed, self.side, ref=1),
+                         kidsvar.name),
+                    init=p.managedVar(managed, self.side)),
+                foreachrecurse,
+                Whitespace.NL,
+                # no need to copy |kids| here; we're the ones deleting
+                # stragglers, no outside C++ is being invoked (except
+                # Dealloc(subactor))
+                foreachdealloc,
+                StmtExpr(_callCxxArrayClear(p.managedVar(managed, self.side))),
+
+            ])
+            deallocsubtree.addstmt(block)
+        # don't delete outselves: either the manager will do it, or
+        # we're toplevel
+        self.cls.addstmts([ deallocsubtree, Whitespace.NL ])
+        
+        ## private members
+        self.cls.addstmt(StmtDecl(Decl(p.channelType(), 'mChannel')))
         if p.decl.type.isToplevel():
             self.cls.addstmts([
                 StmtDecl(Decl(Type('IDMap', T=Type('ChannelListener')),
                               p.actorMapVar().name)),
                 StmtDecl(Decl(_actorIdType(), p.lastActorIdVar().name)),
                 StmtDecl(Decl(Type('ProcessHandle'),