Merge m-c to tm.
authorRobert Sayre <sayrer@gmail.com>
Thu, 17 Dec 2009 04:26:12 -0500
changeset 36443 a1ed559267934a7847b98e5c2e2bee3b2e8592d4
parent 36442 c0af9622cf91dfb01f2ce49bc036a5a5279094aa (current diff)
parent 36328 c122a086b90fc5fd8402f911dc57e157d98f60d2 (diff)
child 36444 e311baa5931e7ae6e727a35175b8a32b185b81d1
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
Merge m-c to tm.
browser/installer/package-manifest.in
configure.in
js/src/jsapi.cpp
js/src/jsscan.cpp
js/src/tests/js1_5/Regress/jstests.list
toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-amd.sym
toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-intel.sym
toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.h
toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc
toolkit/crashreporter/google-breakpad/src/client/linux/sender/google_crash_report_sender.cc
toolkit/crashreporter/google-breakpad/src/client/mac/sender/goArrow.png
toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.cc
toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj
toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc
toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h
toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc
toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc
toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h
toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h
toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h
toolkit/crashreporter/google-breakpad/src/common/linux/memory.h
toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc
toolkit/crashreporter/google-breakpad/src/common/linux/module.cc
toolkit/crashreporter/google-breakpad/src/common/linux/module.h
toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.cc
toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags_completions.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/log_severity.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/raw_logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/stl_logging.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/vlog_is_on.h
toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/gflags/libgflags.a
toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/glog/libglog.a
toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc
toolkit/xre/Makefile.in
toolkit/xre/nsAppRunner.cpp
--- a/.hgtags
+++ b/.hgtags
@@ -27,9 +27,11 @@ 0000000000000000000000000000000000000000
 0cd41f5990807fb6ab52cb59ba3c8e8247281045 GECKO_1_9_1_BASE
 8df5a90281cd4d75835e4b7696da200555eed15f GECKO_1_9_1_BASE
 8a601ed6bc4c7b3d1e35aa9e81f257512d984bd5 FENNEC_A2
 d7d64f68423b68a671f623f123e90057ebc49dac UPDATE_PACKAGING_R7
 fb32f6e1859c07846a01b4478a7b1678019e0b45 UPDATE_PACKAGING_R7
 f817a4378f32b1ad0a7c4b5a9949586dba816da5 FENNEC_M11
 5c1e7c779b6edc8ff912001990edc579f80597f4 FENNEC_B1
 fe9cc55b8db7f56f7e68a246acba363743854979 UPDATE_PACKAGING_R8
+6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-r15462
+6fd4bb500d425c406c1b52f66e5b195b20ae5e0a chromium-import-latest
 376b78fc72230aaf2ca4e279a8f4ef1efd4a1d9f GECKO_1_9_2_BASE
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -404,16 +404,27 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
     eNoValue,
     eSortAction,
     eNoLiveAttr,
     kNoReqStates,
     eARIASelectable,
     eARIAReadonly
   },
   {
+    "scrollbar",
+    nsIAccessibleRole::ROLE_SCROLLBAR,
+    kUseMapRole,
+    eHasValueMinMax,
+    eNoAction,
+    eNoLiveAttr,
+    kNoReqStates,
+    eARIAOrientation,
+    eARIAReadonly
+  },
+  {
     "separator",
     nsIAccessibleRole::ROLE_SEPARATOR,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates
   },
@@ -623,16 +634,21 @@ nsStateMapEntry nsARIAMap::gWAIStateMap[
   nsStateMapEntry(&nsAccessibilityAtoms::aria_multiline, kBoolType, 0,
                   0, nsIAccessibleStates::EXT_STATE_MULTI_LINE,
                   0, nsIAccessibleStates::EXT_STATE_SINGLE_LINE, PR_TRUE),
 
   // eARIAMultiSelectable
   nsStateMapEntry(&nsAccessibilityAtoms::aria_multiselectable, kBoolType, 0,
                   nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE, 0),
 
+  // eARIAOrientation
+  nsStateMapEntry(&nsAccessibilityAtoms::aria_orientation, eUseFirstState,
+                  "vertical", 0, nsIAccessibleStates::EXT_STATE_VERTICAL,
+                  "horizontal", 0, nsIAccessibleStates::EXT_STATE_HORIZONTAL),
+
   // eARIAPressed
   nsStateMapEntry(&nsAccessibilityAtoms::aria_pressed, kMixedType,
                   nsIAccessibleStates::STATE_CHECKABLE,
                   nsIAccessibleStates::STATE_PRESSED, 0),
 
   // eARIAReadonly
   nsStateMapEntry(&nsAccessibilityAtoms::aria_readonly, kBoolType, 0,
                   nsIAccessibleStates::STATE_READONLY, 0),
@@ -688,16 +704,17 @@ nsAttributeCharacteristics nsARIAMap::gW
   {&nsAccessibilityAtoms::aria_grabbed,                            ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_haspopup,          ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_invalid,           ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_labelledby,        ATTR_BYPASSOBJ                 },
   {&nsAccessibilityAtoms::aria_live,                               ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_multiline,         ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_multiselectable,   ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_owns,              ATTR_BYPASSOBJ                 },
+  {&nsAccessibilityAtoms::aria_orientation,                        ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_pressed,           ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_readonly,          ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_relevant,          ATTR_BYPASSOBJ                 },
   {&nsAccessibilityAtoms::aria_required,          ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_selected,          ATTR_BYPASSOBJ | ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_sort,                               ATTR_VALTOKEN },
   {&nsAccessibilityAtoms::aria_valuenow,          ATTR_BYPASSOBJ                 },
   {&nsAccessibilityAtoms::aria_valuemin,          ATTR_BYPASSOBJ                 },
@@ -744,16 +761,36 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom
   attributeName(aAttrName), isToken(PR_FALSE), permanentState(0),
   value1(aValue1), state1(aState1), extraState1(aExtraState1),
   value2(aValue2), state2(aState2), extraState2(aExtraState2),
   value3(aValue3), state3(aState3), extraState3(aExtraState3),
   defaultState(0), defaultExtraState(0), definedIfAbsent(PR_FALSE)
 {
 }
 
+nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
+                                 EDefaultStateRule aDefaultStateRule,
+                                 const char *aValue1,
+                                 PRUint32 aState1, PRUint32 aExtraState1,
+                                 const char *aValue2,
+                                 PRUint32 aState2, PRUint32 aExtraState2,
+                                 const char *aValue3,
+                                 PRUint32 aState3, PRUint32 aExtraState3) :
+  attributeName(aAttrName), isToken(PR_TRUE), permanentState(0),
+  value1(aValue1), state1(aState1), extraState1(aExtraState1),
+  value2(aValue2), state2(aState2), extraState2(aExtraState2),
+  value3(aValue3), state3(aState3), extraState3(aExtraState3),
+  defaultState(0), defaultExtraState(0), definedIfAbsent(PR_TRUE)
+{
+  if (aDefaultStateRule == eUseFirstState) {
+    defaultState = aState1;
+    defaultExtraState = aExtraState1;
+  }
+}
+
 PRBool
 nsStateMapEntry::MapToStates(nsIContent *aContent,
                              PRUint32 *aState, PRUint32 *aExtraState,
                              eStateMapEntryID aStateMapEntryID)
 {
   // Return true if we should continue.
   if (aStateMapEntryID == eARIANone)
     return PR_FALSE;
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -152,16 +152,22 @@ struct nsAttributeCharacteristics
 #define kNoReqStates 0
 
 enum eStateValueType
 {
   kBoolType,
   kMixedType
 };
 
+enum EDefaultStateRule
+{
+  //eNoDefaultState,
+  eUseFirstState
+};
+
 /**
  * ID for state map entry, used in nsRoleMapEntry.
  */
 enum eStateMapEntryID
 {
   eARIANone,
   eARIAAutoComplete,
   eARIABusy,
@@ -169,16 +175,17 @@ enum eStateMapEntryID
   eARIACheckableMixed,
   eARIACheckedMixed,
   eARIADisabled,
   eARIAExpanded,
   eARIAHasPopup,
   eARIAInvalid,
   eARIAMultiline,
   eARIAMultiSelectable,
+  eARIAOrientation,
   eARIAPressed,
   eARIAReadonly,
   eARIAReadonlyOrEditable,
   eARIARequired,
   eARIASelectable
 };
 
 class nsStateMapEntry
@@ -203,16 +210,27 @@ public:
    */
   nsStateMapEntry(nsIAtom **aAttrName,
                   const char *aValue1, PRUint32 aState1, PRUint32 aExtraState1,
                   const char *aValue2, PRUint32 aState2, PRUint32 aExtraState2,
                   const char *aValue3 = 0, PRUint32 aState3 = 0,
                   PRUint32 aExtraState3 = 0);
 
   /**
+   * Used for ARIA attributes having enumerated values, and where a default
+   * attribute state should be assumed when not supplied by the author.
+   */
+  nsStateMapEntry(nsIAtom **aAttrName,
+                  EDefaultStateRule aDefaultStateRule,
+                  const char *aValue1, PRUint32 aState1, PRUint32 aExtraState1,
+                  const char *aValue2, PRUint32 aState2, PRUint32 aExtraState2,
+                  const char *aValue3 = 0, PRUint32 aState3 = 0,
+                  PRUint32 aExtraState3 = 0);
+
+  /**
    * Maps ARIA state map pointed by state map entry ID to accessible states.
    *
    * @param  aContent         [in] node of the accessible
    * @param  aState           [in/out] accessible states
    * @param  aExtraState      [in/out] accessible extra states
    * @param  aStateMapEntryID [in] state map entry ID
    * @return                   true if state map entry ID is valid
    */
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -236,16 +236,17 @@ ACCESSIBILITY_ATOM(aria_grabbed, "aria-g
 ACCESSIBILITY_ATOM(aria_haspopup, "aria-haspopup")
 ACCESSIBILITY_ATOM(aria_invalid, "aria-invalid")
 ACCESSIBILITY_ATOM(aria_label, "aria-label")
 ACCESSIBILITY_ATOM(aria_labelledby, "aria-labelledby")
 ACCESSIBILITY_ATOM(aria_level, "aria-level")
 ACCESSIBILITY_ATOM(aria_live, "aria-live")
 ACCESSIBILITY_ATOM(aria_multiline, "aria-multiline")
 ACCESSIBILITY_ATOM(aria_multiselectable, "aria-multiselectable")
+ACCESSIBILITY_ATOM(aria_orientation, "aria-orientation")
 ACCESSIBILITY_ATOM(aria_owns, "aria-owns")
 ACCESSIBILITY_ATOM(aria_posinset, "aria-posinset")
 ACCESSIBILITY_ATOM(aria_pressed, "aria-pressed")
 ACCESSIBILITY_ATOM(aria_readonly, "aria-readonly")
 ACCESSIBILITY_ATOM(aria_relevant, "aria-relevant")
 ACCESSIBILITY_ATOM(aria_required, "aria-required")
 ACCESSIBILITY_ATOM(aria_selected, "aria-selected")
 ACCESSIBILITY_ATOM(aria_setsize, "aria-setsize")
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -74,16 +74,17 @@ const STATE_UNAVAILABLE = nsIAccessibleS
 
 const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
 const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
 const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
 const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
 const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
 const EXT_STATE_SUPPORTS_AUTOCOMPLETION = 
       nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
+const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
 
 ////////////////////////////////////////////////////////////////////////////////
 // OS detect
 const MAC = (navigator.platform.indexOf("Mac") != -1)? true : false;
 const LINUX = (navigator.platform.indexOf("Linux") != -1)? true : false;
 const WIN = (navigator.platform.indexOf("Win") != -1)? true : false;
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -39,16 +39,17 @@ const ROLE_OUTLINEITEM = nsIAccessibleRo
 const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
 const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
 const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
 const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
 const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
 const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
 const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
+const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
 const ROLE_TEXT_CONTAINER = nsIAccessibleRole.ROLE_TEXT_CONTAINER;
 const ROLE_TEXT_LEAF = nsIAccessibleRole.ROLE_TEXT_LEAF;
 const ROLE_TOGGLE_BUTTON = nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
--- a/accessible/tests/mochitest/test_aria_roles.html
+++ b/accessible/tests/mochitest/test_aria_roles.html
@@ -1,13 +1,14 @@
 <!DOCTYPE html>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=481114
 https://bugzilla.mozilla.org/show_bug.cgi?id=469688
+https://bugzilla.mozilla.org/show_bug.cgi?id=529289
 -->
 <head>
   <title>Test weak ARIA roles</title>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
@@ -58,27 +59,31 @@ https://bugzilla.mozilla.org/show_bug.cg
 
       // abstract roles
       var abstract_roles = ["composite", "landmark", "structure", "widget",
                             "window", "input", "range", "select", "section",
                             "sectionhead"];
       for (a in abstract_roles)
         testRole(abstract_roles[a], ROLE_SECTION);
 
+      // aria scrollbar
+      testRole("scrollbar", ROLE_SCROLLBAR);
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481114">Mozilla Bug 481114</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 469688</a>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 529289</a>
+  </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   
   <!-- "live" roles -->
   <table role="log" id="log_table">
     <tr><td>Table based log</td></tr>
@@ -129,10 +134,12 @@ https://bugzilla.mozilla.org/show_bug.cg
   <!-- test abstract input roles -->
   <div role="input" id="input">input</div>
   <div role="range" id="range">range</div>
   <div role="select" id="select">select</div>
   <!-- test abstract structure roles -->
   <div role="section" id="section">section</div>
   <div role="sectionhead" id="sectionhead">sectionhead</div>
 
+  <!-- aria scrollbar -->
+  <div role="scrollbar" id="scrollbar">scrollbar</div>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_events_valuechange.html
+++ b/accessible/tests/mochitest/test_events_valuechange.html
@@ -61,49 +61,60 @@
     }
 
     function doTests()
     {
       // Test initial values
       testValue("slider_vn", "5", 5, 0, 1000, 0);
       testValue("slider_vnvt", "plain", 0, 0, 5, 0);
       testValue("slider_vt", "hi", 0, 0, 3, 0);
+      testValue("scrollbar", "5", 5, 0, 1000, 0);
 
       // Test value change events
       gQueue = new eventQueue(nsIAccessibleEvent.EVENT_VALUE_CHANGE);
 
       gQueue.push(new changeValue("slider_vn", "6", undefined));
       gQueue.push(new changeValue("slider_vt", undefined, "hey!"));
       gQueue.push(new changeValue("slider_vnvt", "3", "sweet"));
+      gQueue.push(new changeValue("scrollbar", "6", undefined));
 
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=478032"
      title=" Fire delayed value changed event for aria-valuetext changes">
     Mozilla Bug 478032
   </a>
+  <a target="_blank"
+    href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289"
+    title="We dont expose new aria role 'scrollbar' and property aria-orientation">
+   Mozilla Bug 529289
+  </a>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <!-- ARIA sliders -->
   <div id="slider_vn" role="slider" aria-valuenow="5"
-    aria-valuemin="0" aria-valuemax="1000">slider</div>
+       aria-valuemin="0" aria-valuemax="1000">slider</div>
 
   <div id="slider_vt" role="slider" aria-valuetext="hi"
-    aria-valuemin="0" aria-valuemax="3">greeting slider</div>
+       aria-valuemin="0" aria-valuemax="3">greeting slider</div>
 
   <div id="slider_vnvt" role="slider" aria-valuenow="0" aria-valuetext="plain"
-    aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
+       aria-valuemin="0" aria-valuemax="5">sweetness slider</div>
+
+  <!-- ARIA scrollbar -->
+  <div id="scrollbar" role="scrollbar" aria-valuenow="5"
+       aria-valuemin="0" aria-valuemax="1000">slider</div>
 </body>
 </html>
--- a/accessible/tests/mochitest/test_states.html
+++ b/accessible/tests/mochitest/test_states.html
@@ -88,16 +88,21 @@
       testStates("aria_link_anchor", STATE_SELECTABLE);
 
       // some weak landmarks
       testStates("aria_main_link", STATE_LINKED);
       testStates("aria_navigation_link", STATE_LINKED);
       testStates("aria_main_anchor", STATE_SELECTABLE);
       testStates("aria_navigation_anchor", STATE_SELECTABLE);
 
+      // scrollbar
+      testStates("aria_scrollbar", 0, EXT_STATE_VERTICAL);
+      testStates("aria_hscrollbar", 0, EXT_STATE_HORIZONTAL);
+      testStates("aria_vscrollbar", 0, EXT_STATE_VERTICAL);
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
 </head>
@@ -178,10 +183,14 @@
   <a id="aria_main_link" role="main" href="foo">main</a>
   <a id="aria_navigation_link" role="navigation" href="foo">nav</a>
   
   <!-- landmarks: anchors -->
   <a id="aria_application_anchor" role="application" name="app_anchor">app</a>
   <a id="aria_main_anchor" role="main" name="main_anchor">main</a>
   <a id="aria_navigation_anchor" role="navigation" name="nav_anchor">nav</a>
 
+  <!-- scrollbar -->
+  <div id="aria_scrollbar" role="scrollbar">scrollbar</a>
+  <div id="aria_hscrollbar" role="scrollbar" aria-orientation="horizontal">horizontal scrollbar</a>
+  <div id="aria_vscrollbar" role="scrollbar" aria-orientation="vertical">vertical scrollbar</a>
 </body>
 </html>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -306,18 +306,23 @@ pref("browser.search.updateinterval", 6)
 // Whether or not microsummary and generator updates are enabled
 pref("browser.microsummary.enabled", true);
 pref("browser.microsummary.updateGenerators", true);
 
 // enable search suggestions by default
 pref("browser.search.suggest.enabled", true);
 
 pref("browser.sessionhistory.max_entries", 50);
+#ifndef WINCE
 pref("browser.history_expire_days", 180);
 pref("browser.history_expire_days_min", 90);
+#else
+pref("browser.history_expire_days", 90);
+pref("browser.history_expire_days_min", 45);
+#endif
 pref("browser.history_expire_sites", 40000);
 
 // handle links targeting new windows
 // 0=default window, 1=current window/tab, 2=new window, 3=new tab in most recent window
 pref("browser.link.open_newwindow", 3);
 
 // 0: no restrictions - divert everything
 // 1: don't divert window.open at all
@@ -893,16 +898,19 @@ pref("browser.sessionstore.interval", 60
 
 // Whether to use a panel that looks like an OS X sheet for customization
 #ifdef XP_MACOSX
 pref("toolbar.customization.usesheet", true);
 #else
 pref("toolbar.customization.usesheet", false);
 #endif
 
+pref("dom.ipc.plugins.enabled", false);
+pref("dom.ipc.tabs.enabled", false);
+
 #ifdef XP_WIN
 #ifndef WINCE
 pref("browser.taskbar.previews.enable", true);
 pref("browser.taskbar.previews.max", 20);
 pref("browser.taskbar.previews.cachetime", 20);
 pref("browser.taskbar.lists.enabled", true);
 pref("browser.taskbar.lists.frequent.enabled", true);
 pref("browser.taskbar.lists.recent.enabled", false);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2287,17 +2287,17 @@ function SetPageProxyState(aState)
   gProxyFavIcon.setAttribute("pageproxystate", aState);
 
   // the page proxy state is set to valid via OnLocationChange, which
   // gets called when we switch tabs.
   if (aState == "valid") {
     gLastValidURLStr = gURLBar.value;
     gURLBar.addEventListener("input", UpdatePageProxyState, false);
 
-    PageProxySetIcon(gBrowser.selectedBrowser.mIconURL);
+    PageProxySetIcon(gBrowser.getIcon());
   } else if (aState == "invalid") {
     gURLBar.removeEventListener("input", UpdatePageProxyState, false);
     PageProxyClearIcon();
   }
 }
 
 function PageProxySetIcon (aURL)
 {
@@ -3086,28 +3086,28 @@ const BrowserSearch = {
 
         win = window.openDialog("chrome://browser/content/", "_blank",
                                 "chrome,all,dialog=no", "about:blank");
         win.addEventListener("load", webSearchCallback, false);
       }
       return;
     }
 #endif
-    if (window.fullScreen)
+    var searchBar = this.searchBar;
+    if (searchBar && window.fullScreen)
       FullScreen.mouseoverToggle(true);
 
-    var searchBar = this.searchBar;
     if (isElementVisible(searchBar)) {
       searchBar.select();
       searchBar.focus();
     } else {
       var ss = Cc["@mozilla.org/browser/search-service;1"].
                getService(Ci.nsIBrowserSearchService);
       var searchForm = ss.defaultEngine.searchForm;
-      loadURI(searchForm, null, null, false);
+      openUILinkIn(searchForm, "current");
     }
   },
 
   /**
    * Loads a search results page, given a set of search terms. Uses the current
    * engine if the search bar is visible, or the default engine otherwise.
    *
    * @param searchText
@@ -3908,19 +3908,19 @@ var XULBrowserWindow = {
     // check the current value so we don't trigger an attribute change
     // and cause needless (slow!) UI updates
     if (this.statusText != text) {
       this.statusTextField.label = text;
       this.statusText = text;
     }
   },
   
-  onLinkIconAvailable: function (aBrowser) {
+  onLinkIconAvailable: function (aBrowser, aIconURL) {
     if (gProxyFavIcon && gBrowser.userTypedValue === null)
-      PageProxySetIcon(aBrowser.mIconURL); // update the favicon in the URL bar
+      PageProxySetIcon(aIconURL); // update the favicon in the URL bar
   },
 
   onProgressChange: function (aWebProgress, aRequest,
                               aCurSelfProgress, aMaxSelfProgress,
                               aCurTotalProgress, aMaxTotalProgress) {
     // Check this._busyUI to be safe, because we don't want to update
     // the progress meter when restoring a page from bfcache.
     if (aMaxTotalProgress > 0 && this._busyUI) {
@@ -3975,17 +3975,17 @@ var XULBrowserWindow = {
         this.stopCommand.removeAttribute("disabled");
       }
     }
     else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
       if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
         if (aWebProgress.DOMWindow == content) {
           if (aRequest)
             this.endDocumentLoad(aRequest, aStatus);
-          if (!gBrowser.mTabbedMode && !gBrowser.selectedBrowser.mIconURL)
+          if (!gBrowser.mTabbedMode && !gBrowser.getIcon())
             gBrowser.useDefaultIcon(gBrowser.selectedTab);
         }
       }
 
       // This (thanks to the filter) is a network stop or the last
       // request stop outside of loading the document, stop throbbers
       // and progress bars and such
       if (aRequest) {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -695,38 +695,48 @@
 
             this.updateIcon(aTab);
 
             if (browser == this.mCurrentBrowser) {
               for (let i = 0; i < this.mProgressListeners.length; i++) {
                 let p = this.mProgressListeners[i];
                 if ('onLinkIconAvailable' in p)
                   try {
-                    p.onLinkIconAvailable(browser);
+                    p.onLinkIconAvailable(browser, browser.mIconURL);
                   } catch (e) {
                     // don't inhibit other listeners
                     Components.utils.reportError(e);
                   }
               }
             }
 
             for (let i = 0; i < this.mTabsProgressListeners.length; i++) {
               let p = this.mTabsProgressListeners[i];
               if ('onLinkIconAvailable' in p)
                 try {
-                  p.onLinkIconAvailable(browser);
+                  p.onLinkIconAvailable(browser, browser.mIconURL);
                 } catch (e) {
                   // don't inhibit other listeners
                   Components.utils.reportError(e);
                 }
             }
           ]]>
         </body>
       </method>
 
+      <method name="getIcon">
+        <parameter name="aTab"/>
+        <body>
+          <![CDATA[
+            let browser = aTab ? this.getBrowserForTab(aTab) : this.selectedBrowser;
+            return browser.mIconURL;
+          ]]>
+        </body>
+      </method>
+
       <method name="updateIcon">
         <parameter name="aTab"/>
         <body>
           <![CDATA[
             var browser = this.getBrowserForTab(aTab);
             if (!aTab.hasAttribute("busy") && browser.mIconURL)
               aTab.setAttribute("image", browser.mIconURL);
             else
--- a/browser/base/content/test/browser_bug477014.js
+++ b/browser/base/content/test/browser_bug477014.js
@@ -71,16 +71,16 @@ function test() {
           newWindow.removeEventListener("load", arguments.callee, false);
         }
         newWindow.addEventListener("load", onLoad, false);
       }, 0);
       return;
     }
 
     is(newWindow.gBrowser.selectedTab.hasAttribute("busy"), true);
-    is(newWindow.gBrowser.selectedTab.linkedBrowser.mIconURL,iconURLSpec);
+    is(newWindow.gBrowser.getIcon(), iconURLSpec);
     newWindow.close();
     finish();
   }
 
   gBrowser.addEventListener("pageshow", onPageShow, false);
   tabToDetach = gBrowser.addTab(testPage);
 }
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -311,16 +311,28 @@ BrowserGlue.prototype = {
 
     this._observerService
         .notifyObservers(null, "browser-ui-startup-complete", "");
   },
 
   // profile shutdown handler (contains profile cleanup routines)
   _onProfileShutdown: function() 
   {
+#ifdef WINCE
+    // If there's a pending update, clear cache to free up disk space.
+    try {
+      let um = Cc["@mozilla.org/updates/update-manager;1"].
+               getService(Ci.nsIUpdateManager);
+      if (um.activeUpdate && um.activeUpdate.state == "pending") {
+        let cacheService = Cc["@mozilla.org/network/cache-service;1"].
+                           getService(Ci.nsICacheService);
+        cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
+      }
+    } catch (e) { }
+#endif
     this._shutdownPlaces();
     this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
     this._isIdleObserver = false;
     this._sanitizer.onShutdown();
   },
 
   // Browser startup complete. All initial windows have opened.
   _onBrowserStartup: function()
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_viewsource.js
@@ -97,17 +97,16 @@ function test() {
       ww.registerNotification(observer);
 
       gBrowser.addTabsProgressListener({
         onLocationChange: function() {},
         onProgressChange: function() {},
         onSecurityChange: function() {},
         onStatusChange: function() {},
         onRefreshAttempted: function() {},
-        onLinkIconAvailable: function() {},
         onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
           if (aStateFlags & (Ci.nsIWebProgressListener.STATE_STOP |
                              Ci.nsIWebProgressListener.STATE_IS_WINDOW)) {
             gBrowser.removeTabsProgressListener(this);
 
             step3();
           }
         }
--- a/browser/components/search/content/engineManager.js
+++ b/browser/components/search/content/engineManager.js
@@ -221,17 +221,17 @@ var gEngineManagerDialog = {
                                              disableButtons || lastSelected);
     document.getElementById("cmd_editkeyword").setAttribute("disabled",
                                                             noSelection);
   }
 };
 
 function onDragEngineStart(event) {
   var selectedIndex = gEngineView.selectedIndex;
-  if (selectedIndex > 0) {
+  if (selectedIndex >= 0) {
     event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString());
     event.dataTransfer.effectAllowed = "move";
   }
 }
 
 // "Operation" objects
 function EngineMoveOp(aEngineClone, aNewIndex) {
   if (!aEngineClone)
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -67,21 +67,27 @@
 /* :::::::: Constants and Helpers ::::::::::::::: */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const STATE_RUNNING_STR = "running";
+const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
+
+XPCOMUtils.defineLazyServiceGetter(this, "ConsoleSvc",
+  "@mozilla.org/consoleservice;1", "nsIConsoleService");
+
+XPCOMUtils.defineLazyServiceGetter(this, "ObserverSvc",
+  "@mozilla.org/observer-service;1", "nsIObserverService");
 
 function debug(aMsg) {
   aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
-  Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
-                                     .logStringMessage(aMsg);
+  ConsoleSvc.logStringMessage(aMsg);
 }
 
 /* :::::::: The Service ::::::::::::::: */
 
 function SessionStartup() {
 }
 
 SessionStartup.prototype = {
@@ -140,59 +146,54 @@ SessionStartup.prototype = {
       this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
     else if (!lastSessionCrashed && doResumeSession)
       this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
     else
       this._iniString = null; // reset the state string
 
     if (this._sessionType != Ci.nsISessionStartup.NO_SESSION) {
       // wait for the first browser window to open
-      var observerService = Cc["@mozilla.org/observer-service;1"].
-                            getService(Ci.nsIObserverService);
-      observerService.addObserver(this, "domwindowopened", true);
-      observerService.addObserver(this, "browser:purge-session-history", true);
+      ObserverSvc.addObserver(this, "domwindowopened", true);
+      ObserverSvc.addObserver(this, "browser:purge-session-history", true);
     }
   },
 
   /**
    * Handle notifications
    */
   observe: function sss_observe(aSubject, aTopic, aData) {
-    var observerService = Cc["@mozilla.org/observer-service;1"].
-                          getService(Ci.nsIObserverService);
-
     switch (aTopic) {
     case "app-startup": 
-      observerService.addObserver(this, "final-ui-startup", true);
-      observerService.addObserver(this, "quit-application", true);
+      ObserverSvc.addObserver(this, "final-ui-startup", true);
+      ObserverSvc.addObserver(this, "quit-application", true);
       break;
     case "final-ui-startup": 
-      observerService.removeObserver(this, "final-ui-startup");
-      observerService.removeObserver(this, "quit-application");
+      ObserverSvc.removeObserver(this, "final-ui-startup");
+      ObserverSvc.removeObserver(this, "quit-application");
       this.init();
       break;
     case "quit-application":
       // no reason for initializing at this point (cf. bug 409115)
-      observerService.removeObserver(this, "final-ui-startup");
-      observerService.removeObserver(this, "quit-application");
+      ObserverSvc.removeObserver(this, "final-ui-startup");
+      ObserverSvc.removeObserver(this, "quit-application");
       break;
     case "domwindowopened":
       var window = aSubject;
       var self = this;
       window.addEventListener("load", function() {
         self._onWindowOpened(window);
         window.removeEventListener("load", arguments.callee, false);
       }, false);
       break;
     case "browser:purge-session-history":
       // reset all state on sanitization
       this._iniString = null;
       this._sessionType = Ci.nsISessionStartup.NO_SESSION;
       // no need in repeating this, since startup state won't change
-      observerService.removeObserver(this, "browser:purge-session-history");
+      ObserverSvc.removeObserver(this, "browser:purge-session-history");
       break;
     }
   },
 
   /**
    * Removes the default arguments from the first browser window
    * (and removes the "domwindowopened" observer afterwards).
    */
@@ -215,20 +216,18 @@ SessionStartup.prototype = {
      * launching a non-default browser window, so we shouldn't remove the
      * window's arguments.
      */
     var defaultArgs = Cc["@mozilla.org/browser/clh;1"].
                       getService(Ci.nsIBrowserHandler).defaultArgs;
     if (aWindow.arguments && aWindow.arguments[0] &&
         aWindow.arguments[0] == defaultArgs)
       aWindow.arguments[0] = null;
-    
-    var observerService = Cc["@mozilla.org/observer-service;1"].
-                          getService(Ci.nsIObserverService);
-    observerService.removeObserver(this, "domwindowopened");
+
+    ObserverSvc.removeObserver(this, "domwindowopened");
   },
 
 /* ........ Public API ................*/
 
   /**
    * Get the session state as a string
    */
   get state() {
@@ -258,50 +257,50 @@ SessionStartup.prototype = {
    *
    * @param aFile is any nsIFile
    * @returns a session state string
    */
   _readStateFile: function sss_readStateFile(aFile) {
     var stateString = Cc["@mozilla.org/supports-string;1"].
                         createInstance(Ci.nsISupportsString);
     stateString.data = this._readFile(aFile) || "";
-    
-    var observerService = Cc["@mozilla.org/observer-service;1"].
-                          getService(Ci.nsIObserverService);
-    observerService.notifyObservers(stateString, "sessionstore-state-read", "");
-    
+
+    ObserverSvc.notifyObservers(stateString, "sessionstore-state-read", "");
+
     return stateString.data;
   },
 
   /**
    * reads a file into a string
    * @param aFile
    *        nsIFile
    * @returns string
    */
   _readFile: function sss_readFile(aFile) {
     try {
       var stream = Cc["@mozilla.org/network/file-input-stream;1"].
                    createInstance(Ci.nsIFileInputStream);
       stream.init(aFile, 0x01, 0, 0);
       var cvstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
                      createInstance(Ci.nsIConverterInputStream);
-      cvstream.init(stream, "UTF-8", 1024, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-      
-      var content = "";
+
+      var fileSize = stream.available();
+      if (fileSize > MAX_FILE_SIZE)
+        throw "SessionStartup: sessionstore.js was not processed because it was too large.";
+
+      cvstream.init(stream, "UTF-8", fileSize, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
       var data = {};
-      while (cvstream.readString(4096, data)) {
-        content += data.value;
-      }
+      cvstream.readString(fileSize, data);
+      var content = data.value;
       cvstream.close();
-      
+
       return content.replace(/\r\n?/g, "\n");
     }
     catch (ex) { Components.utils.reportError(ex); }
-    
+
     return null;
   },
 
   /* ........ QueryInterface .............. */
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference,
                                           Ci.nsISessionStartup]),
   classDescription: "Browser Session Startup Service",
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -111,28 +111,52 @@ const CAPABILITIES = [
 ];
 
 #ifndef XP_WIN
 #define BROKEN_WM_Z_ORDER
 #endif
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-function debug(aMsg) {
-  aMsg = ("SessionStore: " + aMsg).replace(/\S{80}/g, "$&\n");
-  Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
-                                     .logStringMessage(aMsg);
-}
-
-__defineGetter__("NetUtil", function() {
-  delete this.NetUtil;
+XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
   Cu.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
+XPCOMUtils.defineLazyServiceGetter(this, "ConsoleSvc",
+  "@mozilla.org/consoleservice;1", "nsIConsoleService");
+
+XPCOMUtils.defineLazyServiceGetter(this, "CookieSvc",
+  "@mozilla.org/cookiemanager;1", "nsICookieManager2");
+
+#ifdef MOZ_CRASH_REPORTER
+XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
+  "@mozilla.org/xre/app-info;1", "nsICrashReporter");
+#endif
+
+XPCOMUtils.defineLazyServiceGetter(this, "IOSvc",
+  "@mozilla.org/network/io-service;1", "nsIIOService");
+
+XPCOMUtils.defineLazyServiceGetter(this, "ObserverSvc",
+  "@mozilla.org/observer-service;1", "nsIObserverService");
+
+XPCOMUtils.defineLazyServiceGetter(this, "SecuritySvc",
+  "@mozilla.org/scriptsecuritymanager;1", "nsIScriptSecurityManager");
+
+XPCOMUtils.defineLazyServiceGetter(this, "WindowMediator",
+  "@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator");
+
+XPCOMUtils.defineLazyServiceGetter(this, "WindowWatcher",
+  "@mozilla.org/embedcomp/window-watcher;1", "nsIWindowWatcher");
+
+function debug(aMsg) {
+  aMsg = ("SessionStore: " + aMsg).replace(/\S{80}/g, "$&\n");
+  ConsoleSvc.logStringMessage(aMsg);
+}
+
 /* :::::::: The Service ::::::::::::::: */
 
 function SessionStoreService() {
 }
 
 SessionStoreService.prototype = {
   classDescription: "Browser Session Store Service",
   contractID: "@mozilla.org/browser/sessionstore;1",
@@ -204,21 +228,18 @@ SessionStoreService.prototype = {
         this.onLoad(aWindow);
       return;
     }
 
     this._prefBranch = Cc["@mozilla.org/preferences-service;1"].
                        getService(Ci.nsIPrefService).getBranch("browser.");
     this._prefBranch.QueryInterface(Ci.nsIPrefBranch2);
 
-    this._observerService = Cc["@mozilla.org/observer-service;1"].
-                            getService(Ci.nsIObserverService);
-
     OBSERVING.forEach(function(aTopic) {
-      this._observerService.addObserver(this, aTopic, true);
+      ObserverSvc.addObserver(this, aTopic, true);
     }, this);
 
     var pbs = Cc["@mozilla.org/privatebrowsing;1"].
               getService(Ci.nsIPrivateBrowsingService);
     this._inPrivateBrowsing = pbs.privateBrowsingEnabled;
 
     // get interval from prefs - used often, so caching/observing instead of fetching on-demand
     this._interval = this._prefBranch.getIntPref("sessionstore.interval");
@@ -603,17 +624,17 @@ SessionStoreService.prototype = {
         delete this._initialState;
         
         // _loadState changed from "stopped" to "running"
         // force a save operation so that crashes happening during startup are correctly counted
         this.saveState(true);
       }
       else {
         // Nothing to restore, notify observers things are complete.
-        this._observerService.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
+        ObserverSvc.notifyObservers(null, NOTIFY_WINDOWS_RESTORED, "");
         
         // the next delayed save request should execute immediately
         this._lastSaveTime -= this._interval;
       }
     }
     // this window was opened by _openWindowWithState
     else if (!this._isWindowLoaded(aWindow)) {
       let followUp = this._statesToRestore[aWindow.__SS_restoreID].windows.length == 1;
@@ -1379,19 +1400,17 @@ SessionStoreService.prototype = {
           domain = uri.prePath;
       }
       catch (ex) { /* this throws for host-less URIs (such as about: or jar:) */ }
       if (storageData[domain] || !(aFullData || this._checkPrivacyLevel(uri.schemeIs("https"))))
         continue;
 
       let storage, storageItemCount = 0;
       try {
-        var principal = Cc["@mozilla.org/scriptsecuritymanager;1"].
-                        getService(Ci.nsIScriptSecurityManager).
-                        getCodebasePrincipal(uri);
+        var principal = SecuritySvc.getCodebasePrincipal(uri);
 
         // Using getSessionStorageForPrincipal instead of getSessionStorageForURI
         // just to be able to pass aCreate = false, that avoids creation of the
         // sessionStorage object for the page earlier than the page really
         // requires it. It was causing problems while accessing a storage when
         // a page later changed its domain.
         storage = aDocShell.getSessionStorageForPrincipal(principal, false);
         if (storage)
@@ -1631,28 +1650,27 @@ SessionStoreService.prototype = {
       // aHost, aPath, and aName as keys
       if (!aHash[aHost])
         aHash[aHost] = {};
       if (!aHash[aHost][aPath])
         aHash[aHost][aPath] = {};
       aHash[aHost][aPath][aName] = aCookie;
     }
 
-    var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
     // collect the cookies per window
     for (var i = 0; i < aWindows.length; i++)
       aWindows[i].cookies = [];
 
     var jscookies = {};
     var _this = this;
     // MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
     var MAX_EXPIRY = Math.pow(2, 62);
     aWindows.forEach(function(aWindow) {
       for (var host in aWindow._hosts) {
-        var list = cm.getCookiesFromHost(host);
+        var list = CookieSvc.getCookiesFromHost(host);
         while (list.hasMoreElements()) {
           var cookie = list.getNext().QueryInterface(Ci.nsICookie2);
           if (cookie.isSession && _this._checkPrivacyLevel(cookie.isSecure)) {
             // use the cookie's host, path, and name as keys into a hash,
             // to make sure we serialize each cookie only once
             if (!(cookie.host in jscookies &&
                   cookie.path in jscookies[cookie.host] &&
                   cookie.name in jscookies[cookie.host][cookie.path])) {
@@ -1766,17 +1784,20 @@ SessionStoreService.prototype = {
         total.unshift(lastClosedWindowsCopy.shift())
       } while (total[0].isPopup)
     }
 #endif
 
     if (activeWindow) {
       this.activeWindowSSiCache = activeWindow.__SSi || "";
     }
-    ix = this.activeWindowSSiCache ? windows.indexOf(this.activeWindowSSiCache) : -1;
+    ix = windows.indexOf(this.activeWindowSSiCache);
+    // We don't want to restore focus to a minimized window.
+    if (ix != -1 && total[ix].sizemode == "minimized")
+      ix = -1;
 
     return { windows: total, selectedWindow: ix + 1, _closedWindows: lastClosedWindowsCopy };
   },
 
   /**
    * serialize session data for a window 
    * @param aWindow
    *        Window reference
@@ -2155,29 +2176,27 @@ SessionStoreService.prototype = {
    *        Object containing serialized history data for a URL
    * @param aIdMap
    *        Hash for ensuring unique frame IDs
    * @returns nsISHEntry
    */
   _deserializeHistoryEntry: function sss_deserializeHistoryEntry(aEntry, aIdMap) {
     var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
                   createInstance(Ci.nsISHEntry);
-    
-    var ioService = Cc["@mozilla.org/network/io-service;1"].
-                    getService(Ci.nsIIOService);
-    shEntry.setURI(ioService.newURI(aEntry.url, null, null));
+
+    shEntry.setURI(IOSvc.newURI(aEntry.url, null, null));
     shEntry.setTitle(aEntry.title || aEntry.url);
     if (aEntry.subframe)
       shEntry.setIsSubFrame(aEntry.subframe || false);
     shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;
     if (aEntry.contentType)
       shEntry.contentType = aEntry.contentType;
-    if (aEntry.referrer) 
-      shEntry.referrerURI = ioService.newURI(aEntry.referrer, null, null);
-    
+    if (aEntry.referrer)
+      shEntry.referrerURI = IOSvc.newURI(aEntry.referrer, null, null);
+
     if (aEntry.cacheKey) {
       var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
                      createInstance(Ci.nsISupportsPRUint32);
       cacheKey.data = aEntry.cacheKey;
       shEntry.cacheKey = cacheKey;
     }
 
     if (aEntry.ID) {
@@ -2219,20 +2238,18 @@ SessionStoreService.prototype = {
       ownerInput.setData(binaryData, binaryData.length);
       var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
                          createInstance(Ci.nsIObjectInputStream);
       binaryStream.setInputStream(ownerInput);
       try { // Catch possible deserialization exceptions
         shEntry.owner = binaryStream.readObject(true);
       } catch (ex) { debug(ex); }
     } else if (aEntry.ownerURI) { // Firefox 2
-      var uriObj = ioService.newURI(aEntry.ownerURI, null, null);
-      shEntry.owner = Cc["@mozilla.org/scriptsecuritymanager;1"].
-                      getService(Ci.nsIScriptSecurityManager).
-                      getCodebasePrincipal(uriObj);
+      var uriObj = IOSvc.newURI(aEntry.ownerURI, null, null);
+      shEntry.owner = SecuritySvc.getCodebasePrincipal(uriObj);
     }
     
     if (aEntry.children && shEntry instanceof Ci.nsISHContainer) {
       for (var i = 0; i < aEntry.children.length; i++) {
         //XXXzpao Wallpaper patch for bug 514751
         if (!aEntry.children[i].url)
           continue;
         shEntry.AddChild(this._deserializeHistoryEntry(aEntry.children[i], aIdMap), i);
@@ -2245,19 +2262,18 @@ SessionStoreService.prototype = {
   /**
    * restores all sessionStorage "super cookies"
    * @param aStorageData
    *        Storage data to be restored
    * @param aDocShell
    *        A tab's docshell (containing the sessionStorage)
    */
   _deserializeSessionStorage: function sss_deserializeSessionStorage(aStorageData, aDocShell) {
-    let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
     for (let url in aStorageData) {
-      let uri = ioService.newURI(url, null, null);
+      let uri = IOSvc.newURI(url, null, null);
       let storage = aDocShell.getSessionStorageForURI(uri);
       for (let key in aStorageData[url]) {
         try {
           storage.setItem(key, aStorageData[url][key]);
         }
         catch (ex) { Cu.reportError(ex); } // throws e.g. for URIs that can't have sessionStorage
       }
     }
@@ -2493,25 +2509,25 @@ SessionStoreService.prototype = {
         if (parsed && /^https?:\/\/([^\/]+)/.test(aCookies["domain" + i]))
           converted.push({
             host: RegExp.$1, path: parsed[3], name: parsed[1], value: parsed[2],
             secure: parsed[4], httponly: parsed[5]
           });
       }
       aCookies = converted;
     }
-    
-    var cookieManager = Cc["@mozilla.org/cookiemanager;1"].
-                        getService(Ci.nsICookieManager2);
+
     // MAX_EXPIRY should be 2^63-1, but JavaScript can't handle that precision
     var MAX_EXPIRY = Math.pow(2, 62);
     for (i = 0; i < aCookies.length; i++) {
       var cookie = aCookies[i];
       try {
-        cookieManager.add(cookie.host, cookie.path || "", cookie.name || "", cookie.value, !!cookie.secure, !!cookie.httponly, true, "expiry" in cookie ? cookie.expiry : MAX_EXPIRY);
+        CookieSvc.add(cookie.host, cookie.path || "", cookie.name || "",
+                      cookie.value, !!cookie.secure, !!cookie.httponly, true,
+                      "expiry" in cookie ? cookie.expiry : MAX_EXPIRY);
       }
       catch (ex) { Cu.reportError(ex); } // don't let a single cookie stop recovering
     }
   },
 
 /* ........ Disk Access .............. */
 
   /**
@@ -2573,18 +2589,17 @@ SessionStoreService.prototype = {
    * write a state object to disk
    */
   _saveStateObject: function sss_saveStateObject(aStateObj) {
     var stateString = Cc["@mozilla.org/supports-string;1"].
                         createInstance(Ci.nsISupportsString);
     // parentheses are for backwards compatibility with Firefox 2.0 and 3.0
     stateString.data = "(" + this._toJSONString(aStateObj) + ")";
 
-    this._observerService.notifyObservers(stateString,
-                                          "sessionstore-state-write", "");
+    ObserverSvc.notifyObservers(stateString, "sessionstore-state-write", "");
 
     // don't touch the file if an observer has deleted all state data
     if (stateString.data)
       this._writeFile(this._sessionFile, stateString.data);
 
     this._lastSaveTime = Date.now();
   },
 
@@ -2610,54 +2625,50 @@ SessionStoreService.prototype = {
 
   /**
    * call a callback for all currently opened browser windows
    * (might miss the most recent one)
    * @param aFunc
    *        Callback each window is passed to
    */
   _forEachBrowserWindow: function sss_forEachBrowserWindow(aFunc) {
-    var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].
-                         getService(Ci.nsIWindowMediator);
-    var windowsEnum = windowMediator.getEnumerator("navigator:browser");
+    var windowsEnum = WindowMediator.getEnumerator("navigator:browser");
     
     while (windowsEnum.hasMoreElements()) {
       var window = windowsEnum.getNext();
       if (window.__SSi && !window.closed) {
         aFunc.call(this, window);
       }
     }
   },
 
   /**
    * Returns most recent window
    * @returns Window reference
    */
   _getMostRecentBrowserWindow: function sss_getMostRecentBrowserWindow() {
-    var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
-             getService(Ci.nsIWindowMediator);
-
-    var win = wm.getMostRecentWindow("navigator:browser");
+    var win = WindowMediator.getMostRecentWindow("navigator:browser");
     if (!win)
       return null;
     if (!win.closed)
       return win;
 
 #ifdef BROKEN_WM_Z_ORDER
     win = null;
-    var windowsEnum = wm.getEnumerator("navigator:browser");
+    var windowsEnum = WindowMediator.getEnumerator("navigator:browser");
     // this is oldest to newest, so this gets a bit ugly
     while (windowsEnum.hasMoreElements()) {
       let nextWin = windowsEnum.getNext();
       if (!nextWin.closed)
         win = nextWin;
     }
     return win;
 #else
-    var windowsEnum = wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
+    var windowsEnum =
+      WindowMediator.getZOrderDOMWindowEnumerator("navigator:browser", true);
     while (windowsEnum.hasMoreElements()) {
       win = windowsEnum.getNext();
       if (!win.closed)
         return win;
     }
     return null;
 #endif
   },
@@ -2686,27 +2697,34 @@ SessionStoreService.prototype = {
    * @param aState
    *        Object containing session data
    */
   _openWindowWithState: function sss_openWindowWithState(aState) {
     var argString = Cc["@mozilla.org/supports-string;1"].
                     createInstance(Ci.nsISupportsString);
     argString.data = "";
 
-    //XXXzeniko shouldn't it be possible to set the window's dimensions here (as feature)?
-    var window = Cc["@mozilla.org/embedcomp/window-watcher;1"].
-                 getService(Ci.nsIWindowWatcher).
-                 openWindow(null, this._prefBranch.getCharPref("chromeURL"), "_blank",
-                            "chrome,dialog=no,all", argString);
-    
+    // Build feature string
+    let features = "chrome,dialog=no,all";
+    let winState = aState.windows[0];
+    WINDOW_ATTRIBUTES.forEach(function(aFeature) {
+      // Use !isNaN as an easy way to ignore sizemode and check for numbers
+      if (aFeature in winState && !isNaN(winState[aFeature]))
+        features += "," + aFeature + "=" + winState[aFeature];
+    });
+
+    var window =
+      WindowWatcher.openWindow(null, this._prefBranch.getCharPref("chromeURL"),
+                               "_blank", features, argString);
+
     do {
       var ID = "window" + Math.random();
     } while (ID in this._statesToRestore);
     this._statesToRestore[(window.__SS_restoreID = ID)] = aState;
-    
+
     return window;
   },
 
   /**
    * Whether or not to resume session, if not recovering from a crash.
    * @returns bool
    */
   _doResumeSession: function sss_doResumeSession() {
@@ -2788,46 +2806,40 @@ SessionStoreService.prototype = {
   },
 
   /**
    * Get nsIURI from string
    * @param string
    * @returns nsIURI
    */
   _getURIFromString: function sss_getURIFromString(aString) {
-    var ioService = Cc["@mozilla.org/network/io-service;1"].
-                    getService(Ci.nsIIOService);
-    return ioService.newURI(aString, null, null);
+    return IOSvc.newURI(aString, null, null);
   },
 
   /**
    * Annotate a breakpad crash report with the currently selected tab's URL.
    */
   _updateCrashReportURL: function sss_updateCrashReportURL(aWindow) {
-    if (!Ci.nsICrashReporter) {
-      // if breakpad isn't built, don't bother next time at all
-      this._updateCrashReportURL = function(aWindow) {};
-      return;
-    }
+#ifdef MOZ_CRASH_REPORTER
     try {
       var currentURI = aWindow.gBrowser.currentURI.clone();
       // if the current URI contains a username/password, remove it
-      try { 
-        currentURI.userPass = ""; 
-      } 
+      try {
+        currentURI.userPass = "";
+      }
       catch (ex) { } // ignore failures on about: URIs
 
-      var cr = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsICrashReporter);
-      cr.annotateCrashReport("URL", currentURI.spec);
+      CrashReporter.annotateCrashReport("URL", currentURI.spec);
     }
     catch (ex) {
       // don't make noise when crashreporter is built but not enabled
       if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED)
         debug(ex);
     }
+#endif
   },
 
   /**
    * @param aState is a session state
    * @param aRecentCrashes is the number of consecutive crashes
    * @returns whether a restore page will be needed for the session state
    */
   _needsRestorePage: function sss_needsRestorePage(aState, aRecentCrashes) {
@@ -2891,17 +2903,17 @@ SessionStoreService.prototype = {
     return jsonString;
   },
 
   _sendRestoreCompletedNotifications: function sss_sendRestoreCompletedNotifications() {
     if (this._restoreCount) {
       this._restoreCount--;
       if (this._restoreCount == 0) {
         // This was the last window restored at startup, notify observers.
-        this._observerService.notifyObservers(null,
+        ObserverSvc.notifyObservers(null,
           this._browserSetState ? NOTIFY_BROWSER_STATE_RESTORED : NOTIFY_WINDOWS_RESTORED,
           "");
         this._browserSetState = false;
       }
     }
   },
 
   /**
@@ -2972,19 +2984,19 @@ SessionStoreService.prototype = {
                     createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     // Asynchronously copy the data to the file.
     var istream = converter.convertToInputStream(aData);
     var self = this;
     NetUtil.asyncCopy(istream, ostream, function(rc) {
       if (Components.isSuccessCode(rc)) {
-        self._observerService.notifyObservers(null,
-                                              "sessionstore-state-write-complete",
-                                              "");
+        ObserverSvc.notifyObservers(null,
+                                    "sessionstore-state-write-complete",
+                                    "");
       }
     });
   }
 };
 
 let XPathHelper = {
   // these two hashes should be kept in sync
   namespaceURIs:     { "xhtml": "http://www.w3.org/1999/xhtml" },
--- a/browser/components/sessionstore/test/browser/Makefile.in
+++ b/browser/components/sessionstore/test/browser/Makefile.in
@@ -105,13 +105,14 @@ include $(topsrcdir)/config/rules.mk
 	browser_485563.js \
 	browser_490040.js \
 	browser_491168.js \
 	browser_491577.js \
 	browser_493467.js \
 	browser_495495.js \
 	browser_514751.js \
 	browser_522545.js \
+	browser_524745.js \
 	browser_528776.js \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/components/sessionstore/test/browser/browser_354894.js
+++ b/browser/components/sessionstore/test/browser/browser_354894.js
@@ -438,31 +438,63 @@ function test() {
    * @note: Non-Mac only
    */
   function testOpenCloseRestoreFromPopup(nextFn) {
     setupTestAndRun(function(newWin) {
       setupTestAndRun(function(newWin2) {
         newWin.BrowserTryToCloseWindow();
         newWin2.BrowserTryToCloseWindow();
 
+        browserWindowsCount([0, 1], "browser windows while running testOpenCloseRestoreFromPopup");
+
         newWin = undoCloseWindow(0);
+        newWin.addEventListener("load", function () {
+          info(["testOpenCloseRestoreFromPopup: newWin loaded", newWin.closed, newWin.document]);
+          var ds = newWin.delayedStartup;
+          newWin.delayedStartup = function () {
+            info(["testOpenCloseRestoreFromPopup: newWin delayedStartup", newWin.closed, newWin.document]);
+            ds.apply(newWin, arguments);
+          };
+        }, false);
+        newWin.addEventListener("unload", function () {
+          info("testOpenCloseRestoreFromPopup: newWin unloaded");
+/*
+          var data;
+          try {
+            data = Cc["@mozilla.org/browser/sessionstore;1"]
+                     .getService(Ci.nsISessionStore)
+                     .getWindowState(newWin);
+          } catch (e) { }
+          ok(!data, "getWindowState should not have data about newWin");
+*/
+        }, false);
 
         newWin2 = openDialog(location, "_blank", CHROME_FEATURES);
         newWin2.addEventListener("load", function() {
           newWin2.removeEventListener("load", arguments.callee, true);
           executeSoon(function() {
             is(newWin2.gBrowser.browsers.length, 1,
                "Did not restore, as undoCloseWindow() was last called");
             is(TEST_URLS.indexOf(newWin2.gBrowser.browsers[0].currentURI.spec), -1,
                "Did not restore, as undoCloseWindow() was last called (2)");
 
+            browserWindowsCount([2, 3], "browser windows while running testOpenCloseRestoreFromPopup");
+
+            info([newWin.closed, newWin.__SSi, newWin.__SS_restoreID, newWin.__SS_dyingCache]);
+
             // Cleanup
             newWin.close();
             newWin2.close();
 
+            info([newWin.closed, newWin.__SSi, newWin.__SS_restoreID, newWin.__SS_dyingCache]);
+
+            browserWindowsCount([0, 1], "browser windows while running testOpenCloseRestoreFromPopup");
+
+            info([newWin.closed, newWin.__SSi, newWin.__SS_restoreID, newWin.__SS_dyingCache]);
+
             // Next please
             executeSoon(nextFn);
           });
         }, true);
       });
     });
   }
 
@@ -531,17 +563,17 @@ function test() {
     testOpenCloseNormal(function () {
       browserWindowsCount([0, 1], "browser windows after testOpenCloseNormal");
       testOpenClosePrivateBrowsing(function () {
         browserWindowsCount([0, 1], "browser windows after testOpenClosePrivateBrowsing");
         testOpenCloseWindowAndPopup(function () {
           browserWindowsCount([0, 1], "browser windows after testOpenCloseWindowAndPopup");
           testOpenCloseOnlyPopup(function () {
             browserWindowsCount([0, 1], "browser windows after testOpenCloseOnlyPopup");
-            testOpenCloseRestoreFromPopup (function () {
+            testOpenCloseRestoreFromPopup(function () {
               browserWindowsCount([0, 1], "browser windows after testOpenCloseRestoreFromPopup");
               testNotificationCount(function () {
                 cleanupTestsuite();
                 browserWindowsCount(1, "browser windows after testNotificationCount");
                 finish();
               });
             });
           });
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser/browser_524745.js
@@ -0,0 +1,98 @@
+/* ***** 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 sessionstore test code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Paul O’Shannessy <paul@oshannessy.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 ***** */
+
+function browserWindowsCount() {
+  let count = 0;
+  let e = Cc["@mozilla.org/appshell/window-mediator;1"]
+            .getService(Ci.nsIWindowMediator)
+            .getEnumerator("navigator:browser");
+  while (e.hasMoreElements()) {
+    if (!e.getNext().closed)
+      ++count;
+  }
+  return count;
+}
+
+function test() {
+  /** Test for Bug 524745 **/
+  is(browserWindowsCount(), 1, "Only one browser window should be open initially");
+
+  let ss = Cc["@mozilla.org/browser/sessionstore;1"].
+           getService(Ci.nsISessionStore);
+  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+           getService(Ci.nsIWindowWatcher);
+  let uniqKey = "bug524745";
+  let uniqVal = Date.now();
+
+  waitForExplicitFinish();
+
+  let window_B = openDialog(location, "_blank", "chrome,all,dialog=no");
+  window_B.addEventListener("load", function(aEvent) {
+    window_B.removeEventListener("load", arguments.callee, false);
+
+      waitForFocus(function() {
+        // Add identifying information to window_B
+        ss.setWindowValue(window_B, uniqKey, uniqVal);
+        let state = JSON.parse(ss.getBrowserState());
+        let selectedWindow = state.windows[state.selectedWindow - 1];
+        is(selectedWindow.extData && selectedWindow.extData[uniqKey], uniqVal,
+           "selectedWindow is window_B");
+
+        // Now minimize window_B. The selected window shouldn't have the secret data
+        window_B.minimize();
+        waitForFocus(function() {
+          state = JSON.parse(ss.getBrowserState());
+          selectedWindow = state.windows[state.selectedWindow - 1];
+          ok(!selectedWindow.extData || !selectedWindow.extData[uniqKey],
+             "selectedWindow is not window_B after minimizing it");
+
+          // Now minimize the last open window (assumes no other tests left windows open)
+          window.minimize();
+          state = JSON.parse(ss.getBrowserState());
+          is(state.selectedWindow, 0,
+             "selectedWindow should be 0 when all windows are minimized");
+
+          // Cleanup
+          window.restore();
+          window_B.close();
+          is(browserWindowsCount(), 1,
+             "Only one browser window should be open eventually");
+          finish();
+        });
+      }, window_B);
+  }, false);
+}
--- a/browser/components/wintaskbar/WindowsJumpLists.jsm
+++ b/browser/components/wintaskbar/WindowsJumpLists.jsm
@@ -336,17 +336,17 @@ var WinTaskbarJumpList =
 
     // XXX where can we grab this from in the build? Do we need to?
     file.append("firefox.exe");
 
     var handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"].
                      createInstance(Ci.nsILocalHandlerApp);
     handlerApp.executable = file;
     // handlers default to the leaf name if a name is not specified
-    if (name.length != 0)
+    if (name && name.length != 0)
       handlerApp.name = name;
     handlerApp.detailedDescription = description;
     handlerApp.appendParameter(args);
 
     var item = Cc["@mozilla.org/windows-jumplistshortcut;1"].
                createInstance(Ci.nsIJumpListShortcut);
     item.app = handlerApp;
     item.iconIndex = icon;
--- a/browser/components/wintaskbar/WindowsPreviewPerTab.jsm
+++ b/browser/components/wintaskbar/WindowsPreviewPerTab.jsm
@@ -512,19 +512,19 @@ TabWindow.prototype = {
   onProgressChange: function () {
   },
   onSecurityChange: function () {
   },
   onStateChange: function () {
   },
   onStatusChange: function () {
   },
-  onLinkIconAvailable: function (aBrowser) {
+  onLinkIconAvailable: function (aBrowser, aIconURL) {
     let self = this;
-    getFaviconAsImage(aBrowser.mIconURL, function (img) {
+    getFaviconAsImage(aIconURL, function (img) {
       let index = self.tabbrowser.browsers.indexOf(aBrowser);
       // Only add it if we've found the index.  The tab could have closed!
       if (index != -1)
         self.previews[index].icon = img;
     });
   }
 }
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -45,16 +45,19 @@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 #ifdef XP_MACOSX
 @BINPATH@/XUL
 #else
 @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
 #endif
+#ifdef MOZ_IPC
+@BINPATH@/mozilla-runtime@BIN_SUFFIX@
+#endif
 #ifdef WINCE
 @BINPATH@/mozce_shunt.dll
 #elifdef XP_WIN32
 #ifndef MOZ_MEMORY
 @BINPATH@/Microsoft.VC80.CRT.manifest
 @BINPATH@/msvcm80.dll
 @BINPATH@/msvcp80.dll
 @BINPATH@/msvcr80.dll
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -551,16 +551,19 @@ toolbar[mode="full"] .toolbarbutton-menu
 }
 #stop-button[disabled="true"] {
   list-style-image: url("moz-icon://stock/gtk-stop?size=toolbar&state=disabled");
 }
 
 #home-button {
   list-style-image: url("moz-icon://stock/gtk-home?size=toolbar");
 }
+#home-button[disabled="true"] {
+  list-style-image: url("moz-icon://stock/gtk-home?size=toolbar&state=disabled");
+}
 
 #downloads-button {
   -moz-image-region: rect(0px 24px 24px 0px);
 }
 
 #history-button {
   -moz-image-region: rect(0px 48px 24px 24px);
 }
@@ -673,16 +676,20 @@ toolbar[iconsize="small"] #reload-button
 toolbar[iconsize="small"] #reload-button[disabled="true"] {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu&state=disabled");
 }
 
 toolbar[iconsize="small"] #home-button ,
 #home-button.bookmark-item {
   list-style-image: url("moz-icon://stock/gtk-home?size=menu");
 }
+toolbar[iconsize="small"] #home-button[disabled="true"],
+#home-button.bookmark-item[disabled="true"] {
+  list-style-image: url("moz-icon://stock/gtk-home?size=menu&state=disabled");
+}
 
 toolbar[iconsize="small"] #downloads-button {
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 toolbar[iconsize="small"] #history-button {
   -moz-image-region: rect(0px 32px 16px 16px);
 }
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -577,16 +577,19 @@ toolbar[iconsize="small"] #unified-back-
 }
 
 
 /* ----- DEFAULT HOME BUTTON ----- */	
 
 #home-button {
   -moz-image-region: rect(0px, 180px, 23px, 144px);
 }
+#home-button[disabled="true"] {
+  -moz-image-region: rect(23px, 180px, 46px, 144px) !important;
+}
 #home-button:hover:active {
   -moz-image-region: rect(46px, 180px, 69px, 144px);
 }
 
 #home-button.bookmark-item {
   list-style-image: url("chrome://browser/skin/home.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px) !important;
 }
old mode 100644
new mode 100755
index 76199d9f3d88e26749cbefd7acb3814bf0d87be1..8094d8a1facd9540ad4f14b9ea1fcb794f63361c
GIT binary patch
literal 44506
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
old mode 100644
new mode 100755
index f3607750398621f20c586a144f8748d4e22063b1..9da3ea5abbdf8e354e652b8d4da8b89c06041b69
GIT binary patch
literal 16153
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
BRNw#r
old mode 100644
new mode 100755
index ef903824786d128fe3568240fe8a9bc7bc0e8fd0..c9b39175e8a0aaa57aa00751e82e2356582b756d
GIT binary patch
literal 22459
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
Shg~6n@MoZFbg5Pw7WqFqBMjI8
old mode 100644
new mode 100755
index 6535fa297d7515abfb74f34aa385f4141ecc2080..418d2e977f46ab1e8fda991b2b900baf0cdf6f07
GIT binary patch
literal 44453
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
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -399,16 +399,19 @@ toolbar[iconsize="small"][mode="icons"] 
 /* home button */
 
 #home-button {
   -moz-image-region: rect(0px 120px 24px 96px);
 }
 #home-button:hover {
   -moz-image-region: rect(24px 120px 48px 96px);
 }
+#home-button[disabled="true"] {
+  -moz-image-region: rect(48px 120px 72px 96px);
+}
 
 /* download manager button */
 
 #downloads-button {
   -moz-image-region: rect(0px 144px 24px 120px);
 }
 #downloads-button:hover {
   -moz-image-region: rect(24px 144px 48px 120px);
@@ -594,16 +597,20 @@ toolbar[iconsize="small"] #reload-button
 toolbar[iconsize="small"] #home-button,
 #home-button.bookmark-item {
   -moz-image-region: rect(0px 80px 16px 64px);
 }
 toolbar[iconsize="small"] #home-button:hover,
 #home-button.bookmark-item:hover {
   -moz-image-region: rect(16px 80px 32px 64px);
 }
+toolbar[iconsize="small"] #home-button[disabled="true"],
+#home-button.bookmark-item[disabled="true"] {
+  -moz-image-region: rect(32px 80px 48px 64px);
+}
 
 /* download manager button */
 
 toolbar[iconsize="small"] #downloads-button {
   -moz-image-region: rect(0px 96px 16px 80px);
 }
 toolbar[iconsize="small"] #downloads-button:hover {
   -moz-image-region: rect(16px 96px 32px 80px);
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -44,16 +44,17 @@ import logging
 import os
 import re
 import select
 import shutil
 import signal
 import subprocess
 import sys
 import threading
+import tempfile
 
 from automationutils import checkForCrashes
 
 """
 Runs the browser from a script, and provides useful utilities
 for setting up the browser environment.
 """
 
@@ -451,16 +452,17 @@ def environment(env = None, xrePath = DI
 
   env['GNOME_DISABLE_CRASH_DIALOG'] = "1"
   return env
 
 if IS_WIN32:
   import ctypes, time, msvcrt
   PeekNamedPipe = ctypes.windll.kernel32.PeekNamedPipe
   GetLastError = ctypes.windll.kernel32.GetLastError
+
   def readWithTimeout(f, timeout):
     """Try to read a line of output from the file object |f|.
     |f| must be a  pipe, like the |stdout| member of a subprocess.Popen
     object created with stdout=PIPE. If no output
     is received within |timeout| seconds, return a blank line.
     Returns a tuple (line, did_timeout), where |did_timeout| is True
     if the read timed out, and False otherwise."""
     if timeout is None:
@@ -477,27 +479,75 @@ if IS_WIN32:
         else:
           log.error("readWithTimeout got error: %d", err)
       if l > 0:
         # we're assuming that the output is line-buffered,
         # which is not unreasonable
         return (f.readline(), False)
       time.sleep(0.01)
     return ('', True)
+
+  def isPidAlive(pid):
+    STILL_ACTIVE = 259
+    PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
+    pHandle = ctypes.windll.kernel32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid)
+    if not pHandle:
+      return False
+    pExitCode = ctypes.wintypes.DWORD()
+    ctypes.windll.kernel32.GetExitCodeProcess(pHandle, ctypes.byref(pExitCode))
+    ctypes.windll.kernel32.CloseHandle(pHandle)
+    if (pExitCode.value == STILL_ACTIVE):
+      return True
+    else:
+      return False
+
+  def killPid(pid):
+    PROCESS_TERMINATE = 0x0001
+    pHandle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, 0, pid)
+    if not pHandle:
+      return
+    success = ctypes.windll.kernel32.TerminateProcess(pHandle, 1)
+    ctypes.windll.kernel32.CloseHandle(pHandle)
+
 else:
+  import errno
+
   def readWithTimeout(f, timeout):
     """Try to read a line of output from the file object |f|. If no output
     is received within |timeout| seconds, return a blank line.
     Returns a tuple (line, did_timeout), where |did_timeout| is True
     if the read timed out, and False otherwise."""
     (r, w, e) = select.select([f], [], [], timeout)
     if len(r) == 0:
       return ('', True)
     return (f.readline(), False)
 
+  def isPidAlive(pid):
+    try:
+      # kill(pid, 0) checks for a valid PID without actually sending a signal
+      # The method throws OSError if the PID is invalid, which we catch below.
+      os.kill(pid, 0)
+
+      # Wait on it to see if it's a zombie. This can throw OSError.ECHILD if
+      # the process terminates before we get to this point.
+      wpid, wstatus = os.waitpid(pid, os.WNOHANG)
+      if wpid == 0:
+        return True
+
+      return False
+    except OSError, err:
+      # Catch the errors we might expect from os.kill/os.waitpid, 
+      # and re-raise any others
+      if err.errno == errno.ESRCH or err.errno == errno.ECHILD:
+        return False
+      raise
+
+  def killPid(pid):
+    os.kill(pid, signal.SIGKILL)
+
 def triggerBreakpad(proc, utilityPath):
   """Attempt to kill this process in a way that triggers Breakpad crash
   reporting, if we know how for this platform. Otherwise just .kill() it."""
   if CRASHREPORTER:
     if UNIXISH:
       # SEGV will get picked up by Breakpad's signal handler
       os.kill(proc.pid, signal.SIGSEGV)
       return
@@ -519,16 +569,19 @@ def runApp(testURL, env, app, profileDir
            xrePath = DIST_BIN, certPath = CERTS_SRC_DIR,
            debuggerInfo = None, symbolsPath = None,
            timeout = DEFAULT_TIMEOUT):
   "Run the app, log the duration it took to execute, return the status code."
 
   # copy env so we don't munge the caller's environment
   env = dict(env);
   env["NO_EM_RESTART"] = "1"
+  tmpfd, processLog = tempfile.mkstemp(suffix='pidlog')
+  os.close(tmpfd)
+  env["MOZ_PROCESS_LOG"] = processLog
 
   if IS_TEST_BUILD and runSSLTunnel:
     # create certificate database for the profile
     certificateStatus = fillCertificateDB(profileDir, certPath, utilityPath, xrePath)
     if certificateStatus != 0:
       log.info("TEST-UNEXPECTED FAIL | automation.py | Certificate integration failed")
       return certificateStatus
 
@@ -609,15 +662,37 @@ def runApp(testURL, env, app, profileDir
   if status != 0 and not didTimeout:
     log.info("TEST-UNEXPECTED-FAIL | automation.py | Exited with code %d during test run", status)
   if stackFixerProcess is not None:
     fixerStatus = stackFixerProcess.wait()
     if fixerStatus != 0 and not didTimeout:
       log.info("TEST-UNEXPECTED-FAIL | automation.py | Stack fixer process exited with code %d during test run", fixerStatus)
   log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
 
+  # Do a final check for zombie child processes.
+  if not os.path.exists(processLog):
+    log.info('INFO | automation.py | PID log not found: %s', processLog)
+  else:
+    log.info('INFO | automation.py | Reading PID log: %s', processLog)
+    processList = []
+    pidRE = re.compile(r'launched child process (\d+)$')
+    processLogFD = open(processLog)
+    for line in processLogFD:
+      log.info(line.rstrip())
+      m = pidRE.search(line)
+      if m:
+        processList.append(int(m.group(1)))
+    processLogFD.close()
+    os.unlink(processLog)
+
+    for processPID in processList:
+      log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID)
+      if isPidAlive(processPID):
+        log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID)
+        killPid(processPID)
+
   if checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath):
     status = -1
 
   if IS_TEST_BUILD and runSSLTunnel:
     ssltunnelProcess.kill()
 
   return status
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -195,87 +195,125 @@ def dumpLeakLog(leakLogFile, filter = Fa
   # Only |XPCOM_MEM_LEAK_LOG| reports can be actually filtered out.
   # Only check whether an actual leak was reported.
   if filter and not "0 TOTAL " in leakReport:
     return
 
   # Simply copy the log.
   log.info(leakReport.rstrip("\n"))
 
-def processLeakLog(leakLogFile, leakThreshold = 0):
-  """Process the leak log, parsing it.
-
-  Use this function if you want an additional PASS/FAIL summary.
-  It must be used with the |XPCOM_MEM_BLOAT_LOG| environment variable.
+def processSingleLeakFile(leakLogFileName, PID, processType, leakThreshold):
+  """Process a single leak log, corresponding to the specified
+  process PID and type.
   """
 
-  if not os.path.exists(leakLogFile):
-    log.info("WARNING | automationutils.processLeakLog() | refcount logging is off, so leaks can't be detected!")
-    return
-
   #                  Per-Inst  Leaked      Total  Rem ...
   #   0 TOTAL              17     192  419115886    2 ...
   # 833 nsTimerImpl        60     120      24726    2 ...
   lineRe = re.compile(r"^\s*\d+\s+(?P<name>\S+)\s+"
                       r"(?P<size>-?\d+)\s+(?P<bytesLeaked>-?\d+)\s+"
                       r"-?\d+\s+(?P<numLeaked>-?\d+)")
 
-  leaks = open(leakLogFile, "r")
+  processString = ""
+  if PID and processType:
+    processString = "| %s process %s " % (processType, PID)
+  leaks = open(leakLogFileName, "r")
   for line in leaks:
     matches = lineRe.match(line)
     if (matches and
         int(matches.group("numLeaked")) == 0 and
         matches.group("name") != "TOTAL"):
       continue
     log.info(line.rstrip())
   leaks.close()
 
-  leaks = open(leakLogFile, "r")
+  leaks = open(leakLogFileName, "r")
   seenTotal = False
+  crashedOnPurpose = False
   prefix = "TEST-PASS"
   for line in leaks:
+    if line.find("purposefully crash") > -1:
+      crashedOnPurpose = True
     matches = lineRe.match(line)
     if not matches:
       continue
     name = matches.group("name")
     size = int(matches.group("size"))
     bytesLeaked = int(matches.group("bytesLeaked"))
     numLeaked = int(matches.group("numLeaked"))
     if size < 0 or bytesLeaked < 0 or numLeaked < 0:
-      log.info("TEST-UNEXPECTED-FAIL | automationutils.processLeakLog() | negative leaks caught!")
+      log.info("TEST-UNEXPECTED-FAIL %s| automationutils.processLeakLog() | negative leaks caught!" %
+               processString)
       if name == "TOTAL":
         seenTotal = True
     elif name == "TOTAL":
       seenTotal = True
       # Check for leaks.
       if bytesLeaked < 0 or bytesLeaked > leakThreshold:
         prefix = "TEST-UNEXPECTED-FAIL"
-        leakLog = "TEST-UNEXPECTED-FAIL | automationutils.processLeakLog() | leaked" \
-                  " %d bytes during test execution" % bytesLeaked
+        leakLog = "TEST-UNEXPECTED-FAIL %s| automationutils.processLeakLog() | leaked" \
+                  " %d bytes during test execution" % (processString, bytesLeaked)
       elif bytesLeaked > 0:
-        leakLog = "TEST-PASS | automationutils.processLeakLog() | WARNING leaked" \
-                  " %d bytes during test execution" % bytesLeaked
+        leakLog = "TEST-PASS %s| automationutils.processLeakLog() | WARNING leaked" \
+                  " %d bytes during test execution" % (processString, bytesLeaked)
       else:
-        leakLog = "TEST-PASS | automationutils.processLeakLog() | no leaks detected!"
+        leakLog = "TEST-PASS %s| automationutils.processLeakLog() | no leaks detected!" \
+                  % processString
       # Remind the threshold if it is not 0, which is the default/goal.
       if leakThreshold != 0:
         leakLog += " (threshold set at %d bytes)" % leakThreshold
       # Log the information.
       log.info(leakLog)
     else:
       if numLeaked != 0:
         if numLeaked > 1:
           instance = "instances"
           rest = " each (%s bytes total)" % matches.group("bytesLeaked")
         else:
           instance = "instance"
           rest = ""
-        log.info("%(prefix)s | automationutils.processLeakLog() | leaked %(numLeaked)d %(instance)s of %(name)s "
+        log.info("%(prefix)s %(process)s| automationutils.processLeakLog() | leaked %(numLeaked)d %(instance)s of %(name)s "
                  "with size %(size)s bytes%(rest)s" %
                  { "prefix": prefix,
+                   "process": processString,
                    "numLeaked": numLeaked,
                    "instance": instance,
                    "name": name,
                    "size": matches.group("size"),
                    "rest": rest })
   if not seenTotal:
-    log.info("TEST-UNEXPECTED-FAIL | automationutils.processLeakLog() | missing output line for total leaks!")
+    if crashedOnPurpose:
+      log.info("INFO | automationutils.processLeakLog() | process %s was " \
+               "deliberately crashed and thus has no leak log" % PID)
+    else:
+      log.info("TEST-UNEXPECTED-FAIL %s| automationutils.processLeakLog() | missing output line for total leaks!" %
+             processString)
   leaks.close()
+
+
+def processLeakLog(leakLogFile, leakThreshold = 0):
+  """Process the leak log, including separate leak logs created
+  by child processes.
+
+  Use this function if you want an additional PASS/FAIL summary.
+  It must be used with the |XPCOM_MEM_BLOAT_LOG| environment variable.
+  """
+
+  if not os.path.exists(leakLogFile):
+    log.info("WARNING | automationutils.processLeakLog() | refcount logging is off, so leaks can't be detected!")
+    return
+
+  (leakLogFileDir, leakFileBase) = os.path.split(leakLogFile)
+  pidRegExp = re.compile(r".*?_([a-z]*)_pid(\d*)$")
+  if leakFileBase[-4:] == ".log":
+    leakFileBase = leakFileBase[:-4]
+    pidRegExp = re.compile(r".*?_([a-z]*)_pid(\d*).log$")
+
+  for fileName in os.listdir(leakLogFileDir):
+    if fileName.find(leakFileBase) != -1:
+      thisFile = os.path.join(leakLogFileDir, fileName)
+      processPID = 0
+      processType = None
+      m = pidRegExp.search(fileName)
+      if m:
+        processType = m.group(1)
+        processPID = m.group(2)
+      processSingleLeakFile(thisFile, processPID, processType, leakThreshold)
--- a/build/unix/run-mozilla.sh
+++ b/build/unix/run-mozilla.sh
@@ -54,26 +54,33 @@ echo ""
 echo "  options:"
 echo ""
 echo "    -g                   Run in debugger."
 echo "    --debug"
 echo ""
 echo "    -d debugger          Debugger to use."
 echo "    --debugger debugger"
 echo ""
+echo "    -a debugger_args     Arguments passed to [debugger]."
+echo "    --debugger-args debugger_args"
+echo ""
 echo "  Examples:"
 echo ""
 echo "  Run the mozilla-bin binary"
 echo ""
 echo "    ${cmdname} mozilla-bin"
 echo ""
 echo "  Debug the mozilla-bin binary in gdb"
 echo ""
 echo "    ${cmdname} -g mozilla-bin -d gdb"
 echo ""
+echo "  Run mozilla-bin under valgrind with arguments"
+echo ""
+echo "    ${cmdname} -g -d valgrind -a '--tool=memcheck --leak-check=full' mozilla-bin"
+echo ""
 	return 0
 }
 ##########################################################################
 moz_bail()
 {
 	message=$1
 	echo
 	echo "$cmdname: $message"
@@ -157,39 +164,40 @@ moz_debug_program()
 	else
 		debugger=`moz_get_debugger`
 	fi
     if [ -x "$debugger" ] 
     then
 # If you are not using ddd, gdb and know of a way to convey the arguments 
 # over to the prog then add that here- Gagan Saksena 03/15/00
         case `basename $debugger` in
-            gdb) echo "$debugger --args $prog" ${1+"$@"}
-                exec "$debugger" --args "$prog" ${1+"$@"}
+            gdb) echo "$debugger $moz_debugger_args --args $prog" ${1+"$@"}
+                exec "$debugger" $moz_debugger_args --args "$prog" ${1+"$@"}
 		exitcode=$?
                 ;;
-            ddd) echo "$debugger --gdb -- --args $prog" ${1+"$@"}
-		exec "$debugger" --gdb -- --args "$prog" ${1+"$@"}
+            ddd) echo "$debugger $moz_debugger_args --gdb -- --args $prog" ${1+"$@"}
+		exec "$debugger" $moz_debugger_args --gdb -- --args "$prog" ${1+"$@"}
 		exitcode=$?
                 ;;
-            *) echo "$debugger $prog ${1+"$@"}"
-                exec $debugger "$prog" ${1+"$@"}
+            *) echo "$debugger $moz_debugger_args $prog ${1+"$@"}"
+                exec $debugger $moz_debugger_args "$prog" ${1+"$@"}
 		exitcode=$?
                 ;;
         esac
     else
         moz_bail "Could not find a debugger on your system."
     fi
 }
 ##########################################################################
 ##
 ## Command line arg defaults
 ##
 moz_debug=0
 moz_debugger=""
+moz_debugger_args=""
 #
 ##
 ## Parse the command line
 ##
 while [ $# -gt 0 ]
 do
   case $1 in
     -g | --debug)
@@ -200,16 +208,25 @@ do
       moz_debugger=$2;
       if [ "${moz_debugger}" != "" ]; then
 	shift 2
       else
         echo "-d requires an argument"
         exit 1
       fi
       ;;
+    -a | --debugger-args)
+      moz_debugger_args=$2;
+      if [ "${moz_debugger_args}" != "" ]; then
+	shift 2
+      else
+        echo "-a requires an argument"
+        exit 1
+      fi
+      ;;
     *)
       break;
       ;;
   esac
 done
 #
 ##
 ## Program name given in $1
@@ -358,16 +375,17 @@ then
   echo "     LIBRARY_PATH=$LIBRARY_PATH"
   echo "       SHLIB_PATH=$SHLIB_PATH"
   echo "          LIBPATH=$LIBPATH"
   echo "       ADDON_PATH=$ADDON_PATH"
   echo "      MOZ_PROGRAM=$MOZ_PROGRAM"
   echo "      MOZ_TOOLKIT=$MOZ_TOOLKIT"
   echo "        moz_debug=$moz_debug"
   echo "     moz_debugger=$moz_debugger"
+  echo "moz_debugger_args=$moz_debugger_args"
 fi
 #
 export MOZILLA_FIVE_HOME LD_LIBRARY_PATH
 export SHLIB_PATH LIBPATH LIBRARY_PATH ADDON_PATH DYLD_LIBRARY_PATH
 
 if [ $moz_debug -eq 1 ]
 then
 	moz_debug_program ${1+"$@"}
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -99,16 +99,18 @@ MOZ_DEBUG_ENABLE_DEFS		= @MOZ_DEBUG_ENAB
 MOZ_DEBUG_DISABLE_DEFS	= @MOZ_DEBUG_DISABLE_DEFS@
 MOZ_DEBUG_FLAGS	= @MOZ_DEBUG_FLAGS@
 MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
 MOZ_DBGRINFO_MODULES	= @MOZ_DBGRINFO_MODULES@
 MOZ_EXTENSIONS  = @MOZ_EXTENSIONS@
 MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
 MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
 MOZ_JSDEBUGGER  = @MOZ_JSDEBUGGER@
+MOZ_IPC 	= @MOZ_IPC@
+MOZ_IPDL_TESTS 	= @MOZ_IPDL_TESTS@
 MOZ_LEAKY	= @MOZ_LEAKY@
 MOZ_MEMORY      = @MOZ_MEMORY@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_TRACEVIS    = @MOZ_TRACEVIS@
 DEHYDRA_PATH    = @DEHYDRA_PATH@
--- a/configure.in
+++ b/configure.in
@@ -461,21 +461,17 @@ fi
 
 dnl Special win32 checks
 dnl ========================================================
 case "$target" in
 *-wince|*-winmo)
     WINVER=500
     ;;
 *)
-    if test -n "$GNU_CC"; then  
-        WINVER=501
-    else    
-        WINVER=500
-    fi
+    WINVER=502
     ;;
 esac
 
 dnl Target the Windows 7 SDK by default
 WINSDK_TARGETVER=601
 
 MOZ_ARG_WITH_STRING(windows-version,
 [  --with-windows-version=WINSDK_TARGETVER
@@ -4238,17 +4234,17 @@ dnl are defined in build/autoconf/altopt
 
 dnl ========================================================
 dnl =
 dnl = Check for external package dependencies
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(External Packages)
 
-MOZ_ENABLE_LIBXUL=
+MOZ_ENABLE_LIBXUL=1
 
 MOZ_ARG_WITH_STRING(libxul-sdk,
 [  --with-libxul-sdk=PFX   Use the libXUL SDK at <PFX>],
   LIBXUL_SDK_DIR=$withval)
 
 if test "$LIBXUL_SDK_DIR" = "yes"; then
     AC_MSG_ERROR([--with-libxul-sdk must specify a path])
 elif test -n "$LIBXUL_SDK_DIR" -a "$LIBXUL_SDK_DIR" != "no"; then
@@ -4565,16 +4561,17 @@ BUILD_STATIC_LIBS=
 ENABLE_TESTS=1
 MOZ_ACTIVEX_SCRIPTING_SUPPORT=
 MOZ_BRANDING_DIRECTORY=
 MOZ_OFFICIAL_BRANDING=
 MOZ_DBGRINFO_MODULES=
 MOZ_FEEDS=1
 MOZ_IMG_DECODERS_DEFAULT="png gif jpeg bmp icon"
 MOZ_IMG_ENCODERS_DEFAULT="png jpeg"
+MOZ_IPC=1
 MOZ_JAVAXPCOM=
 MOZ_JSDEBUGGER=1
 MOZ_JSLOADER=1
 MOZ_MATHML=1
 MOZ_MORK=1
 MOZ_MORKREADER=
 MOZ_AUTH_EXTENSION=1
 MOZ_NO_ACTIVEX_SUPPORT=1
@@ -5291,16 +5288,59 @@ dnl = JS Debugger XPCOM component (js/js
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(jsd,
 [  --disable-jsd           Disable JavaScript debug library],
     MOZ_JSDEBUGGER=,
     MOZ_JSDEBUGGER=1)
 
 
 dnl ========================================================
+dnl = Disable IPC support for tabs and plugins
+dnl ========================================================
+case "${target}" in
+*-apple-darwin*)
+    MOZ_IPC=
+    ;;
+*-wince*)
+    MOZ_IPC=
+    ;;
+esac
+
+MOZ_ARG_DISABLE_BOOL(ipc,
+[  --disable-ipc           Disable IPC supports for tabs and plugins],
+    MOZ_IPC=,
+    MOZ_IPC=1)
+
+if test -n "$MOZ_IPC"; then
+    AC_DEFINE(MOZ_IPC)
+fi
+
+AC_SUBST(MOZ_IPC)
+
+dnl ========================================================
+dnl = Enable IPDL's "expensive" unit tests
+dnl ========================================================
+MOZ_IPDL_TESTS=
+
+MOZ_ARG_ENABLE_BOOL(ipdl-tests,
+[  --enable-ipdl-tests     Enable expensive IPDL tests],
+    MOZ_IPDL_TESTS=1,
+    MOZ_IPDL_TESTS=)
+
+if test -z "$MOZ_IPC" -a -n "$MOZ_IPDL_TESTS"; then
+    AC_MSG_ERROR([--enable-ipdl-tests requires --enable-ipc])
+fi
+
+if test -n "$MOZ_IPDL_TESTS"; then
+    AC_DEFINE(MOZ_IPDL_TESTS)
+fi
+
+AC_SUBST(MOZ_IPDL_TESTS)
+
+dnl ========================================================
 dnl = Disable plugin support
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(plugins,
 [  --disable-plugins       Disable plugins support],
     MOZ_PLUGINS=,
     MOZ_PLUGINS=1)
 
 dnl ========================================================
@@ -7180,16 +7220,17 @@ if test "$ac_nscap_nonconst_opeq_bug" = 
     AC_DEFINE(NSCAP_DONT_PROVIDE_NONCONST_OPEQ)
 fi
 fi # SKIP_COMPILER_CHECKS
 
 dnl ========================================================
 dnl C++ rtti
 dnl Should be smarter and check that the compiler does indeed have rtti
 dnl ========================================================
+
 MOZ_ARG_ENABLE_BOOL(cpp-rtti,
 [  --enable-cpp-rtti       Enable C++ RTTI ],
 [ _MOZ_USE_RTTI=1 ],
 [ _MOZ_USE_RTTI= ])
 
 if test "$_MOZ_USE_RTTI"; then
    _MOZ_RTTI_FLAGS=$_MOZ_RTTI_FLAGS_ON
 else
@@ -7291,34 +7332,33 @@ dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Static build options)
 
 MOZ_ARG_ENABLE_BOOL(static,
 [  --enable-static         Enable building of internal static libs],
     BUILD_STATIC_LIBS=1,
     BUILD_STATIC_LIBS=)
 
-dnl Disable libxul in debug builds, but not for xulrunner.
-if test -n "$MOZ_DEBUG" -a "$MOZ_BUILD_APP" != "xulrunner"; then
-   MOZ_ENABLE_LIBXUL=
-fi
-
 MOZ_ARG_ENABLE_BOOL(libxul,
 [  --enable-libxul         Enable building of libxul],
     MOZ_ENABLE_LIBXUL=1,
     MOZ_ENABLE_LIBXUL=)
 
 if test -n "$MOZ_STATIC_BUILD_UNSUPPORTED" -a -n "$BUILD_STATIC_LIBS"; then
 	AC_MSG_ERROR([--enable-static is not supported for building $MOZ_APP_NAME. You probably want --enable-libxul.])
 fi
 
 if test -n "$MOZ_ENABLE_LIBXUL" -a -n "$BUILD_STATIC_LIBS"; then
 	AC_MSG_ERROR([--enable-libxul is not compatible with --enable-static])
 fi
 
+if test -n "$MOZ_IPC" -a -z "$MOZ_ENABLE_LIBXUL"; then
+    AC_MSG_ERROR([--enable-ipc requires --enable-libxul])
+fi
+
 AC_SUBST(LIBXUL_LIBS)
 
 if test -n "$MOZ_ENABLE_LIBXUL"; then
     XPCOM_LIBS="$LIBXUL_LIBS"
     AC_DEFINE(MOZ_ENABLE_LIBXUL)
 else
     if test -n "$BUILD_STATIC_LIBS"; then
         AC_DEFINE(MOZ_STATIC_BUILD)
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -240,17 +240,23 @@ nsCrossSiteListenerProxy::CheckRequestAp
   NS_ENSURE_TRUE(http, NS_ERROR_DOM_BAD_URI);
 
   // Redirects aren't success-codes. But necko already checked that it was a
   // valid redirect.
   if (!aIsRedirect) {
     PRBool succeeded;
     rv = http->GetRequestSucceeded(&succeeded);
     NS_ENSURE_SUCCESS(rv, rv);
-    NS_ENSURE_TRUE(succeeded, NS_ERROR_DOM_BAD_URI);
+    if (!succeeded) {
+      PRUint32 responseStatus;
+      rv = http->GetResponseStatus(&responseStatus);
+      NS_ENSURE_SUCCESS(rv, rv);
+      NS_ENSURE_TRUE(mAllowedHTTPErrors.Contains(responseStatus),
+                     NS_ERROR_DOM_BAD_URI);
+    }
   }
 
   // Check the Access-Control-Allow-Origin header
   nsCAutoString allowedOriginHeader;
   rv = http->GetResponseHeader(
     NS_LITERAL_CSTRING("Access-Control-Allow-Origin"), allowedOriginHeader);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/base/src/nsCrossSiteListenerProxy.h
+++ b/content/base/src/nsCrossSiteListenerProxy.h
@@ -76,24 +76,30 @@ public:
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSICHANNELEVENTSINK
 
   // Must be called at startup.
   static void Startup();
 
+  void AllowHTTPResult(PRUint32 aResultCode)
+  {
+    mAllowedHTTPErrors.AppendElement(aResultCode);
+  }
+
 private:
   nsresult UpdateChannel(nsIChannel* aChannel);
   nsresult CheckRequestApproved(nsIRequest* aRequest, PRBool aIsRedirect);
 
   nsCOMPtr<nsIStreamListener> mOuterListener;
   nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
   nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
   PRBool mWithCredentials;
   PRBool mRequestApproved;
   PRBool mHasBeenCrossSite;
   PRBool mIsPreflight;
   nsCString mPreflightMethod;
   nsTArray<nsCString> mPreflightHeaders;
+  nsTArray<PRUint32> mAllowedHTTPErrors;
 };
 
 #endif
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -409,16 +409,17 @@ nsINode::GetSelectionRootContent(nsIPres
   if (presContext) {
     nsIEditor* editor = GetHTMLEditor(presContext);
     if (editor) {
       // This node is in HTML editor.
       nsIDocument* doc = GetCurrentDoc();
       if (!doc || doc->HasFlag(NODE_IS_EDITABLE) ||
           !HasFlag(NODE_IS_EDITABLE)) {
         nsIContent* editorRoot = GetEditorRootContent(editor);
+        NS_ENSURE_TRUE(editorRoot, nsnull);
         return nsContentUtils::IsInSameAnonymousTree(this, editorRoot) ?
                  editorRoot :
                  GetRootForContentSubtree(static_cast<nsIContent*>(this));
       }
       // If the current document is not editable, but current content is
       // editable, we should assume that the child of the nearest non-editable
       // ancestor is selection root.
       nsIContent* content = static_cast<nsIContent*>(this);
@@ -440,16 +441,17 @@ nsINode::GetSelectionRootContent(nsIPres
       content = doc->GetRootContent();
       if (!content)
         return nsnull;
     }
   }
 
   // This node might be in another subtree, if so, we should find this subtree's
   // root.  Otherwise, we can return the content simply.
+  NS_ENSURE_TRUE(content, nsnull);
   return nsContentUtils::IsInSameAnonymousTree(this, content) ?
            content : GetRootForContentSubtree(static_cast<nsIContent*>(this));
 }
 
 nsINodeList*
 nsINode::GetChildNodesList()
 {
   nsSlots *slots = GetSlots();
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -626,23 +626,26 @@ nsresult nsHTMLMediaElement::LoadResourc
   // after it is finished with the element.
   nsRefPtr<MediaLoadListener> loadListener = new MediaLoadListener(this);
   if (!loadListener) return NS_ERROR_OUT_OF_MEMORY;
 
   mChannel->SetNotificationCallbacks(loadListener);
 
   nsCOMPtr<nsIStreamListener> listener;
   if (ShouldCheckAllowOrigin()) {
-    listener = new nsCrossSiteListenerProxy(loadListener,
-                                            NodePrincipal(),
-                                            mChannel,
-                                            PR_FALSE,
-                                            &rv);
-    NS_ENSURE_SUCCESS(rv,rv);
-    if (!listener) return NS_ERROR_OUT_OF_MEMORY;
+    nsCrossSiteListenerProxy* crossSiteListener =
+      new nsCrossSiteListenerProxy(loadListener,
+                                   NodePrincipal(),
+                                   mChannel,
+                                   PR_FALSE,
+                                   &rv);
+    listener = crossSiteListener;
+    NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
+    NS_ENSURE_SUCCESS(rv, rv);
+    crossSiteListener->AllowHTTPResult(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE);
   } else {
     rv = nsContentUtils::GetSecurityManager()->
            CheckLoadURIWithPrincipal(NodePrincipal(),
                                      aURI,
                                      nsIScriptSecurityManager::STANDARD);
     NS_ENSURE_SUCCESS(rv,rv);
     listener = loadListener;
   }
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/nsMediaStream.cpp
@@ -54,17 +54,16 @@
 #include "nsHTMLMediaElement.h"
 #include "nsIDocument.h"
 #include "nsDOMError.h"
 #include "nsICachingChannel.h"
 #include "nsURILoader.h"
 
 #define HTTP_OK_CODE 200
 #define HTTP_PARTIAL_RESPONSE_CODE 206
-#define HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE 416
 
 using mozilla::TimeStamp;
 
 nsMediaChannelStream::nsMediaChannelStream(nsMediaDecoder* aDecoder,
     nsIChannel* aChannel, nsIURI* aURI)
   : nsMediaStream(aDecoder, aChannel, aURI),
     mOffset(0), mSuspendCount(0),
     mReopenOnError(PR_FALSE), mIgnoreClose(PR_FALSE),
@@ -420,23 +419,26 @@ nsresult nsMediaChannelStream::OpenChann
     nsCOMPtr<nsIStreamListener> listener = mListener.get();
 
     // Ensure that if we're loading cross domain, that the server is sending
     // an authorizing Access-Control header.
     nsHTMLMediaElement* element = mDecoder->GetMediaElement();
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
     if (element->ShouldCheckAllowOrigin()) {
       nsresult rv;
-      listener = new nsCrossSiteListenerProxy(mListener,
-                                              element->NodePrincipal(),
-                                              mChannel,
-                                              PR_FALSE,
-                                              &rv);
-      NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
+      nsCrossSiteListenerProxy* crossSiteListener =
+        new nsCrossSiteListenerProxy(mListener,
+                                     element->NodePrincipal(),
+                                     mChannel,
+                                     PR_FALSE,
+                                     &rv);
+      listener = crossSiteListener;
+      NS_ENSURE_TRUE(crossSiteListener, NS_ERROR_OUT_OF_MEMORY);
       NS_ENSURE_SUCCESS(rv, rv);
+      crossSiteListener->AllowHTTPResult(HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE);
     } else {
       nsresult rv = nsContentUtils::GetSecurityManager()->
         CheckLoadURIWithPrincipal(element->NodePrincipal(),
                                   mURI,
                                   nsIScriptSecurityManager::STANDARD);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
--- a/content/media/nsMediaStream.h
+++ b/content/media/nsMediaStream.h
@@ -48,16 +48,18 @@
 #include "prlock.h"
 #include "nsMediaCache.h"
 
 // For HTTP seeking, if number of bytes needing to be
 // seeked forward is less than this value then a read is
 // done rather than a byte range request.
 #define SEEK_VS_READ_THRESHOLD (32*1024)
 
+#define HTTP_REQUESTED_RANGE_NOT_SATISFIABLE_CODE 416
+
 class nsMediaDecoder;
 
 /**
  * This class is useful for estimating rates of data passing through
  * some channel. The idea is that activity on the channel "starts"
  * and "stops" over time. At certain times data passes through the
  * channel (usually while the channel is active; data passing through
  * an inactive channel is ignored). The GetRate() function computes
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -174,16 +174,17 @@ endif
 		$(NULL)
 
 # These tests need to be converted to be backend-independent. This list
 # is deprecated, do not add to it.
 ifdef MOZ_OGG
 _TEST_FILES += \
 		dynamic_redirect.sjs \
 		file_access_controls.html \
+		test_access_control.html \
 		test_bug448534.html \
 		test_bug468190.html \
 		test_bug486646.html \
 		test_bug493187.html \
 		test_bug495145.html \
 		test_bug495319.html \
 		test_closing_connections.html \
 		test_contentDuration1.html \
@@ -222,17 +223,16 @@ ifdef MOZ_OGG
 # test_videoDocumentTitle.html
 # Bug 493692:
 # test_autobuffer2.html
 ifneq ($(OS_ARCH),WINNT)
 # These tests are disabled on windows until we
 # figure out the random failures. See bug 475369 and bug 526323
 _TEST_FILES += \
 		test_timeupdate3.html \
-		test_access_control.html \
 		$(NULL)
 endif
 endif
 
 ifdef MOZ_OGG
 _TEST_FILES += \
 		test_can_play_type_ogg.html \
 		$(NULL)
--- a/content/media/test/file_access_controls.html
+++ b/content/media/test/file_access_controls.html
@@ -10,90 +10,91 @@ var gTests = [
   {
     // Test 0
     url: "redirect.sjs?http://example.com/tests/content/media/test/320x240.ogv",
     result: "error",
     description: "Won't load when redirected to different domain",
   },{
     // Test 1
     url: "redirect.sjs?http://example.com/tests/content/media/test/320x240.allow-origin.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load when redirected to different domain with allow-origin",
   },{
     // Test 2
     url: "redirect.sjs?http://test1.example.org/tests/content/media/test/320x240.ogv",
     result: "error",
     description: "Won't load when redirected to subdomain",
   },{
     // Test 3
     url: "redirect.sjs?http://test1.example.org/tests/content/media/test/320x240.allow-origin.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load when redirected to subdomain with allow-origin",
   },{
     // Test 4
     url: "redirect.sjs?http://example.org/tests/content/media/test/320x240.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load when redirected to same domain",
   },{
     // Test 5
     url: "http://example.org/tests/content/media/test/320x240.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load from same domain"
   },{
     // Test 6
     url: "http://example.org:8000/tests/content/media/test/320x240.ogv",
     result: "error",
     description: "Won't load from differnet port on same domain"
   },{
     // Test 7
     url: "http://example.org:8000/tests/content/media/test/320x240.allow-origin.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load from different port on same domain with allow-origin",
   },{
     // Test 8
     url: "http://example.com/tests/content/media/test/320x240.ogv",
     result: "error",
     description: "Won't load cross domain",
   },{
     // Test 9
     url: "http://example.com/tests/content/media/test/320x240.allow-origin.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load cross domain with allow-origin",
   },{
     // Test 10
     url: "http://test1.example.org/tests/content/media/test/320x240.allow-origin.ogv",
-    result: "loaded",
+    result: "loadeddata",
     description: "Can load from subdomain with allow-origin",
   },{
     // Test 11
     url: "http://test1.example.org/tests/content/media/test/320x240.ogv",
     result: "error",
     description: "Won't load from subdomain",
   }
 ];
 
 var gTestNum = 0;
-var gExpectedResult = null;
-var gTestDescription = null;
 var gVideo = null;
 var gTestedRemoved = false;
 var gOldPref;
 
-function result(code) {
-  //dump((gTestNum - 1) + ": " + code + "\n");
+function eventHandler(event) {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-  opener.is(code, gExpectedResult, gTestDescription);
+  //dump((gTestNum - 1) + ": " + event.type + "\n");
+  var video = event.target;
+  opener.is(event.type, video.expectedResult, video.testDescription +
+    (gTestedRemoved ? " (element not in document)" : " (element in document)"));
+  // Make sure any extra events cause an error
+  video.expectedResult = "<none>";
   nextTest();
 }
 
 function createVideo() {
   var v = document.createElement('video');
-  v.addEventListener('loadeddata', function(){result('loaded');}, false);
-  v.addEventListener('error', function(){result('error');}, false);
-  v.id = 'video';
+  v.addEventListener('loadeddata', eventHandler, false);
+  v.addEventListener('error', eventHandler, false);
   return v;
 }
 
 function load() {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   opener.is(window.location.href,
             "http://example.org/tests/content/media/test/file_access_controls.html",
             "We must be on a example.org:80");
@@ -107,39 +108,38 @@ function load() {
   opener.ok(branch!=null, "Get media pref branch");
   gOldPref = branch.getBoolPref("enforce_same_site_origin");
   branch.setBoolPref("enforce_same_site_origin", true);
   nextTest();
 }
 
 function nextTest() {
   //dump("nextTest() called, gTestNum="+gTestNum+" gTestedRemoved="+gTestedRemoved+"\n");
-  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   if (gTestNum == gTests.length) {
     //dump("gTestNum == gTests.length\n");
     if (!gTestedRemoved) {
       // Repeat all tests with element removed from doc, should get same result.
       gTestedRemoved = true;
       gTestNum = 0;
     } else {
       //dump("Exiting...\n");
       // We're done, exit the test.
       window.close();
       return;
     }
   }
-  gExpectedResult = gTests[gTestNum].result;
-  gTestDescription = gTests[gTestNum].description;
-  //dump("Starting test " + gTestNum + " at " + gTests[gTestNum].url + " expecting:" + gExpectedResult + "\n");
 
   if (gVideo && gVideo.parentNode)
     gVideo.parentNode.removeChild(gVideo);
   
   gVideo = createVideo();
+  gVideo.expectedResult = gTests[gTestNum].result;
+  gVideo.testDescription = gTests[gTestNum].description;
   gVideo.src = gTests[gTestNum].url;
+  //dump("Starting test " + gTestNum + " at " + gVideo.src + " expecting:" + gVideo.expectedResult + "\n");
   if (!gTestedRemoved) {
     document.body.appendChild(gVideo); 
     // Will cause load() to be invoked.
   } else {
     gVideo.load();
   }
   gTestNum++;
 }
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -1865,19 +1865,21 @@ nsXULTemplateBuilder::CompileTemplate(ns
         if (ni->Equals(nsGkAtoms::rule, kNameSpaceID_XUL)) {
             nsCOMPtr<nsIContent> action;
             nsXULContentUtils::FindChildByTag(rulenode,
                                               kNameSpaceID_XUL,
                                               nsGkAtoms::action,
                                               getter_AddRefs(action));
 
             if (action){
-                nsCOMPtr<nsIAtom> memberVariable;
-                DetermineMemberVariable(action, getter_AddRefs(memberVariable));
-                if (! memberVariable) continue;
+                nsCOMPtr<nsIAtom> memberVariable = mMemberVariable;
+                if (!memberVariable) {
+                    memberVariable = DetermineMemberVariable(action);
+                    if (!memberVariable) continue;
+                }
 
                 if (hasQuery) {
                     nsCOMPtr<nsIAtom> tag;
                     DetermineRDFQueryRef(aQuerySet->mQueryNode,
                                          getter_AddRefs(tag));
                     if (tag)
                         aQuerySet->SetTag(tag);
 
@@ -1989,19 +1991,21 @@ nsXULTemplateBuilder::CompileTemplate(ns
             if (! hasQuery)
                 continue;
 
             nsCOMPtr<nsIAtom> tag;
             DetermineRDFQueryRef(aQuerySet->mQueryNode, getter_AddRefs(tag));
             if (tag)
                 aQuerySet->SetTag(tag);
 
-            nsCOMPtr<nsIAtom> memberVariable;
-            DetermineMemberVariable(rulenode, getter_AddRefs(memberVariable));
-            if (! memberVariable) continue;
+            nsCOMPtr<nsIAtom> memberVariable = mMemberVariable;
+            if (!memberVariable) {
+                memberVariable = DetermineMemberVariable(rulenode);
+                if (!memberVariable) continue;
+            }
 
             nsCOMPtr<nsIDOMNode> query(do_QueryInterface(aQuerySet->mQueryNode));
 
             rv = mQueryProcessor->CompileQuery(this, query,
                                                mRefVariable, memberVariable,
                                                getter_AddRefs(aQuerySet->mCompiledQuery));
 
             if (aQuerySet->mCompiledQuery) {
@@ -2072,63 +2076,36 @@ nsXULTemplateBuilder::CompileExtendedQue
         bindings = aRuleElement;
 
     rv = CompileBindings(rule, bindings);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
 
-nsresult
-nsXULTemplateBuilder::DetermineMemberVariable(nsIContent* aActionElement,
-                                              nsIAtom** aMemberVariable)
+already_AddRefed<nsIAtom>
+nsXULTemplateBuilder::DetermineMemberVariable(nsIContent* aElement)
 {
-    // If the member variable hasn't already been specified, then
-    // grovel over <action> to find it. We'll use the first one
-    // that we find in a breadth-first search.
-
-    if (mMemberVariable) {
-        *aMemberVariable = mMemberVariable;
-        NS_IF_ADDREF(*aMemberVariable);
-    }
-    else {
-        *aMemberVariable = nsnull;
-
-        nsCOMArray<nsIContent> unvisited;
-
-        if (!unvisited.AppendObject(aActionElement))
-            return NS_ERROR_OUT_OF_MEMORY;
-
-        while (unvisited.Count()) {
-            nsIContent* next = unvisited[0];
-            unvisited.RemoveObjectAt(0);
-
-            nsAutoString uri;
-            next->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
-
-            if (!uri.IsEmpty() && uri[0] == PRUnichar('?')) {
-                // Found it.
-                *aMemberVariable = NS_NewAtom(uri);
-                break;
-            }
-
-            // otherwise, append the children to the unvisited list: this
-            // results in a breadth-first search.
-            PRUint32 count = next->GetChildCount();
-
-            for (PRUint32 i = 0; i < count; ++i) {
-                nsIContent *child = next->GetChildAt(i);
-
-                if (!unvisited.AppendObject(child))
-                    return NS_ERROR_OUT_OF_MEMORY;
-            }
+    // recursively iterate over the children looking for an element
+    // with uri="?..."
+    for (nsINode::ChildIterator iter(aElement); !iter.IsDone(); iter.Next()) {
+        nsAutoString uri;
+        nsIContent *child = iter;
+        child->GetAttr(kNameSpaceID_None, nsGkAtoms::uri, uri);
+        if (!uri.IsEmpty() && uri[0] == PRUnichar('?')) {
+            return NS_NewAtom(uri);
+        }
+
+        nsCOMPtr<nsIAtom> result = DetermineMemberVariable(child);
+        if (result) {
+            return result.forget();
         }
     }
 
-    return NS_OK;
+    return nsnull;
 }
 
 void
 nsXULTemplateBuilder::DetermineRDFQueryRef(nsIContent* aQueryElement, nsIAtom** aTag)
 {
     // check for a tag
     nsCOMPtr<nsIContent> content;
     nsXULContentUtils::FindChildByTag(aQueryElement,
--- a/content/xul/templates/src/nsXULTemplateBuilder.h
+++ b/content/xul/templates/src/nsXULTemplateBuilder.h
@@ -207,18 +207,17 @@ public:
      * Determine the ref variable and tag from inside a RDF query.
      */
     void DetermineRDFQueryRef(nsIContent* aQueryElement, nsIAtom** tag);
 
     /**
      * Determine the member variable from inside an action body. It will be
      * the value of the uri attribute on a node.
      */
-    nsresult
-    DetermineMemberVariable(nsIContent* aActionElement, nsIAtom** aMemberVariable);
+    already_AddRefed<nsIAtom> DetermineMemberVariable(nsIContent* aElement);
 
     /**
      * Compile a simple query. A simple query is one that doesn't have a
      * <query> and should use a default query which would normally just return
      * a list of children of the reference point.
      *
      * @param aRuleElement the <rule>
      * @param aQuerySet the query set
--- a/docshell/resources/content/netError.xhtml
+++ b/docshell/resources/content/netError.xhtml
@@ -58,17 +58,17 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>&loadError.label;</title>
     <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
     <!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in
          toolkit/components/places/src/nsFaviconService.h should be updated. -->
     <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
 
-    <script type="application/x-javascript"><![CDATA[
+    <script type="application/javascript"><![CDATA[
       // Error url MUST be formatted like this:
       //   moz-neterror:page?e=error&u=url&d=desc
       //
       // or optionally, to specify an alternate CSS class to allow for
       // custom styling and favicon:
       //
       //   moz-neterror:page?e=error&u=url&s=classname&d=desc
 
@@ -371,12 +371,12 @@
 
     </div>
 
     <!--
     - Note: It is important to run the script this way, instead of using
     - an onload handler. This is because error pages are loaded as
     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
     -->
-    <script type="application/x-javascript">initPage();</script>
+    <script type="application/javascript">initPage();</script>
 
   </body>
 </html>
--- a/docshell/shistory/src/nsSHEntry.cpp
+++ b/docshell/shistory/src/nsSHEntry.cpp
@@ -589,18 +589,18 @@ nsSHEntry::AddChild(nsISHEntry * aChild,
   //
   //  Assert that aOffset will not be so high as to grow us a lot.
   //
   NS_ASSERTION(aOffset < (mChildren.Count()+1023), "Large frames array!\n");
 
   if (aOffset < mChildren.Count()) {
     nsISHEntry* oldChild = mChildren.ObjectAt(aOffset);
     if (oldChild && oldChild != aChild) {
-      NS_ERROR("Adding child where we already have a child?  "
-               "This will likely misbehave");
+      NS_WARNING("Adding child where we already have a child?  "
+                 "This will likely misbehave");
       oldChild->SetParent(nsnull);
     }
   }
   
   // This implicitly extends the array to include aOffset
   mChildren.ReplaceObjectAt(aChild, aOffset);
 
   return NS_OK;
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -74,16 +74,17 @@ ifdef MOZ_SMIL
 DIRS += interfaces/smil
 endif
 
 DIRS += \
   public/coreEvents \
   base \
   src \
   locales \
+  plugins \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
 endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -414,16 +414,17 @@ public:
 
   NS_IMETHOD GetURL(const char *aURL, const char *aTarget, void *aPostData,
                     PRUint32 aPostDataLen, void *aHeadersData,
                     PRUint32 aHeadersDataLen, PRBool aIsFile = PR_FALSE);
   NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
   NPError ShowNativeContextMenu(NPMenu* menu, void* event);
   NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
                       double *destX, double *destY, NPCoordinateSpace destSpace);
+  void SendIdleEvent();
 
   NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner)
 
 private:
   nsCOMPtr<nsIPluginInstance> mInstance;
   nsCOMPtr<nsIDocument> mDocument;
 };
 
@@ -558,16 +559,21 @@ nsDummyJavaPluginOwner::GetNetscapeWindo
 }
 
 NS_IMETHODIMP
 nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+void
+nsDummyJavaPluginOwner::SendIdleEvent()
+{
+}
+
 /**
  * An indirect observer object that means we don't have to implement nsIObserver
  * on nsGlobalWindow, where any script could see it.
  */
 class nsGlobalWindowObserver : public nsIObserver {
 public:
   nsGlobalWindowObserver(nsGlobalWindow* aWindow) : mWindow(aWindow) {}
   NS_DECL_ISUPPORTS
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2551,19 +2551,17 @@ nsJSContext::InitContext(nsIScriptGlobal
                                               NS_GET_IID(nsISupports),
                                               flags,
                                               getter_AddRefs(holder));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Now check whether we need to grab a pointer to the
     // XPCNativeWrapper class
     if (!nsDOMClassInfo::GetXPCNativeWrapperClass()) {
-      JSAutoRequest ar(mContext);
-      rv = FindXPCNativeWrapperClass(holder);
-      NS_ENSURE_SUCCESS(rv, rv);
+      nsDOMClassInfo::SetXPCNativeWrapperClass(xpc->GetNativeWrapperClass());
     }
   } else {
     // There's already a global object. We are preparing this outer window
     // object for use as a real outer window (i.e. everything needs to live on
     // the inner window).
 
     // Call ClearScope to nuke any properties (e.g. Function and Object) on the
     // outer object. From now on, anybody asking the outer object for these
@@ -2953,62 +2951,16 @@ nsJSContext::AddSupportsPrimitiveTojsval
       NS_WARNING("Unknown primitive type used");
       *aArgv = JSVAL_NULL;
       break;
     }
   }
   return NS_OK;
 }
 
-nsresult
-nsJSContext::FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder)
-{
-  NS_ASSERTION(!nsDOMClassInfo::GetXPCNativeWrapperClass(),
-               "Why was this called?");
-
-  JSObject *globalObj;
-  aHolder->GetJSObject(&globalObj);
-  NS_ASSERTION(globalObj, "Must have global by now!");
-
-  const char* arg = "arg";
-  NS_NAMED_LITERAL_STRING(body, "return new XPCNativeWrapper(arg);");
-
-  // Can't use CompileFunction() here because our principal isn't
-  // inited yet and a null principal makes it fail.
-  JSFunction *fun =
-    ::JS_CompileUCFunction(mContext,
-                           globalObj,
-                           "_XPCNativeWrapperCtor",
-                           1, &arg,
-                           (jschar*)body.get(),
-                           body.Length(),
-                           "javascript:return new XPCNativeWrapper(arg);",
-                           1 // lineno
-                           );
-  NS_ENSURE_TRUE(fun, NS_ERROR_FAILURE);
-
-  jsval globalVal = OBJECT_TO_JSVAL(globalObj);
-  jsval wrapper;
-
-  JSBool ok = ::JS_CallFunction(mContext, globalObj, fun,
-                                1, &globalVal, &wrapper);
-  if (!ok) {
-    // No need to notify about pending exceptions here; we don't
-    // expect any other than out of memory, really.
-    return NS_ERROR_FAILURE;
-  }
-
-  NS_ASSERTION(JSVAL_IS_OBJECT(wrapper), "This should be an object!");
-
-  nsDOMClassInfo::SetXPCNativeWrapperClass(
-    ::JS_GET_CLASS(mContext, JSVAL_TO_OBJECT(wrapper)));
-
-  return NS_OK;
-}
-
 static JSPropertySpec OptionsProperties[] = {
   {"strict",    (int8)JSOPTION_STRICT,   JSPROP_ENUMERATE | JSPROP_PERMANENT},
   {"werror",    (int8)JSOPTION_WERROR,   JSPROP_ENUMERATE | JSPROP_PERMANENT},
   {"relimit",   (int8)JSOPTION_RELIMIT,  JSPROP_ENUMERATE | JSPROP_PERMANENT},
   {0}
 };
 
 static JSBool
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -200,18 +200,16 @@ public:
 
   // Calls IntervalCC() if user is currently inactive, otherwise MaybeCC(PR_TRUE)
   static void CCIfUserInactive();
 
   static void FireGCTimer(PRBool aLoadInProgress);
 
 protected:
   nsresult InitializeExternalClasses();
-  // aHolder should be holding our global object
-  nsresult FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder);
 
   // Helper to convert xpcom datatypes to jsvals.
   JS_FORCES_STACK nsresult ConvertSupportsTojsvals(nsISupports *aArgs,
                                                    void *aScope,
                                                    PRUint32 *aArgc,
                                                    void **aArgv,
                                                    void **aMarkp);
 
new file mode 100644
--- /dev/null
+++ b/dom/plugins/AStream.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation <http://www.mozilla.org/>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_plugins_AStream_h
+#define mozilla_plugins_AStream_h
+
+namespace mozilla {
+namespace plugins {
+
+/**
+ * When we are passed NPStream->{ndata,pdata} in {NPN,NPP}_DestroyStream, we
+ * don't know whether it's a plugin stream or a browser stream. This abstract
+ * class lets us cast to the right type of object and send the appropriate
+ * message.
+ */
+class AStream
+{
+public:
+  virtual bool IsBrowserStream() = 0;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/plugins/BrowserStreamChild.cpp
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 "BrowserStreamChild.h"
+#include "PluginInstanceChild.h"
+#include "StreamNotifyChild.h"
+
+namespace mozilla {
+namespace plugins {
+
+BrowserStreamChild::BrowserStreamChild(PluginInstanceChild* instance,
+                                       const nsCString& url,
+                                       const uint32_t& length,
+                                       const uint32_t& lastmodified,
+                                       const PStreamNotifyChild* notifyData,
+                                       const nsCString& headers,
+                                       const nsCString& mimeType,
+                                       const bool& seekable,
+                                       NPError* rv,
+                                       uint16_t* stype)
+  : mInstance(instance)
+  , mClosed(false)
+  , mURL(url)
+  , mHeaders(headers)
+{
+  AssertPluginThread();
+
+  memset(&mStream, 0, sizeof(mStream));
+  mStream.ndata = static_cast<AStream*>(this);
+  mStream.url = NullableStringGet(mURL);
+  mStream.end = length;
+  mStream.lastmodified = lastmodified;
+  if (notifyData)
+    mStream.notifyData =
+      static_cast<const StreamNotifyChild*>(notifyData)->mClosure;
+  mStream.headers = NullableStringGet(mHeaders);
+
+  *rv = mInstance->mPluginIface->newstream(
+    &mInstance->mData, const_cast<char*>(NullableStringGet(mimeType)),
+    &mStream, seekable, stype);
+  if (*rv != NPERR_NO_ERROR)
+    mClosed = true;
+}
+
+bool
+BrowserStreamChild::AnswerNPP_WriteReady(const int32_t& newlength,
+                                         int32_t *size)
+{
+  AssertPluginThread();
+
+  if (mClosed) {
+    *size = 0;
+    return true;
+  }
+
+  mStream.end = newlength;
+
+  *size = mInstance->mPluginIface->writeready(&mInstance->mData, &mStream);
+  return true;
+}
+
+bool
+BrowserStreamChild::AnswerNPP_Write(const int32_t& offset,
+                                    const Buffer& data,
+                                    int32_t* consumed)
+{
+  _MOZ_LOG(__FUNCTION__);
+  AssertPluginThread();
+
+  if (mClosed) {
+    *consumed = -1;
+    return true;
+  }
+
+  *consumed = mInstance->mPluginIface->write(&mInstance->mData, &mStream,
+                                             offset, data.Length(),
+                                             const_cast<char*>(data.get()));
+  return true;
+}
+
+bool
+BrowserStreamChild::AnswerNPP_StreamAsFile(const nsCString& fname)
+{
+  _MOZ_LOG(__FUNCTION__);
+  AssertPluginThread();
+  printf("mClosed: %i\n", mClosed);
+
+  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};
+    ranges.push_back(br);
+  }
+
+  NPError result;
+  CallNPN_RequestRead(ranges, &result);
+  return result;
+}
+
+void
+BrowserStreamChild::NPP_DestroyStream(NPError reason)
+{
+  AssertPluginThread();
+
+  if (mClosed)
+    return;
+
+  mInstance->mPluginIface->destroystream(&mInstance->mData, &mStream, reason);
+  mClosed = true;
+}
+
+} /* namespace plugins */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/dom/plugins/BrowserStreamChild.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_plugins_BrowserStreamChild_h
+#define mozilla_plugins_BrowserStreamChild_h 1
+
+#include "mozilla/plugins/PBrowserStreamChild.h"
+#include "mozilla/plugins/AStream.h"
+
+namespace mozilla {
+namespace plugins {
+
+class PluginInstanceChild;
+class PStreamNotifyChild;
+
+class BrowserStreamChild : public PBrowserStreamChild, public AStream
+{
+public:
+  BrowserStreamChild(PluginInstanceChild* instance,
+                     const nsCString& url,
+                     const uint32_t& length,
+                     const uint32_t& lastmodified,
+                     const PStreamNotifyChild* notifyData,
+                     const nsCString& headers,
+                     const nsCString& mimeType,
+                     const bool& seekable,
+                     NPError* rv,
+                     uint16_t* stype);
+  virtual ~BrowserStreamChild() { }
+
+  NS_OVERRIDE virtual bool IsBrowserStream() { return true; }
+
+  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)
+  {
+    if (s != &mStream)
+      NS_RUNTIMEABORT("Incorrect stream data");
+  }
+
+  NPError NPN_RequestRead(NPByteRange* aRangeList);
+  void NPP_DestroyStream(NPError reason);
+
+private:
+  PluginInstanceChild* mInstance;
+  NPStream mStream;
+  bool mClosed;
+  nsCString mURL;
+  nsCString mHeaders;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif /* mozilla_plugins_BrowserStreamChild_h */
new file mode 100644
--- /dev/null
+++ b/dom/plugins/BrowserStreamParent.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+
+#include "BrowserStreamParent.h"
+#include "PluginInstanceParent.h"
+
+namespace mozilla {
+namespace plugins {
+
+BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
+                                         NPStream* stream)
+  : mNPP(npp)
+  , mStream(stream)
+{
+  printf("BrowserStreamParent::BrowserStreamParent<%p>\n", (void*) this);
+  mStream->pdata = static_cast<AStream*>(this);
+}
+
+BrowserStreamParent::~BrowserStreamParent()
+{
+  printf("BrowserStreamParent::~BrowserStreamParent<%p>\n", (void*) this);
+}
+
+bool
+BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
+                                           NPError* result)
+{
+  _MOZ_LOG(__FUNCTION__);
+
+  if (!mStream)
+    return false;
+
+  if (ranges.size() > PR_INT32_MAX)
+    return false;
+
+  nsAutoArrayPtr<NPByteRange> rp(new NPByteRange[ranges.size()]);
+  for (PRUint32 i = 0; i < ranges.size(); ++i) {
+    rp[i].offset = ranges[i].offset;
+    rp[i].length = ranges[i].length;
+    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;
+
+  return result;
+}
+
+int32_t
+BrowserStreamParent::Write(int32_t offset,
+                           int32_t len,
+                           void* buffer)
+{
+  _MOZ_LOG(__FUNCTION__);
+
+  int32_t result;
+  if (!CallNPP_Write(offset,
+                     nsCString(static_cast<char*>(buffer), len),
+                     &result))
+    return -1;
+
+  return result;
+}
+
+void
+BrowserStreamParent::StreamAsFile(const char* fname)
+{
+  _MOZ_LOG(__FUNCTION__);
+
+  CallNPP_StreamAsFile(nsCString(fname));
+}
+
+NPError
+BrowserStreamParent::NPN_DestroyStream(NPReason reason)
+{
+  _MOZ_LOG(__FUNCTION__);
+
+  return mNPP->mNPNIface->destroystream(mNPP->mNPP, mStream, reason);
+}
+
+} // namespace plugins
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/plugins/BrowserStreamParent.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation <http://www.mozilla.org/>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_plugins_BrowserStreamParent_h
+#define mozilla_plugins_BrowserStreamParent_h
+
+#include "mozilla/plugins/PBrowserStreamParent.h"
+#include "mozilla/plugins/AStream.h"
+
+namespace mozilla {
+namespace plugins {
+
+class PluginInstanceParent;
+
+class BrowserStreamParent : public PBrowserStreamParent, public AStream
+{
+  friend class PluginModuleParent;
+  friend class PluginInstanceParent;
+
+public:
+  BrowserStreamParent(PluginInstanceParent* npp,
+                      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);
+
+  PluginInstanceParent* mNPP;
+  NPStream* mStream;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/plugins/Makefile.in
@@ -0,0 +1,118 @@
+# ***** 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 Plugins.
+#
+# The Initial Developer of the Original Code is
+#   Ben Turner <bent.mozilla@gmail.com>.
+# 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 *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = dom
+
+EXPORTS_NAMESPACES = mozilla
+
+EXPORTS_mozilla = \
+  PluginLibrary.h \
+  PluginPRLibrary.h \
+  $(NULL)
+
+ifdef MOZ_IPC
+
+EXPORTS_NAMESPACES = mozilla mozilla/plugins
+
+EXPORTS_mozilla/plugins = \
+  BrowserStreamChild.h \
+  BrowserStreamParent.h \
+  NPEventOSX.h \
+  NPEventWindows.h \
+  NPEventX11.h \
+  PluginInstanceChild.h \
+  PluginInstanceParent.h \
+  PluginMessageUtils.h \
+  PluginModuleChild.h \
+  PluginModuleParent.h \
+  PluginProcessParent.h \
+  PluginScriptableObjectChild.h \
+  PluginScriptableObjectParent.h \
+  PluginInstanceChild.h \
+  PluginInstanceParent.h \
+  AStream.h \
+  BrowserStreamChild.h \
+  BrowserStreamParent.h \
+  PluginStreamChild.h \
+  PluginStreamParent.h \
+  PluginMessageUtils.h \
+  PluginProcessParent.h \
+  PluginThreadChild.h \
+  StreamNotifyChild.h \
+  StreamNotifyParent.h \
+  $(NULL)
+
+MODULE           = dom
+LIBRARY_NAME     = domplugins_s
+LIBXUL_LIBRARY   = 1
+FORCE_STATIC_LIB = 1
+EXPORT_LIBRARY = 1
+ENABLE_CXX_EXCEPTIONS = 1
+
+CPPSRCS = \
+  PluginMessageUtils.cpp \
+  PluginInstanceChild.cpp \
+  PluginInstanceParent.cpp \
+  PluginModuleChild.cpp \
+  PluginModuleParent.cpp \
+  PluginProcessParent.cpp \
+  PluginScriptableObjectChild.cpp \
+  PluginScriptableObjectParent.cpp \
+  BrowserStreamChild.cpp \
+  BrowserStreamParent.cpp \
+  PluginStreamChild.cpp \
+  PluginStreamParent.cpp \
+  PluginThreadChild.cpp \
+  $(NULL)
+
+LOCAL_INCLUDES = \
+  -I$(topsrcdir)/modules/plugin/base/public/ \
+  -I$(topsrcdir)/modules/plugin/base/src/ \
+  $(NULL)
+
+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/dom/plugins/NPEventOSX.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+/* ***** 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 Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_dom_plugins_NPEventOSX_h
+#define mozilla_dom_plugins_NPEventOSX_h 1
+
+
+#include "npapi.h"
+#include "IPC/IPCMessageUtils.h"
+
+#warning This is only a stub implementation IMPLEMENT ME
+
+namespace mozilla {
+namespace plugins {
+struct NPRemoteEvent {
+    NPEvent event;
+};
+}
+}
+
+namespace IPC {
+
+template <>
+struct ParamTraits<mozilla::plugins::NPRemoteEvent>
+{
+    typedef mozilla::plugins::NPRemoteEvent paramType;
+
+    static void Write(Message* aMsg, const paramType& aParam)
+    {
+    }
+
+    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    {
+        return true;
+    }
+
+    static void Log(const paramType& aParam, std::wstring* aLog)
+    {
+    }
+};
+
+} // namespace IPC
+
+#endif // ifndef mozilla_dom_plugins_NPEventOSX_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/NPEventWindows.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+/* ***** 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 Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_dom_plugins_NPEventWindows_h
+#define mozilla_dom_plugins_NPEventWindows_h 1
+
+
+#include "npapi.h"
+namespace mozilla {
+
+namespace plugins {
+
+// We use an NPRemoteEvent struct so that we can store the extra data on
+// the stack so that we don't need to worry about managing the memory.
+struct NPRemoteEvent
+{
+    NPEvent event;
+    union {
+        RECT rect;
+        WINDOWPOS windowpos;
+    } lParamData;
+};
+
+}
+
+}
+
+namespace IPC {
+
+template <>
+struct ParamTraits<mozilla::plugins::NPRemoteEvent>
+{
+    typedef mozilla::plugins::NPRemoteEvent paramType;
+
+    static void Write(Message* aMsg, const paramType& aParam)
+    {
+        // Make a non-const copy of aParam so that we can muck with
+        // its insides for tranport
+        paramType paramCopy;
+
+        paramCopy.event = aParam.event;
+
+        // We can't blindly ipc events because they may sometimes contain
+        // pointers to memory in the sending process. For example, the
+        // WM_IME_CONTROL with the IMC_GETCOMPOSITIONFONT message has lParam
+        // set to a pointer to a LOGFONT structure.
+        switch (paramCopy.event.event) {
+            case WM_WINDOWPOSCHANGED:
+                // The lParam paramter of WM_WINDOWPOSCHANGED holds a pointer to
+                // a WINDOWPOS structure that contains information about the
+                // window's new size and position
+                paramCopy.lParamData.windowpos = *(reinterpret_cast<WINDOWPOS*>(paramCopy.event.lParam));
+                break;
+            case WM_PAINT:
+                // The lParam paramter of WM_PAINT holds a pointer to an RECT
+                // structure specifying the bounding box of the update area.
+                paramCopy.lParamData.rect = *(reinterpret_cast<RECT*>(paramCopy.event.lParam));
+                break;
+
+            // the white list of events that we will ipc to the client
+            case WM_CHAR:
+            case WM_SYSCHAR:
+
+            case WM_KEYUP:
+            case WM_SYSKEYUP:
+
+            case WM_KEYDOWN:
+            case WM_SYSKEYDOWN:
+
+            case WM_DEADCHAR:
+            case WM_SYSDEADCHAR:
+            case WM_CONTEXTMENU:
+
+            case WM_CUT:
+            case WM_COPY:
+            case WM_PASTE:
+            case WM_CLEAR:
+            case WM_UNDO:
+
+            case WM_MOUSEMOVE:
+            case WM_LBUTTONDOWN:
+            case WM_MBUTTONDOWN:
+            case WM_RBUTTONDOWN:
+            case WM_LBUTTONUP:
+            case WM_MBUTTONUP:
+            case WM_RBUTTONUP:
+            case WM_LBUTTONDBLCLK:
+            case WM_MBUTTONDBLCLK:
+            case WM_RBUTTONDBLCLK:
+
+            case WM_SETFOCUS:
+            case WM_KILLFOCUS:
+                break;
+
+            default:
+                // RegisterWindowMessage events should be passed.
+                if (paramCopy.event.event >= 0xC000 && paramCopy.event.event <= 0xFFFF)
+                    break;
+
+                // ignore any events we don't expect
+                return;
+        }
+
+        aMsg->WriteBytes(&paramCopy, sizeof(paramType));
+    }
+
+    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    {
+        const char* bytes = 0;
+
+        if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
+            return false;
+        }
+        memcpy(aResult, bytes, sizeof(paramType));
+
+        if (aResult->event.event == WM_PAINT) {
+            // restore the lParam to point at the RECT
+            aResult->event.lParam = reinterpret_cast<LPARAM>(&aResult->lParamData.rect);
+        } else if (aResult->event.event == WM_WINDOWPOSCHANGED) {
+            // restore the lParam to point at the WINDOWPOS
+            aResult->event.lParam = reinterpret_cast<LPARAM>(&aResult->lParamData.windowpos);
+        }
+
+        return true;
+    }
+
+    static void Log(const paramType& aParam, std::wstring* aLog)
+    {
+        aLog->append(L"(WINEvent)");
+    }
+
+};
+
+} // namespace IPC
+
+#endif // ifndef mozilla_dom_plugins_NPEventWindows_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/NPEventX11.h
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+/* ***** 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 Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The 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 ***** */
+
+#ifndef mozilla_dom_plugins_NPEventX11_h
+#define mozilla_dom_plugins_NPEventX11_h 1
+
+#if defined(MOZ_WIDGET_GTK2)
+#  include <gdk/gdkx.h>
+#else
+#  error Implement me for your toolkit
+#endif
+
+#include "npapi.h"
+
+namespace mozilla {
+
+namespace plugins {
+
+struct NPRemoteEvent {
+    NPEvent event;
+};
+
+}
+
+}
+
+
+//
+// XEvent is defined as a union of all more specific X*Events.
+// Luckily, as of xorg 1.6.0 / X protocol 11 rev 0, the only pointer
+// field contained in any of these specific X*Event structs is a
+// |Display*|.  So to simplify serializing these XEvents, we make the
+// 
+// ********** XXX ASSUMPTION XXX **********
+//
+// that the process to which the event is forwarded shares the same
+// display as the process on which the event originated.
+//
+// With this simplification, serialization becomes a simple memcpy to
+// the output stream.  Deserialization starts as just a memcpy from
+// the input stream, BUT we then have to write the correct |Display*|
+// into the right field of each X*Event that contains one.
+//
+
+namespace IPC {
+
+template <>
+struct ParamTraits<mozilla::plugins::NPRemoteEvent>     // synonym for XEvent
+{
+    typedef mozilla::plugins::NPRemoteEvent paramType;
+
+    static void Write(Message* aMsg, const paramType& aParam)
+    {
+        aMsg->WriteBytes(&aParam, sizeof(paramType));
+    }
+
+    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    {
+        const char* bytes = 0;
+
+        if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
+            return false;
+        }
+
+        memcpy(aResult, bytes, sizeof(paramType));
+        SetXDisplay(aResult->event);
+        return true;
+    }
+
+    static void Log(const paramType& aParam, std::wstring* aLog)
+    {
+        // TODO
+        aLog->append(L"(XEvent)");
+    }
+
+private:
+    static Display* GetXDisplay(const XAnyEvent& ev)
+    {
+        // TODO: get Display* from Window in |ev|
+
+        // FIXME: do this using Xlib, don't use Gdk
+        
+        return GDK_DISPLAY();
+    }
+
+    static Display* GetXDisplay(const XErrorEvent& ev)
+    {
+        // TODO: get Display* from Window in |ev|
+
+        // FIXME: do this using Xlib, don't use Gdk
+        
+        return GDK_DISPLAY();
+    }
+
+    static void SetXDisplay(XEvent& ev)
+    {
+        if (ev.type >= KeyPress) {
+            ev.xany.display = GetXDisplay(ev.xany);
+        }
+        else {
+            // XXX assuming that this is an error event
+            // (type == 0? not clear from Xlib.h)
+            ev.xerror.display = GetXDisplay(ev.xerror);
+        }
+    }
+};
+
+} // namespace IPC
+
+
+#endif // ifndef mozilla_dom_plugins_NPEventX11_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PBrowserStream.ipdl
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 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.
+ */
+
+rpc protocol PBrowserStream
+{
+  manager PPluginInstance;
+
+child:
+  rpc NPP_WriteReady(int32_t newlength)
+    returns (int32_t size);
+
+  rpc NPP_Write(int32_t offset,
+                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
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * 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):
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ *   Ben Turner <bent.mozilla@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 ***** */
+
+include protocol "PPluginModule.ipdl";
+include protocol "PPluginScriptableObject.ipdl";
+include protocol "PBrowserStream.ipdl";
+include protocol "PPluginStream.ipdl";
+include protocol "PStreamNotify.ipdl";
+
+include "mozilla/plugins/PluginMessageUtils.h";
+
+using NPError;
+using NPRemoteWindow;
+using NPRemoteEvent;
+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 (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 (nullable PPluginScriptableObject value, NPError result);
+  rpc NPN_GetValue_NPNVPluginElementNPObject()
+    returns (nullable PPluginScriptableObject value, NPError result);
+  rpc NPN_GetValue_NPNVprivateModeBool()
+    returns (bool value, NPError result);
+
+  rpc NPN_SetValue_NPPVpluginWindow(bool windowed)
+    returns (NPError result);
+  rpc NPN_SetValue_NPPVpluginTransparent(bool transparent)
+    returns (NPError result);
+
+  rpc NPN_GetURL(nsCString url, nsCString target)
+    returns (NPError result);
+  rpc NPN_PostURL(nsCString url, nsCString target, nsCString buffer, bool file)
+    returns (NPError result);
+
+  /**
+   * Covers both NPN_GetURLNotify and NPN_PostURLNotify.
+   * @TODO This would be more readable as an overloaded method,
+   *       but IPDL doesn't allow that for constructors (or any method?).
+   */
+  rpc PStreamNotify(nsCString url, nsCString target, bool post,
+                    nsCString buffer, bool file)
+    returns (NPError result);
+
+  async NPN_InvalidateRect(NPRect rect);
+
+  rpc NPN_PushPopupsEnabledState(bool aState)
+    returns (bool aSuccess);
+
+  rpc NPN_PopPopupsEnabledState()
+    returns (bool aSuccess);
+
+both:
+  rpc PPluginScriptableObject();
+
+child:
+  /* NPP_NewStream */
+  rpc PBrowserStream(nsCString url,
+                     uint32_t length,
+                     uint32_t lastmodified,
+                     nullable PStreamNotify notifyData,
+                     nsCString headers,
+                     nsCString mimeType,
+                     bool seekable)
+    returns (NPError rv,
+             uint16_t stype);
+
+parent:
+  /* NPN_NewStream */
+  rpc PPluginStream(nsCString mimeType,
+                    nsCString target)
+    returns (NPError result);
+};
+
+} // namespace plugins
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PPluginModule.ipdl
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * 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):
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ *   Ben Turner <bent.mozilla@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 ***** */
+
+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;
+
+child:
+  rpc NP_Initialize()
+    returns (NPError rv);
+
+  rpc PPluginInstance(nsCString aMimeType,
+                      uint16_t aMode,
+                      nsCString[] aNames,
+                      nsCString[] aValues)
+    returns (NPError rv);
+
+  rpc NP_Shutdown()
+    returns (NPError rv);
+
+parent:
+  rpc NPN_UserAgent()
+    returns (nsCString userAgent);
+
+  sync NPN_GetStringIdentifier(nsCString aString)
+    returns (NPRemoteIdentifier aId);
+  sync NPN_GetIntIdentifier(int32_t aInt)
+    returns (NPRemoteIdentifier aId);
+
+  // for the following two methods, the returned value is valid iff
+  // |err == NPERR_NO_ERROR|
+  sync NPN_UTF8FromIdentifier(NPRemoteIdentifier aId)
+    returns (NPError err, nsCString aString);
+  // technically |aInt| is undefined when |aId| is invalid.  but it's
+  // nice to let the other side know that |aId| was invalid
+  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
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PPluginScriptableObject.ipdl
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * 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):
+ *   Benjamin Smedberg <benjamin@smedbergs.us>
+ *   Ben Turner <bent.mozilla@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 ***** */
+
+include protocol "PPluginInstance.ipdl";
+
+include "npapi.h";
+include "npruntime.h";
+include "mozilla/plugins/PluginMessageUtils.h";
+
+using mozilla::ipc::NPRemoteIdentifier;
+using mozilla::void_t;
+using mozilla::null_t;
+
+namespace mozilla {
+namespace plugins {
+
+union Variant {
+  void_t;
+  null_t;
+  bool;
+  int;
+  double;
+  nsCString;
+  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();
+
+  rpc HasMethod(NPRemoteIdentifier aId)
+    returns (bool aHasMethod);
+
+  rpc Invoke(NPRemoteIdentifier aId,
+             Variant[] aArgs)
+    returns (Variant aResult,
+             bool aSuccess);
+
+  rpc InvokeDefault(Variant[] aArgs)
+    returns (Variant aResult,
+             bool aSuccess);
+
+  rpc HasProperty(NPRemoteIdentifier aId)
+    returns (bool aHasProperty);
+
+  rpc GetProperty(NPRemoteIdentifier aId)
+    returns (Variant aResult,
+             bool aSuccess);
+
+  rpc SetProperty(NPRemoteIdentifier aId,
+                  Variant aValue)
+    returns (bool aSuccess);
+
+  rpc RemoveProperty(NPRemoteIdentifier aId)
+    returns (bool aSuccess);
+
+  rpc Enumerate()
+    returns (NPRemoteIdentifier[] aProperties,
+             bool aSuccess);
+
+  rpc Construct(Variant[] aArgs)
+    returns (Variant aResult,
+             bool aSuccess);
+};
+
+} // namespace plugins
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PPluginStream.ipdl
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation <http://www.mozilla.org/>.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 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
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PStreamNotify.ipdl
@@ -0,0 +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
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -0,0 +1,1080 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/
+ *
+ * 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 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
+ * 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 "PluginInstanceChild.h"
+#include "PluginModuleChild.h"
+#include "BrowserStreamChild.h"
+#include "PluginStreamChild.h"
+#include "StreamNotifyChild.h"
+
+#include "mozilla/ipc/SyncChannel.h"
+
+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>
+
+#define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
+#endif
+
+PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface) :
+        mPluginIface(aPluginIface)
+#if defined(OS_WIN)
+        , mPluginWindowHWND(0)
+        , mPluginWndProc(0)
+        , mPluginParentHWND(0)
+#endif
+    {
+        memset(&mWindow, 0, sizeof(mWindow));
+        mData.ndata = (void*) this;
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+        mWindow.ws_info = &mWsInfo;
+        memset(&mWsInfo, 0, sizeof(mWsInfo));
+#  ifdef MOZ_WIDGET_GTK2
+        mWsInfo.display = GDK_DISPLAY();
+#  endif
+#endif
+#if defined(OS_WIN)
+    memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
+    mAlphaExtract.doublePassEvent = ::RegisterWindowMessage(NS_OOPP_DOUBLEPASS_MSGID);
+#endif
+    }
+
+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();
+
+    switch(aVar) {
+
+    case NPNVSupportsWindowless:
+#if defined(OS_LINUX) || defined(OS_WIN)
+        *((NPBool*)aValue) = true;
+#else
+        *((NPBool*)aValue) = false;
+#endif
+        return NPERR_NO_ERROR;
+
+#if defined(OS_LINUX)
+    case NPNVSupportsXEmbedBool:
+        *((NPBool*)aValue) = true;
+        return NPERR_NO_ERROR;
+
+    case NPNVToolkit:
+        *((NPNToolkitType*)aValue) = NPNVGtk2;
+        return NPERR_NO_ERROR;
+
+#elif defined(OS_WIN)
+    case NPNVToolkit:
+        return NPERR_GENERIC_ERROR;
+#endif
+    case NPNVjavascriptEnabledBool: {
+        bool v = false;
+        NPError result;
+        if (!CallNPN_GetValue_NPNVjavascriptEnabledBool(&v, &result)) {
+            return NPERR_GENERIC_ERROR;
+        }
+        *static_cast<NPBool*>(aValue) = v;
+        return result;
+    }
+
+    case NPNVisOfflineBool: {
+        bool v = false;
+        NPError result;
+        if (!CallNPN_GetValue_NPNVisOfflineBool(&v, &result)) {
+            return NPERR_GENERIC_ERROR;
+        }
+        *static_cast<NPBool*>(aValue) = v;
+        return result;
+    }
+
+    case NPNVprivateModeBool: {
+        bool v = false;
+        NPError result;
+        if (!CallNPN_GetValue_NPNVprivateModeBool(&v, &result)) {
+            return NPERR_GENERIC_ERROR;
+        }
+        *static_cast<NPBool*>(aValue) = v;
+        return result;
+    }
+
+    case NPNVWindowNPObject: {
+        PPluginScriptableObjectChild* actor;
+        NPError result;
+        if (!CallNPN_GetValue_NPNVWindowNPObject(&actor, &result)) {
+            NS_WARNING("Failed to send message!");
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (result != NPERR_NO_ERROR) {
+            return result;
+        }
+
+        NS_ASSERTION(actor, "Null actor!");
+
+        NPObject* object =
+            static_cast<PluginScriptableObjectChild*>(actor)->GetObject();
+        NS_ASSERTION(object, "Null object?!");
+
+        PluginModuleChild::sBrowserFuncs.retainobject(object);
+        *((NPObject**)aValue) = object;
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVPluginElementNPObject: {
+        PPluginScriptableObjectChild* actor;
+        NPError result;
+        if (!CallNPN_GetValue_NPNVPluginElementNPObject(&actor, &result)) {
+            NS_WARNING("Failed to send message!");
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (result != NPERR_NO_ERROR) {
+            return result;
+        }
+
+        NS_ASSERTION(actor, "Null actor!");
+
+        NPObject* object =
+            static_cast<PluginScriptableObjectChild*>(actor)->GetObject();
+        NS_ASSERTION(object, "Null object?!");
+
+        PluginModuleChild::sBrowserFuncs.retainobject(object);
+        *((NPObject**)aValue) = object;
+        return NPERR_NO_ERROR;
+    }
+
+    default:
+        printf("  unhandled var %s\n", NPNVariableToString(aVar));
+        return NPERR_GENERIC_ERROR;
+    }
+
+}
+
+
+NPError
+PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
+{
+    printf ("[PluginInstanceChild] NPN_SetValue(%s, %ld)\n",
+            NPPVariableToString(aVar), reinterpret_cast<intptr_t>(aValue));
+    AssertPluginThread();
+
+    switch (aVar) {
+    case NPPVpluginWindowBool: {
+        NPError rv;
+        bool windowed = (NPBool) (intptr_t) aValue;
+
+        if (!CallNPN_SetValue_NPPVpluginWindow(windowed, &rv))
+            return NPERR_GENERIC_ERROR;
+
+        return rv;
+    }
+
+    case NPPVpluginTransparentBool: {
+        NPError rv;
+        bool transparent = (NPBool) (intptr_t) aValue;
+
+        if (!CallNPN_SetValue_NPPVpluginTransparent(transparent, &rv))
+            return NPERR_GENERIC_ERROR;
+
+        return rv;
+    }
+
+    default:
+        printf("  unhandled var %s\n", NPPVariableToString(aVar));
+        return NPERR_GENERIC_ERROR;
+    }
+}
+
+
+bool
+PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWindow(
+    bool* windowed, NPError* rv)
+{
+    AssertPluginThread();
+
+    NPBool isWindowed;
+    *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginWindowBool,
+                                 reinterpret_cast<void*>(&isWindowed));
+    *windowed = isWindowed;
+    return true;
+}
+
+bool
+PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginTransparent(
+    bool* transparent, NPError* rv)
+{
+    AssertPluginThread();
+
+    NPBool isTransparent;
+    *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginTransparentBool,
+                                 reinterpret_cast<void*>(&isTransparent));
+    *transparent = isTransparent;
+    return true;
+}
+
+bool
+PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(
+    bool* needs, NPError* rv)
+{
+    AssertPluginThread();
+
+#ifdef OS_LINUX
+
+    // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|.
+    // thus we can't NPBool for needsXEmbed, or the three bytes above
+    // it on the stack would get clobbered. so protect with unsigned
+    // long.
+    unsigned long needsXEmbed = 0;
+    *rv = mPluginIface->getvalue(GetNPP(), NPPVpluginNeedsXEmbed,
+                                 reinterpret_cast<void*>(&needsXEmbed));
+    *needs = needsXEmbed;
+    return true;
+
+#else
+
+    NS_RUNTIMEABORT("shouldn't be called on non-linux platforms");
+    return false;               // not reached
+
+#endif
+}
+
+bool
+PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
+                                          PPluginScriptableObjectChild** aValue,
+                                          NPError* aResult)
+{
+    AssertPluginThread();
+
+    NPObject* object;
+    NPError result = mPluginIface->getvalue(GetNPP(),
+                                            NPPVpluginScriptableNPObject,
+                                            &object);
+    if (result == NPERR_NO_ERROR && object) {
+        PluginScriptableObjectChild* actor = GetActorForNPObject(object);
+
+        // If we get an actor then it has retained. Otherwise we don't need it
+        // any longer.
+        PluginModuleChild::sBrowserFuncs.releaseobject(object);
+        if (actor) {
+            *aValue = actor;
+            *aResult = NPERR_NO_ERROR;
+            return true;
+        }
+
+        NS_ERROR("Failed to get actor!");
+        result = NPERR_GENERIC_ERROR;
+    }
+
+    *aValue = nsnull;
+    *aResult = result;
+    return true;
+}
+
+bool
+PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
+                                           int16_t* handled)
+{
+    _MOZ_LOG(__FUNCTION__);
+    AssertPluginThread();
+
+#if defined(OS_LINUX) && defined(DEBUG)
+    if (GraphicsExpose == event.event.type)
+        printf("  received drawable 0x%lx\n",
+               event.event.xgraphicsexpose.drawable);
+#endif
+
+    // Make a copy since we may modify values.
+    NPEvent evcopy = event.event;
+
+#ifdef OS_WIN
+    // Painting for win32. SharedSurfacePaint handles everything.
+    if (mWindow.type == NPWindowTypeDrawable) {
+       if (evcopy.event == WM_PAINT) {
+          *handled = SharedSurfacePaint(evcopy);
+          return true;
+       }
+       else if (evcopy.event == mAlphaExtract.doublePassEvent) {
+            // We'll render to mSharedSurfaceDib first, then render to a cached bitmap
+            // we store locally. The two passes are for alpha extraction, so the second
+            // pass must be to a flat white surface in order for things to work.
+            mAlphaExtract.doublePass = RENDER_BACK_ONE;
+            *handled = true;
+            return true;
+       }
+    }
+#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
+        // process does not need to wait; the parent is the process that needs
+        // to wait.  A possibly-slightly-better alternative would be to send
+        // an X event to the parent that the parent would wait for.
+        XSync(mWsInfo.display, False);
+    }
+#endif
+
+    return true;
+}
+
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+static bool
+XVisualIDToInfo(Display* aDisplay, VisualID aVisualID,
+                Visual** aVisual, unsigned int* aDepth)
+{
+    if (aVisualID == None) {
+        *aVisual = NULL;
+        *aDepth = 0;
+        return true;
+    }
+
+    const Screen* screen = DefaultScreenOfDisplay(aDisplay);
+
+    for (int d = 0; d < screen->ndepths; d++) {
+        Depth *d_info = &screen->depths[d];
+        for (int v = 0; v < d_info->nvisuals; v++) {
+            Visual* visual = &d_info->visuals[v];
+            if (visual->visualid == aVisualID) {
+                *aVisual = visual;
+                *aDepth = d_info->depth;
+                return true;
+            }
+        }
+    }
+
+    NS_ERROR("VisualID not on Screen.");
+    return false;
+}
+#endif
+
+bool
+PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow,
+                                         NPError* rv)
+{
+    printf("[PluginInstanceChild] NPP_SetWindow(0x%lx, %d, %d, %d x %d)\n",
+           aWindow.window,
+           aWindow.x, aWindow.y,
+           aWindow.width, aWindow.height);
+    AssertPluginThread();
+
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+    // The minimum info is sent over IPC to allow this
+    // code to determine the rest.
+
+    mWindow.window = reinterpret_cast<void*>(aWindow.window);
+    mWindow.x = aWindow.x;
+    mWindow.y = aWindow.y;
+    mWindow.width = aWindow.width;
+    mWindow.height = aWindow.height;
+    mWindow.clipRect = aWindow.clipRect;
+    mWindow.type = aWindow.type;
+
+    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)
+    switch (aWindow.type) {
+      case NPWindowTypeWindow:
+      {
+          if (!CreatePluginWindow())
+              return false;
+
+          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)));
+              }
+          }
+      }
+      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()
+{
+    return true;
+}
+
+void
+PluginInstanceChild::Destroy()
+{
+    // Copy the actors here so we don't enumerate a mutating array.
+    nsAutoTArray<PluginScriptableObjectChild*, 10> objects;
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        objects.AppendElement(mScriptableObjects[index]);
+    }
+
+    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
+bool
+PluginInstanceChild::RegisterWindowClass()
+{
+    static bool alreadyRegistered = false;
+    if (alreadyRegistered)
+        return true;
+
+    alreadyRegistered = true;
+
+    WNDCLASSEX wcex;
+    wcex.cbSize         = sizeof(WNDCLASSEX);
+    wcex.style          = CS_DBLCLKS;
+    wcex.lpfnWndProc    = DummyWindowProc;
+    wcex.cbClsExtra     = 0;
+    wcex.cbWndExtra     = 0;
+    wcex.hInstance      = GetModuleHandle(NULL);
+    wcex.hIcon          = 0;
+    wcex.hCursor        = 0;
+    wcex.hbrBackground  = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
+    wcex.lpszMenuName   = 0;
+    wcex.lpszClassName  = kWindowClassName;
+    wcex.hIconSm        = 0;
+
+    return RegisterClassEx(&wcex) ? true : false;
+}
+
+bool
+PluginInstanceChild::CreatePluginWindow()
+{
+    // already initialized
+    if (mPluginWindowHWND)
+        return true;
+        
+    if (!RegisterWindowClass())
+        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));
+
+    return true;
+}
+
+void
+PluginInstanceChild::DestroyPluginWindow()
+{
+    if (mPluginWindowHWND) {
+        // Unsubclass the window.
+        WNDPROC wndProc = reinterpret_cast<WNDPROC>(
+            GetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC));
+        if (wndProc == PluginWindowProc) {
+            NS_ASSERTION(mPluginWndProc, "Should have old proc here!");
+            SetWindowLongPtr(mPluginWindowHWND, GWLP_WNDPROC,
+                             reinterpret_cast<LONG>(mPluginWndProc));
+            mPluginWndProc = 0;
+        }
+
+        RemoveProp(mPluginWindowHWND, kPluginInstanceChildProperty);
+        DestroyWindow(mPluginWindowHWND);
+        mPluginWindowHWND = 0;
+    }
+}
+
+void
+PluginInstanceChild::ReparentPluginWindow(HWND hWndParent)
+{
+    if (hWndParent != mPluginParentHWND && IsWindow(hWndParent)) {
+        // Fix the child window's style to be a child window.
+        LONG style = GetWindowLongPtr(mPluginWindowHWND, GWL_STYLE);
+        style |= WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+        style &= ~WS_POPUP;
+        SetWindowLongPtr(mPluginWindowHWND, GWL_STYLE, style);
+
+        // Do the reparenting.
+        SetParent(mPluginWindowHWND, hWndParent);
+
+        // Make sure we're visible.
+        ShowWindow(mPluginWindowHWND, SW_SHOWNA);
+    }
+    mPluginParentHWND = hWndParent;
+}
+
+void
+PluginInstanceChild::SizePluginWindow(int width,
+                                      int height)
+{
+    if (mPluginWindowHWND) {
+        SetWindowPos(mPluginWindowHWND, NULL, 0, 0, width, height,
+                     SWP_NOZORDER | SWP_NOREPOSITION);
+    }
+}
+
+// See chromium's webplugin_delegate_impl.cc for explanation of this function.
+// static
+LRESULT CALLBACK
+PluginInstanceChild::DummyWindowProc(HWND hWnd,
+                                     UINT message,
+                                     WPARAM wParam,
+                                     LPARAM lParam)
+{
+    return CallWindowProc(DefWindowProc, hWnd, message, wParam, lParam);
+}
+
+// static
+LRESULT CALLBACK
+PluginInstanceChild::PluginWindowProc(HWND hWnd,
+                                      UINT message,
+                                      WPARAM wParam,
+                                      LPARAM lParam)
+{
+    NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
+                 "Failed to prevent a nonqueued message from running!");
+
+    PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
+        GetProp(hWnd, kPluginInstanceChildProperty));
+    if (!self) {
+        NS_NOTREACHED("Badness!");
+        return 0;
+    }
+
+    NS_ASSERTION(self->mPluginWindowHWND == hWnd, "Wrong window!");
+
+    LRESULT res = CallWindowProc(self->mPluginWndProc, hWnd, message, wParam,
+                                 lParam);
+
+    if (message == WM_CLOSE)
+        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;
+        // Free any alpha extraction resources if needed. This will be reset
+        // the next time it's used.
+        AlphaExtractCacheRelease();
+    }
+      
+    // 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();
+    AlphaExtractCacheRelease();
+}
+
+/* double pass cache buffer - (rarely) used in cases where alpha extraction
+ * occurs for windowless plugins. */
+ 
+bool
+PluginInstanceChild::AlphaExtractCacheSetup()
+{
+    AlphaExtractCacheRelease();
+
+    mAlphaExtract.hdc = ::CreateCompatibleDC(NULL);
+
+    if (!mAlphaExtract.hdc)
+        return false;
+
+    BITMAPINFOHEADER bmih;
+    memset((void*)&bmih, 0, sizeof(BITMAPINFOHEADER));
+    bmih.biSize        = sizeof(BITMAPINFOHEADER);
+    bmih.biWidth       = mWindow.width;
+    bmih.biHeight      = mWindow.height;
+    bmih.biPlanes      = 1;
+    bmih.biBitCount    = 32;
+    bmih.biCompression = BI_RGB;
+
+    void* ppvBits = nsnull;
+    mAlphaExtract.bmp = ::CreateDIBSection(mAlphaExtract.hdc,
+                                           (BITMAPINFO*)&bmih,
+                                           DIB_RGB_COLORS,
+                                           (void**)&ppvBits,
+                                           NULL,
+                                           (unsigned long)sizeof(BITMAPINFOHEADER));
+    if (!mAlphaExtract.bmp)
+      return false;
+
+    DeleteObject(::SelectObject(mAlphaExtract.hdc, mAlphaExtract.bmp));
+    return true;
+}
+
+void
+PluginInstanceChild::AlphaExtractCacheRelease()
+{
+    if (mAlphaExtract.bmp)
+        ::DeleteObject(mAlphaExtract.bmp);
+
+    if (mAlphaExtract.hdc)
+        ::DeleteObject(mAlphaExtract.hdc);
+
+    mAlphaExtract.bmp = NULL;
+    mAlphaExtract.hdc = NULL;
+}
+
+void
+PluginInstanceChild::UpdatePaintClipRect(RECT* aRect)
+{
+    if (aRect) {
+        // Update the clip rect on our internal hdc
+        HRGN clip = ::CreateRectRgnIndirect(aRect);
+        ::SelectClipRgn(mSharedSurfaceDib.GetHDC(), clip);
+        ::DeleteObject(clip);
+    }
+}
+
+int16_t
+PluginInstanceChild::SharedSurfacePaint(NPEvent& evcopy)
+{
+    RECT* pRect = reinterpret_cast<RECT*>(evcopy.lParam);
+
+    switch(mAlphaExtract.doublePass) {
+        case RENDER_NATIVE:
+            // pass the internal hdc to the plugin
+            UpdatePaintClipRect(pRect);
+            evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC());
+            return mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
+        break;
+        case RENDER_BACK_ONE:
+              // Handle a double pass render used in alpha extraction for transparent
+              // plugins. (See nsObjectFrame and gfxWindowsNativeDrawing for details.)
+              // We render twice, once to the shared dib, and once to a cache which
+              // we copy back on a second paint. These paints can't be spread across
+              // multiple rpc messages as delays cause animation frame changes.
+              if (!mAlphaExtract.bmp && !AlphaExtractCacheSetup()) {
+                  mAlphaExtract.doublePass = RENDER_NATIVE;
+                  return false;
+              }
+
+              // See gfxWindowsNativeDrawing, color order doesn't have to match.
+              ::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
+              UpdatePaintClipRect(pRect);
+              evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC());
+              if (!mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy))) {
+                  mAlphaExtract.doublePass = RENDER_NATIVE;
+                  return false;
+              }
+
+              // Copy to cache. We render to shared dib so we don't have to call
+              // setwindow between calls (flash issue).  
+              ::BitBlt(mAlphaExtract.hdc,
+                       pRect->left,
+                       pRect->top,
+                       pRect->right - pRect->left,
+                       pRect->bottom - pRect->top,
+                       mSharedSurfaceDib.GetHDC(),
+                       pRect->left,
+                       pRect->top,
+                       SRCCOPY);
+
+              ::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
+              if (!mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy))) {
+                  mAlphaExtract.doublePass = RENDER_NATIVE;
+                  return false;
+              }
+              mAlphaExtract.doublePass = RENDER_BACK_TWO;
+              return true;
+        break;
+        case RENDER_BACK_TWO:
+              // copy our cached surface back
+              ::BitBlt(mSharedSurfaceDib.GetHDC(),
+                       pRect->left,
+                       pRect->top,
+                       pRect->right - pRect->left,
+                       pRect->bottom - pRect->top,
+                       mAlphaExtract.hdc,
+                       pRect->left,
+                       pRect->top,
+                       SRCCOPY);
+              mAlphaExtract.doublePass = RENDER_NATIVE;
+              return true;
+        break;
+    }
+    return false;
+}
+
+#endif // OS_WIN
+
+PPluginScriptableObjectChild*
+PluginInstanceChild::AllocPPluginScriptableObject()
+{
+    AssertPluginThread();
+
+    nsAutoPtr<PluginScriptableObjectChild>* object =
+        mScriptableObjects.AppendElement();
+    NS_ENSURE_TRUE(object, nsnull);
+
+    *object = new PluginScriptableObjectChild();
+    NS_ENSURE_TRUE(*object, nsnull);
+
+    return object->get();
+}
+
+bool
+PluginInstanceChild::DeallocPPluginScriptableObject(
+    PPluginScriptableObjectChild* aObject)
+{
+    AssertPluginThread();
+
+    PluginScriptableObjectChild* object =
+        reinterpret_cast<PluginScriptableObjectChild*>(aObject);
+
+    NPObject* npobject = object->GetObject();
+    if (npobject &&
+        npobject->_class != PluginScriptableObjectChild::GetClass()) {
+        PluginModuleChild::current()->UnregisterNPObject(npobject);
+    }
+
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        if (mScriptableObjects[index] == object) {
+            mScriptableObjects.RemoveElementAt(index);
+            return true;
+        }
+    }
+    NS_NOTREACHED("An actor we don't know about?!");
+    return false;
+}
+
+bool
+PluginInstanceChild::AnswerPPluginScriptableObjectConstructor(
+                                           PPluginScriptableObjectChild* aActor)
+{
+    AssertPluginThread();
+
+    // This is only called in response to the parent process requesting the
+    // creation of an actor. This actor will represent an NPObject that is
+    // created by the browser and returned to the plugin.
+    NPClass* npclass =
+        const_cast<NPClass*>(PluginScriptableObjectChild::GetClass());
+
+    ChildNPObject* object = reinterpret_cast<ChildNPObject*>(
+        PluginModuleChild::sBrowserFuncs.createobject(GetNPP(), npclass));
+    if (!object) {
+        NS_WARNING("Failed to create NPObject!");
+        return false;
+    }
+
+    PluginScriptableObjectChild* actor =
+        static_cast<PluginScriptableObjectChild*>(aActor);
+    actor->Initialize(const_cast<PluginInstanceChild*>(this), object);
+
+    return true;
+}
+
+PBrowserStreamChild*
+PluginInstanceChild::AllocPBrowserStream(const nsCString& url,
+                                         const uint32_t& length,
+                                         const uint32_t& lastmodified,
+                                         PStreamNotifyChild* notifyData,
+                                         const nsCString& headers,
+                                         const nsCString& mimeType,
+                                         const bool& seekable,
+                                         NPError* rv,
+                                         uint16_t *stype)
+{
+    AssertPluginThread();
+    return new BrowserStreamChild(this, url, length, lastmodified, notifyData,
+                                  headers, mimeType, seekable, rv, stype);
+}
+
+bool
+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::DeallocPPluginStream(PPluginStreamChild* stream)
+{
+    AssertPluginThread();
+    delete stream;
+    return true;
+}
+
+PStreamNotifyChild*
+PluginInstanceChild::AllocPStreamNotify(const nsCString& url,
+                                        const nsCString& target,
+                                        const bool& post,
+                                        const nsCString& buffer,
+                                        const bool& file,
+                                        NPError* result)
+{
+    AssertPluginThread();
+    NS_RUNTIMEABORT("not reached");
+    return NULL;
+}
+
+bool
+StreamNotifyChild::Answer__delete__(const NPReason& reason)
+{
+    AssertPluginThread();
+    return static_cast<PluginInstanceChild*>(Manager())
+        ->NotifyStream(this, reason);
+}
+
+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)
+{
+    AssertPluginThread();
+    delete notifyData;
+    return true;
+}
+
+PluginScriptableObjectChild*
+PluginInstanceChild::GetActorForNPObject(NPObject* aObject)
+{
+    AssertPluginThread();
+  NS_ASSERTION(aObject, "Null pointer!");
+
+  if (aObject->_class == PluginScriptableObjectChild::GetClass()) {
+      // One of ours! It's a browser-provided object.
+      ChildNPObject* object = static_cast<ChildNPObject*>(aObject);
+      NS_ASSERTION(object->parent, "Null actor!");
+      return object->parent;
+  }
+
+  PluginScriptableObjectChild* actor =
+      PluginModuleChild::current()->GetActorForNPObject(aObject);
+  if (actor) {
+      // Plugin-provided object that we've previously wrapped.
+      return actor;
+  }
+
+  actor = reinterpret_cast<PluginScriptableObjectChild*>(
+      CallPPluginScriptableObjectConstructor());
+  NS_ENSURE_TRUE(actor, nsnull);
+
+  actor->Initialize(this, aObject);
+
+#ifdef DEBUG
+  bool ok =
+#endif
+  PluginModuleChild::current()->RegisterNPObject(aObject, actor);
+  NS_ASSERTION(ok, "Out of memory?");
+
+  return actor;
+}
+
+NPError
+PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
+                                   NPStream** aStream)
+{
+    AssertPluginThread();
+
+    PluginStreamChild* ps = new PluginStreamChild();
+
+    NPError result;
+    CallPPluginStreamConstructor(ps, nsDependentCString(aMIMEType),
+                                 NullableString(aWindow), &result);
+    if (NPERR_NO_ERROR != result) {
+        *aStream = NULL;
+        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
+    // 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;
+}
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginInstanceChild.h
@@ -0,0 +1,226 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/
+ *
+ * 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 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):
+ *
+ * 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 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)
+
+namespace mozilla {
+namespace plugins {
+
+class PBrowserStreamChild;
+class BrowserStreamChild;
+
+class PluginInstanceChild : public PPluginInstanceChild
+{
+    friend class BrowserStreamChild;
+    friend class PluginStreamChild;
+
+#ifdef OS_WIN
+    friend LRESULT CALLBACK PluginWindowProc(HWND hWnd,
+                                             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
+    AnswerNPP_GetValue_NPPVpluginScriptableNPObject(PPluginScriptableObjectChild** value,
+                                                    NPError* result);
+
+    virtual bool
+    AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled);
+
+    virtual PPluginScriptableObjectChild*
+    AllocPPluginScriptableObject();
+
+    virtual bool
+    DeallocPPluginScriptableObject(PPluginScriptableObjectChild* aObject);
+
+    virtual bool
+    AnswerPPluginScriptableObjectConstructor(PPluginScriptableObjectChild* aActor);
+
+    virtual PBrowserStreamChild*
+    AllocPBrowserStream(const nsCString& url,
+                        const uint32_t& length,
+                        const uint32_t& lastmodified,
+                        PStreamNotifyChild* notifyData,
+                        const nsCString& headers,
+                        const nsCString& mimeType,
+                        const bool& seekable,
+                        NPError* rv,
+                        uint16_t *stype);
+
+    virtual bool
+    DeallocPBrowserStream(PBrowserStreamChild* stream);
+
+    virtual PPluginStreamChild*
+    AllocPPluginStream(const nsCString& mimeType,
+                       const nsCString& target,
+                       NPError* result);
+
+    virtual bool
+    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
+    DeallocPStreamNotify(PStreamNotifyChild* notifyData);
+
+public:
+    PluginInstanceChild(const NPPluginFuncs* aPluginIface);
+
+    virtual ~PluginInstanceChild();
+
+    bool Initialize();
+    void Destroy();
+
+    NPP GetNPP()
+    {
+        return &mData;
+    }
+
+    NPError
+    NPN_GetValue(NPNVariable aVariable, void* aValue);
+
+    NPError
+    NPN_SetValue(NPPVariable aVariable, void* aValue);
+
+    PluginScriptableObjectChild*
+    GetActorForNPObject(NPObject* aObject);
+
+    NPError
+    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);
+    static LRESULT CALLBACK DummyWindowProc(HWND hWnd,
+                                            UINT message,
+                                            WPARAM wParam,
+                                            LPARAM lParam);
+    static LRESULT CALLBACK PluginWindowProc(HWND hWnd,
+                                             UINT message,
+                                             WPARAM wParam,
+                                             LPARAM lParam);
+#endif
+
+    const NPPluginFuncs* mPluginIface;
+    NPP_t mData;
+    NPWindow mWindow;
+#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
+    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);
+    int16_t SharedSurfacePaint(NPEvent& evcopy);
+    void SharedSurfaceRelease();
+    bool AlphaExtractCacheSetup();
+    void AlphaExtractCacheRelease();
+    void UpdatePaintClipRect(RECT* aRect);
+
+private:
+    enum {
+      RENDER_NATIVE,
+      RENDER_BACK_ONE,
+      RENDER_BACK_TWO 
+    };
+    gfx::SharedDIBWin mSharedSurfaceDib;
+    struct {
+      PRUint32        doublePassEvent;
+      PRUint16        doublePass;
+      HDC             hdc;
+      HBITMAP         bmp;
+    } mAlphaExtract;
+#endif // defined(OS_WIN)
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif // ifndef dom_plugins_PluginInstanceChild_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -0,0 +1,842 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/
+ *
+ * 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 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
+ * 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 "PluginInstanceParent.h"
+
+#include "BrowserStreamParent.h"
+#include "PluginModuleParent.h"
+#include "PluginStreamParent.h"
+#include "StreamNotifyParent.h"
+
+#include "npfunctions.h"
+#include "nsAutoPtr.h"
+
+#if defined(OS_WIN)
+#include <windowsx.h>
+#endif
+
+using namespace mozilla::plugins;
+
+PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
+                                           NPP npp,
+                                           const NPNetscapeFuncs* npniface)
+  : mParent(parent),
+    mNPP(npp),
+    mNPNIface(npniface),
+    mWindowType(NPWindowTypeWindow)
+{
+}
+
+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();
+    for (PRUint32 index = 0; index < count; index++) {
+        objects.AppendElement(mScriptableObjects[index]);
+    }
+
+    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,
+                                          const nsCString& mimeType,
+                                          const bool& seekable,
+                                          NPError* rv,
+                                          uint16_t *stype)
+{
+    NS_RUNTIMEABORT("Not reachable");
+    return NULL;
+}
+
+bool
+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)
+{
+    delete stream;
+    return true;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
+                                                       bool* value,
+                                                       NPError* result)
+{
+    NPBool v;
+    *result = mNPNIface->getvalue(mNPP, NPNVjavascriptEnabledBool, &v);
+    *value = v;
+    return true;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_GetValue_NPNVisOfflineBool(bool* value,
+                                                           NPError* result)
+{
+    NPBool v;
+    *result = mNPNIface->getvalue(mNPP, NPNVisOfflineBool, &v);
+    *value = v;
+    return true;
+}
+
+bool
+PluginInstanceParent::InternalGetValueForNPObject(
+                                         NPNVariable aVariable,
+                                         PPluginScriptableObjectParent** aValue,
+                                         NPError* aResult)
+{
+    NPObject* npobject;
+    NPError result = mNPNIface->getvalue(mNPP, aVariable, (void*)&npobject);
+    if (result == NPERR_NO_ERROR) {
+        NS_ASSERTION(npobject, "Shouldn't return null and NPERR_NO_ERROR!");
+
+        PluginScriptableObjectParent* actor = GetActorForNPObject(npobject);
+        mNPNIface->releaseobject(npobject);
+        if (actor) {
+            *aValue = actor;
+            *aResult = NPERR_NO_ERROR;
+            return true;
+        }
+
+        NS_ERROR("Failed to get actor!");
+        result = NPERR_GENERIC_ERROR;
+    }
+
+    *aValue = nsnull;
+    *aResult = result;
+    return true;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject(
+                                         PPluginScriptableObjectParent** aValue,
+                                         NPError* aResult)
+{
+    return InternalGetValueForNPObject(NPNVWindowNPObject, aValue, aResult);
+}
+
+bool
+PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject(
+                                         PPluginScriptableObjectParent** aValue,
+                                         NPError* aResult)
+{
+    return InternalGetValueForNPObject(NPNVPluginElementNPObject, aValue,
+                                       aResult);
+}
+
+bool
+PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value,
+                                                             NPError* result)
+{
+    NPBool v;
+    *result = mNPNIface->getvalue(mNPP, NPNVprivateModeBool, &v);
+    *value = v;
+    return true;
+}
+
+
+bool
+PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
+    const bool& windowed, NPError* result)
+{
+    NPBool isWindowed = windowed;
+    *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool,
+                                  (void*)isWindowed);
+    return true;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent(
+    const bool& transparent, NPError* result)
+{
+    NPBool isTransparent = transparent;
+    *result = mNPNIface->setvalue(mNPP, NPPVpluginTransparentBool,
+                                  (void*)isTransparent);
+    return true;
+}
+
+
+bool
+PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url,
+                                       const nsCString& target,
+                                       NPError* result)
+{
+    *result = mNPNIface->geturl(mNPP,
+                                NullableStringGet(url),
+                                NullableStringGet(target));
+    return true;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_PostURL(const nsCString& url,
+                                        const nsCString& target,
+                                        const nsCString& buffer,
+                                        const bool& file,
+                                        NPError* result)
+{
+    *result = mNPNIface->posturl(mNPP, url.get(), NullableStringGet(target),
+                                 buffer.Length(), buffer.get(), file);
+    return true;
+}
+
+PStreamNotifyParent*
+PluginInstanceParent::AllocPStreamNotify(const nsCString& url,
+                                         const nsCString& target,
+                                         const bool& post,
+                                         const nsCString& buffer,
+                                         const bool& file,
+                                         NPError* result)
+{
+    return new StreamNotifyParent();
+}
+
+bool
+PluginInstanceParent::AnswerPStreamNotifyConstructor(PStreamNotifyParent* actor,
+                                                     const nsCString& url,
+                                                     const nsCString& target,
+                                                     const bool& post,
+                                                     const nsCString& buffer,
+                                                     const bool& file,
+                                                     NPError* result)
+{
+    if (!post) {
+        *result = mNPNIface->geturlnotify(mNPP,
+                                          NullableStringGet(url),
+                                          NullableStringGet(target),
+                                          actor);
+    }
+    else {
+        *result = mNPNIface->posturlnotify(mNPP,
+                                           NullableStringGet(url),
+                                           NullableStringGet(target),
+                                           buffer.Length(),
+                                           NullableStringGet(buffer),
+                                           file, actor);
+    }
+
+    if (*result != NPERR_NO_ERROR)
+        PStreamNotifyParent::Call__delete__(actor, NPERR_GENERIC_ERROR);
+
+    return true;
+}
+
+bool
+PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent* notifyData)
+{
+    delete notifyData;
+    return true;
+}
+
+bool
+PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect& rect)
+{
+    mNPNIface->invalidaterect(mNPP, const_cast<NPRect*>(&rect));
+    return true;
+}
+
+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; // 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;
+    if (!CallNPP_SetWindow(window, &prv))
+        return NPERR_GENERIC_ERROR;
+    return prv;
+}
+
+NPError
+PluginInstanceParent::NPP_GetValue(NPPVariable aVariable,
+                                   void* _retval)
+{
+    printf("[PluginInstanceParent] NPP_GetValue(%s)\n",
+           NPPVariableToString(aVariable));
+
+    switch (aVariable) {
+
+    case NPPVpluginWindowBool: {
+        bool windowed;
+        NPError rv;
+
+        if (!CallNPP_GetValue_NPPVpluginWindow(&windowed, &rv)) {
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (NPERR_NO_ERROR != rv) {
+            return rv;
+        }
+
+        (*(NPBool*)_retval) = windowed;
+        return NPERR_NO_ERROR;
+    }
+
+    case NPPVpluginTransparentBool: {
+        bool transparent;
+        NPError rv;
+
+        if (!CallNPP_GetValue_NPPVpluginTransparent(&transparent, &rv)) {
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (NPERR_NO_ERROR != rv) {
+            return rv;
+        }
+
+        (*(NPBool*)_retval) = transparent;
+        return NPERR_NO_ERROR;
+    }
+
+#ifdef OS_LINUX
+    case NPPVpluginNeedsXEmbed: {
+        bool needsXEmbed;
+        NPError rv;
+
+        if (!CallNPP_GetValue_NPPVpluginNeedsXEmbed(&needsXEmbed, &rv)) {
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (NPERR_NO_ERROR != rv) {
+            return rv;
+        }
+
+        (*(NPBool*)_retval) = needsXEmbed;
+        return NPERR_NO_ERROR;
+    }
+#endif
+
+    case NPPVpluginScriptableNPObject: {
+        PPluginScriptableObjectParent* actor;
+        NPError rv;
+        if (!CallNPP_GetValue_NPPVpluginScriptableNPObject(&actor, &rv)) {
+            return NPERR_GENERIC_ERROR;
+        }
+
+        if (NPERR_NO_ERROR != rv) {
+            return rv;
+        }
+
+        if (!actor) {
+            NS_ERROR("NPPVpluginScriptableNPObject succeeded but null.");
+            return NPERR_GENERIC_ERROR;
+        }
+
+        const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
+        if (!npn) {
+            NS_WARNING("No netscape functions?!");
+            return NPERR_GENERIC_ERROR;
+        }
+
+        NPObject* object =
+            static_cast<PluginScriptableObjectParent*>(actor)->GetObject();
+        NS_ASSERTION(object, "This shouldn't ever be null!");
+
+        (*(NPObject**)_retval) = npn->retainobject(object);
+        return NPERR_NO_ERROR;
+    }
+
+    default:
+        printf("  unhandled var %s\n", NPPVariableToString(aVariable));
+        return NPERR_GENERIC_ERROR;
+    }
+}
+
+int16_t
+PluginInstanceParent::NPP_HandleEvent(void* event)
+{
+    _MOZ_LOG(__FUNCTION__);
+
+    NPEvent* npevent = reinterpret_cast<NPEvent*>(event);
+    NPRemoteEvent npremoteevent;
+    npremoteevent.event = *npevent;
+    int16_t handled;
+
+#if defined(OS_WIN)
+    RECT rect;
+    if (mWindowType == NPWindowTypeDrawable) {
+        switch(npevent->event) {
+            case WM_PAINT:
+            {
+                RECT rect;
+                SharedSurfaceBeforePaint(rect, npremoteevent);
+                if (!CallNPP_HandleEvent(npremoteevent, &handled))
+                    return 0;
+                if (handled)
+                    SharedSurfaceAfterPaint(npevent);
+            }
+            break;
+            case WM_WINDOWPOSCHANGED:
+                SharedSurfaceSetOrigin(npremoteevent);
+                if (!CallNPP_HandleEvent(npremoteevent, &handled))
+                    return 0;
+            break;
+            case WM_MOUSEMOVE:
+            case WM_RBUTTONDOWN:
+            case WM_MBUTTONDOWN:
+            case WM_LBUTTONDOWN:
+            case WM_LBUTTONUP:
+            case WM_MBUTTONUP:
+            case WM_RBUTTONUP:
+            case WM_LBUTTONDBLCLK:
+            case WM_MBUTTONDBLCLK:
+            case WM_RBUTTONDBLCLK:
+            {
+                // Received mouse events have an origin at the position of the plugin rect
+                // in the page. However, when rendering to the shared dib, the rect origin
+                // changes to 0,0 via the WM_WINDOWPOSCHANGED event. In this case we need to
+                // translate these coords to the proper location.
+                nsPoint pt(GET_X_LPARAM(npremoteevent.event.lParam), GET_Y_LPARAM(npremoteevent.event.lParam));
+                pt.MoveBy(-mPluginPosOrigin.x, -mPluginPosOrigin.y);
+                npremoteevent.event.lParam = MAKELPARAM(pt.x, pt.y);
+                if (!CallNPP_HandleEvent(npremoteevent, &handled))
+                    return 0;
+            }
+            default:
+                if (!CallNPP_HandleEvent(npremoteevent, &handled))
+                    return 0;
+            break;
+        }
+    }
+    else {
+        if (!CallNPP_HandleEvent(npremoteevent, &handled))
+            return 0;
+    }
+#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
+        // process does not need to wait; the child is the process that needs
+        // to wait.  A possibly-slightly-better alternative would be to send
+        // an X event to the child that the child would wait for.
+#  ifdef MOZ_WIDGET_GTK2
+        XSync(GDK_DISPLAY(), False);
+#  endif
+    }
+
+    if (!CallNPP_HandleEvent(npremoteevent, &handled))
+        return 0; // no good way to handle errors here...
+#endif
+
+    return handled;
+}
+
+NPError
+PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
+                                    NPBool seekable, uint16_t* stype)
+{
+    _MOZ_LOG(__FUNCTION__);
+
+    BrowserStreamParent* bs = new BrowserStreamParent(this, stream);
+
+    NPError err;
+    if (!CallPBrowserStreamConstructor(bs,
+                                       NullableString(stream->url),
+                                       stream->end,
+                                       stream->lastmodified,
+                                       static_cast<PStreamNotifyParent*>(stream->notifyData),
+                                       NullableString(stream->headers),
+                                       NullableString(type), seekable,
+                                       &err, stype))
+        return NPERR_GENERIC_ERROR;
+
+    if (NPERR_NO_ERROR != err)
+        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");
+
+        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");
+
+        PPluginStreamParent::Call__delete__(sp, reason, false);
+        return NPERR_NO_ERROR;
+    }
+}
+
+PPluginScriptableObjectParent*
+PluginInstanceParent::AllocPPluginScriptableObject()
+{
+    nsAutoPtr<PluginScriptableObjectParent>* object =
+        mScriptableObjects.AppendElement();
+    NS_ENSURE_TRUE(object, nsnull);
+
+    *object = new PluginScriptableObjectParent();
+    NS_ENSURE_TRUE(*object, nsnull);
+
+    return object->get();
+}
+
+bool
+PluginInstanceParent::DeallocPPluginScriptableObject(
+                                         PPluginScriptableObjectParent* aObject)
+{
+    PluginScriptableObjectParent* object =
+        reinterpret_cast<PluginScriptableObjectParent*>(aObject);
+
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        if (mScriptableObjects[index] == object) {
+            mScriptableObjects.RemoveElementAt(index);
+            return true;
+        }
+    }
+    NS_NOTREACHED("An actor we don't know about?!");
+    return false;
+}
+
+bool
+PluginInstanceParent::AnswerPPluginScriptableObjectConstructor(
+                                          PPluginScriptableObjectParent* aActor)
+{
+    // This is only called in response to the child process requesting the
+    // creation of an actor. This actor will represent an NPObject that is
+    // created by the plugin and returned to the browser.
+    const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
+    if (!npn) {
+        NS_WARNING("No netscape function pointers?!");
+        return false;
+    }
+
+    NPClass* npclass =
+        const_cast<NPClass*>(PluginScriptableObjectParent::GetClass());
+
+    ParentNPObject* object = reinterpret_cast<ParentNPObject*>(
+        npn->createobject(mNPP, npclass));
+    if (!object) {
+        NS_WARNING("Failed to create NPObject!");
+        return false;
+    }
+
+    static_cast<PluginScriptableObjectParent*>(aActor)->Initialize(
+        const_cast<PluginInstanceParent*>(this), object);
+    return true;
+}
+
+void
+PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason,
+                                    void* notifyData)
+{
+    _MOZ_LOG(__FUNCTION__);
+
+    PStreamNotifyParent* streamNotify =
+        static_cast<PStreamNotifyParent*>(notifyData);
+    PStreamNotifyParent::Call__delete__(streamNotify, reason);
+}
+
+PluginScriptableObjectParent*
+PluginInstanceParent::GetActorForNPObject(NPObject* aObject)
+{
+    NS_ASSERTION(aObject, "Null pointer!");
+
+    if (aObject->_class == PluginScriptableObjectParent::GetClass()) {
+        // One of ours!
+        ParentNPObject* object = static_cast<ParentNPObject*>(aObject);
+        NS_ASSERTION(object->parent, "Null actor!");
+        return object->parent;
+    }
+
+    PRUint32 count = mScriptableObjects.Length();
+    for (PRUint32 index = 0; index < count; index++) {
+        nsAutoPtr<PluginScriptableObjectParent>& actor =
+            mScriptableObjects[index];
+        if (actor->GetObject() == aObject) {
+            return actor;
+        }
+    }
+
+    PluginScriptableObjectParent* actor =
+        static_cast<PluginScriptableObjectParent*>(
+            CallPPluginScriptableObjectConstructor());
+    NS_ENSURE_TRUE(actor, nsnull);
+
+    actor->Initialize(const_cast<PluginInstanceParent*>(this), aObject);
+    return actor;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState,
+                                                       bool* aSuccess)
+{
+    *aSuccess = mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0);
+    return true;
+}
+
+bool
+PluginInstanceParent::AnswerNPN_PopPopupsEnabledState(bool* aSuccess)
+{
+    *aSuccess = mNPNIface->poppopupsenabledstate(mNPP);
+    return true;
+}
+
+#if defined(OS_WIN)
+
+/* windowless drawing helpers */
+
+/*
+ * Origin info:
+ *
+ * windowless, offscreen:
+ *
+ * WM_WINDOWPOSCHANGED: origin is relative to container 
+ * setwindow: origin is 0,0
+ * WM_PAINT: origin is 0,0
+ *
+ * windowless, native:
+ *
+ * WM_WINDOWPOSCHANGED: origin is relative to container 
+ * setwindow: origin is relative to container
+ * WM_PAINT: origin is relative to container
+ *
+ * PluginInstanceParent:
+ *
+ * painting: mPluginPort (nsIntRect, saved in SetWindow)
+ * event translation: mPluginPosOrigin (nsIntPoint, saved in SetOrigin)
+ */
+
+void
+PluginInstanceParent::SharedSurfaceSetOrigin(NPRemoteEvent& npremoteevent)
+{
+    WINDOWPOS* winpos = (WINDOWPOS*)npremoteevent.event.lParam;
+
+    // save the origin, we'll use this to translate input coordinates
+    mPluginPosOrigin.x = winpos->x;
+    mPluginPosOrigin.y = winpos->y;
+
+    // Reset to the offscreen dib origin
+    winpos->x  = 0;
+    winpos->y  = 0;
+}
+
+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;
+}
+
+void
+PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect,
+                                               NPRemoteEvent& npremoteevent)
+{
+    RECT* dr = (RECT*)npremoteevent.event.lParam;
+    HDC parentHdc = (HDC)npremoteevent.event.wParam;
+
+    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.x + dirtyRect.width;
+    rect.bottom = dirtyRect.y + dirtyRect.height;
+
+    npremoteevent.event.wParam = WPARAM(0);
+    npremoteevent.event.lParam = LPARAM(&rect);
+}
+
+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)
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginInstanceParent.h
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/
+ *
+ * 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 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):
+ *
+ * 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 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 PluginModuleParent;
+
+class PluginInstanceParent : public PPluginInstanceParent
+{
+    friend class PluginModuleParent;
+    friend class BrowserStreamParent;
+    friend class PluginStreamParent;
+
+public:
+    PluginInstanceParent(PluginModuleParent* parent,
+                         NPP npp,
+                         const NPNetscapeFuncs* npniface);
+
+    virtual ~PluginInstanceParent();
+
+    void Destroy();
+
+    virtual PPluginScriptableObjectParent*
+    AllocPPluginScriptableObject();
+
+    virtual bool
+    AnswerPPluginScriptableObjectConstructor(PPluginScriptableObjectParent* aActor);
+
+    virtual bool
+    DeallocPPluginScriptableObject(PPluginScriptableObjectParent* aObject);
+    virtual PBrowserStreamParent*
+    AllocPBrowserStream(const nsCString& url,
+                        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
+    DeallocPBrowserStream(PBrowserStreamParent* stream);
+
+    virtual PPluginStreamParent*
+    AllocPPluginStream(const nsCString& mimeType,
+                       const nsCString& target,
+                       NPError* result);
+    virtual bool
+    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,
+                                       NPError* result);
+    virtual bool
+    AnswerNPN_GetValue_NPNVPluginElementNPObject(
+                                       PPluginScriptableObjectParent** value,
+                                       NPError* result);
+    virtual bool
+    AnswerNPN_GetValue_NPNVprivateModeBool(bool* value, NPError* result);
+
+    virtual bool
+    AnswerNPN_SetValue_NPPVpluginWindow(const bool& windowed, NPError* result);
+    virtual bool
+    AnswerNPN_SetValue_NPPVpluginTransparent(const bool& transparent,
+                                             NPError* result);
+
+    virtual bool
+    AnswerNPN_GetURL(const nsCString& url, const nsCString& target,
+                     NPError *result);
+
+    virtual bool
+    AnswerNPN_PostURL(const nsCString& url, const nsCString& target,
+                      const nsCString& buffer, const bool& file,
+                      NPError* result);
+
+    virtual PStreamNotifyParent*
+    AllocPStreamNotify(const nsCString& url, const nsCString& target,
+                       const bool& post, const nsCString& buffer,
+                       const bool& file,
+                       NPError* result);
+
+    NS_OVERRIDE virtual bool
+    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);
+
+    virtual bool
+    RecvNPN_InvalidateRect(const NPRect& rect);
+
+    virtual bool
+    AnswerNPN_PushPopupsEnabledState(const bool& aState,
+                                     bool* aSuccess);
+
+    virtual bool
+    AnswerNPN_PopPopupsEnabledState(bool* aSuccess);
+
+    NPError NPP_SetWindow(const NPWindow* aWindow);
+
+    NPError NPP_GetValue(NPPVariable variable, void *ret_value);
+    NPError NPP_SetValue(NPNVariable variable, void *value)
+    {
+        _MOZ_LOG(__FUNCTION__);
+        return 1;
+    }
+
+    NPError NPP_NewStream(NPMIMEType type, NPStream* stream,
+                          NPBool seekable, uint16_t* stype);
+    NPError NPP_DestroyStream(NPStream* stream, NPReason reason);
+
+    void NPP_Print(NPPrint* platformPrint)
+    {
+        _MOZ_LOG(__FUNCTION__);
+    }
+
+    int16_t NPP_HandleEvent(void* event);
+
+    void NPP_URLNotify(const char* url, NPReason reason, void* notifyData);
+
+    PluginModuleParent* Module()
+    {
+        return mParent;
+    }
+
+    const NPNetscapeFuncs* GetNPNIface()
+    {
+        return mNPNIface;
+    }
+
+    PluginScriptableObjectParent*
+    GetActorForNPObject(NPObject* aObject);
+
+    NPP
+    GetNPP()
+    {
+      return mNPP;
+    }
+
+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);
+    void SharedSurfaceBeforePaint(RECT &rect, NPRemoteEvent& npremoteevent);
+    void SharedSurfaceAfterPaint(NPEvent* npevent);
+    void SharedSurfaceSetOrigin(NPRemoteEvent& npremoteevent);
+    void SharedSurfaceRelease();
+
+private:
+    gfx::SharedDIBWin  mSharedSurfaceDib;
+    nsIntRect          mPluginPort;
+    nsIntRect          mSharedSize;
+    nsIntPoint         mPluginPosOrigin;
+#endif // defined(XP_WIN)
+};
+
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif // ifndef dom_plugins_PluginInstanceParent_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginLibrary.h
@@ -0,0 +1,84 @@
+/* -*- 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/
+ *
+ * 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 Foundation.
+ *
+ * The Initial Developer of the Original Code is
+ *   Josh Aas <josh@mozilla.com>
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 mozilla_PluginLibrary_h
+#define mozilla_PluginLibrary_h 1
+
+#include "prlink.h"
+#include "npapi.h"
+#include "nscore.h"
+
+class nsNPAPIPlugin;
+
+namespace mozilla {
+
+class PluginLibrary
+{
+public:
+  virtual ~PluginLibrary() { }
+
+  /**
+   * Inform this library about the nsNPAPIPlugin which owns it. This
+   * object will hold a weak pointer to the plugin.
+   */
+  virtual void SetPlugin(nsNPAPIPlugin* plugin) = 0;
+
+  virtual bool HasRequiredFunctions() = 0;
+
+#if defined(XP_UNIX) && !defined(XP_MACOSX)
+  virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) = 0;
+#else
+  virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) = 0;
+#endif
+  virtual nsresult NP_Shutdown(NPError* error) = 0;
+  virtual nsresult NP_GetMIMEDescription(char** mimeDesc) = 0;
+  virtual nsresult NP_GetValue(void *future, NPPVariable aVariable,
+                               void *aValue, NPError* error) = 0;
+#if defined(XP_WIN) || defined(XP_MACOSX)
+  virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) = 0;
+#endif
+  virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance,
+                           uint16_t mode, int16_t argc, char* argn[],
+                           char* argv[], NPSavedData* saved,
+                           NPError* error) = 0;
+};
+
+
+} // namespace mozilla
+
+#endif  // ifndef mozilla_PluginLibrary_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginMessageUtils.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
+/* vim: set sw=2 ts=8 et 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 Content App.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 "PluginMessageUtils.h"
+#include "nsIRunnable.h"
+#include "nsThreadUtils.h"
+
+namespace {
+
+class DeferNPObjectReleaseRunnable : public nsRunnable
+{
+public:
+  DeferNPObjectReleaseRunnable(const NPNetscapeFuncs* f, NPObject* o)
+    : mFuncs(f)
+    , mObject(o)
+  {
+    NS_ASSERTION(o, "no release null objects");
+  }
+
+  NS_IMETHOD Run();
+
+private:
+  const NPNetscapeFuncs* mFuncs;
+  NPObject* mObject;
+};
+
+NS_IMETHODIMP
+DeferNPObjectReleaseRunnable::Run()
+{
+  mFuncs->releaseobject(mObject);
+  return NS_OK;
+}
+
+} // anonymous namespace
+
+namespace mozilla {
+namespace plugins {
+
+void
+DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o)
+{
+  if (!o)
+    return;
+
+  if (o->referenceCount > 1) {
+    f->releaseobject(o);
+    return;
+  }
+
+  NS_DispatchToCurrentThread(new DeferNPObjectReleaseRunnable(f, o));
+}
+
+void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v)
+{
+  if (!NPVARIANT_IS_OBJECT(*v)) {
+    f->releasevariantvalue(v);
+    return;
+  }
+  DeferNPObjectLastRelease(f, v->value.objectValue);
+  VOID_TO_NPVARIANT(*v);
+}
+
+} // namespace plugins
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginMessageUtils.h
@@ -0,0 +1,611 @@
+/* -*- Mode: C++; tab-width: 4; 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/
+ *
+ * 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 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):
+ *
+ * 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 DOM_PLUGINS_PLUGINMESSAGEUTILS_H
+#define DOM_PLUGINS_PLUGINMESSAGEUTILS_H
+
+#include "IPC/IPCMessageUtils.h"
+
+#include "npapi.h"
+#include "npruntime.h"
+#include "npfunctions.h"
+#include "nsAutoPtr.h"
+#include "nsStringGlue.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+
+// XXX might want to move these to nscore.h or something, they can be
+// generally useful
+struct void_t { };
+struct null_t { };
+
+namespace ipc {
+
+typedef intptr_t NPRemoteIdentifier;
+
+} /* namespace ipc */
+
+namespace plugins {
+
+/**
+ * This is NPByteRange without the linked list.
+ */
+struct IPCByteRange
+{
+  int32_t offset;
+  uint32_t length;
+};  
+
+typedef std::vector<IPCByteRange> IPCByteRanges;
+
+typedef nsCString Buffer;
+
+struct NPRemoteWindow
+{
+  unsigned long window;
+  int32_t x;
+  int32_t y;
+  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)
+{
+    switch (aVar) {
+        VARSTR(NPPVpluginNameString);
+        VARSTR(NPPVpluginDescriptionString);
+        VARSTR(NPPVpluginWindowBool);
+        VARSTR(NPPVpluginTransparentBool);
+        VARSTR(NPPVjavaClass);
+        VARSTR(NPPVpluginWindowSize);
+        VARSTR(NPPVpluginTimerInterval);
+
+        VARSTR(NPPVpluginScriptableInstance);
+        VARSTR(NPPVpluginScriptableIID);
+
+        VARSTR(NPPVjavascriptPushCallerBool);
+
+        VARSTR(NPPVpluginKeepLibraryInMemory);
+        VARSTR(NPPVpluginNeedsXEmbed);
+
+        VARSTR(NPPVpluginScriptableNPObject);
+
+        VARSTR(NPPVformValue);
+  
+        VARSTR(NPPVpluginUrlRequestsDisplayedBool);
+  
+        VARSTR(NPPVpluginWantsAllNetworkStreams);
+
+#ifdef XP_MACOSX
+        VARSTR(NPPVpluginDrawingModel);
+        VARSTR(NPPVpluginEventModel);
+#endif
+
+    default: return "???";
+    }
+}
+
+inline const char*
+NPNVariableToString(NPNVariable aVar)
+{
+    switch(aVar) {
+        VARSTR(NPNVxDisplay);
+        VARSTR(NPNVxtAppContext);
+        VARSTR(NPNVnetscapeWindow);
+        VARSTR(NPNVjavascriptEnabledBool);
+        VARSTR(NPNVasdEnabledBool);
+        VARSTR(NPNVisOfflineBool);
+
+        VARSTR(NPNVserviceManager);
+        VARSTR(NPNVDOMElement);
+        VARSTR(NPNVDOMWindow);
+        VARSTR(NPNVToolkit);
+        VARSTR(NPNVSupportsXEmbedBool);
+
+        VARSTR(NPNVWindowNPObject);
+
+        VARSTR(NPNVPluginElementNPObject);
+
+        VARSTR(NPNVSupportsWindowless);
+
+        VARSTR(NPNVprivateModeBool);
+
+    default: return "???";
+    }
+}
+#undef VARSTR
+
+
+inline void AssertPluginThread()
+{
+  NS_ASSERTION(NS_IsMainThread(), "should be on the plugin's main thread!");
+}
+
+void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o);
+void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v);
+
+// in NPAPI, char* == NULL is sometimes meaningful.  the following is
+// helper code for dealing with nullable nsCString's
+inline nsCString
+NullableString(const char* aString)
+{
+    if (!aString) {
+        nsCString str;
+        str.SetIsVoid(PR_TRUE);
+        return str;
+    }
+    return nsCString(aString);
+}
+
+inline const char*
+NullableStringGet(const nsCString& str)
+{
+  if (str.IsVoid())
+    return NULL;
+
+  return str.get();
+}
+
+} /* namespace plugins */
+
+} /* namespace mozilla */
+
+namespace IPC {
+
+template <>
+struct ParamTraits<NPRect>
+{
+  typedef NPRect paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.top);
+    WriteParam(aMsg, aParam.left);
+    WriteParam(aMsg, aParam.bottom);
+    WriteParam(aMsg, aParam.right);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    uint16_t top, left, bottom, right;
+    if (ReadParam(aMsg, aIter, &top) &&
+        ReadParam(aMsg, aIter, &left) &&
+        ReadParam(aMsg, aIter, &bottom) &&
+        ReadParam(aMsg, aIter, &right)) {
+      aResult->top = top;
+      aResult->left = left;
+      aResult->bottom = bottom;
+      aResult->right = right;
+      return true;
+    }
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(StringPrintf(L"[%u, %u, %u, %u]", aParam.top, aParam.left,
+                              aParam.bottom, aParam.right));
+  }
+};
+
+template <>
+struct ParamTraits<NPWindowType>
+{
+  typedef NPWindowType paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    aMsg->WriteInt16(int16(aParam));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    int16 result;
+    if (aMsg->ReadInt16(aIter, &result)) {
+      *aResult = paramType(result);
+      return true;
+    }
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(StringPrintf(L"%d", int16(aParam)));
+  }
+};
+
+template <>
+struct ParamTraits<mozilla::plugins::NPRemoteWindow>
+{
+  typedef mozilla::plugins::NPRemoteWindow paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    aMsg->WriteULong(aParam.window);
+    WriteParam(aMsg, aParam.x);
+    WriteParam(aMsg, aParam.y);
+    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;
+    NPWindowType type;
+    if (!(aMsg->ReadULong(aIter, &window) &&
+          ReadParam(aMsg, aIter, &x) &&
+          ReadParam(aMsg, aIter, &y) &&
+          ReadParam(aMsg, aIter, &width) &&
+          ReadParam(aMsg, aIter, &height) &&
+          ReadParam(aMsg, aIter, &clipRect) &&
+          ReadParam(aMsg, aIter, &type)))
+      return false;
+
+#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,
+                              aParam.height, (long)aParam.type));
+  }
+};
+
+template <>
+struct ParamTraits<NPString>
+{
+  typedef NPString paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.UTF8Length);
+    aMsg->WriteBytes(aParam.UTF8Characters,
+                     aParam.UTF8Length * sizeof(NPUTF8));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (ReadParam(aMsg, aIter, &aResult->UTF8Length)) {
+      int byteCount = aResult->UTF8Length * sizeof(NPUTF8);
+      if (!byteCount) {
+        aResult->UTF8Characters = "\0";
+        return true;
+      }
+
+      const char* messageBuffer = nsnull;
+      nsAutoArrayPtr<char> newBuffer(new char[byteCount]);
+      if (newBuffer && aMsg->ReadBytes(aIter, &messageBuffer, byteCount )) {
+        memcpy((void*)messageBuffer, newBuffer.get(), byteCount);
+        aResult->UTF8Characters = newBuffer.forget();
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    aLog->append(StringPrintf(L"%s", aParam.UTF8Characters));
+  }
+};
+
+template <>
+struct ParamTraits<NPVariant>
+{
+  typedef NPVariant paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    if (NPVARIANT_IS_VOID(aParam)) {
+      aMsg->WriteInt(0);
+      return;
+    }
+
+    if (NPVARIANT_IS_NULL(aParam)) {
+      aMsg->WriteInt(1);
+      return;
+    }
+
+    if (NPVARIANT_IS_BOOLEAN(aParam)) {
+      aMsg->WriteInt(2);
+      WriteParam(aMsg, NPVARIANT_TO_BOOLEAN(aParam));
+      return;
+    }
+
+    if (NPVARIANT_IS_INT32(aParam)) {
+      aMsg->WriteInt(3);
+      WriteParam(aMsg, NPVARIANT_TO_INT32(aParam));
+      return;
+    }
+
+    if (NPVARIANT_IS_DOUBLE(aParam)) {
+      aMsg->WriteInt(4);
+      WriteParam(aMsg, NPVARIANT_TO_DOUBLE(aParam));
+      return;
+    }
+
+    if (NPVARIANT_IS_STRING(aParam)) {
+      aMsg->WriteInt(5);
+      WriteParam(aMsg, NPVARIANT_TO_STRING(aParam));
+      return;
+    }
+
+    NS_ERROR("Unsupported type!");
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    int type;
+    if (!aMsg->ReadInt(aIter, &type)) {
+      return false;
+    }
+
+    switch (type) {
+      case 0:
+        VOID_TO_NPVARIANT(*aResult);
+        return true;
+
+      case 1:
+        NULL_TO_NPVARIANT(*aResult);
+        return true;
+
+      case 2: {
+        bool value;
+        if (ReadParam(aMsg, aIter, &value)) {
+          BOOLEAN_TO_NPVARIANT(value, *aResult);
+          return true;
+        }
+      } break;
+
+      case 3: {
+        int32 value;
+        if (ReadParam(aMsg, aIter, &value)) {
+          INT32_TO_NPVARIANT(value, *aResult);
+          return true;
+        }
+      } break;
+
+      case 4: {
+        double value;
+        if (ReadParam(aMsg, aIter, &value)) {
+          DOUBLE_TO_NPVARIANT(value, *aResult);
+          return true;
+        }
+      } break;
+
+      case 5: {
+        NPString value;
+        if (ReadParam(aMsg, aIter, &value)) {
+          STRINGN_TO_NPVARIANT(value.UTF8Characters, value.UTF8Length,
+                               *aResult);
+          return true;
+        }
+      } break;
+
+      default:
+        NS_ERROR("Unsupported type!");
+    }
+
+    return false;
+  }
+
+  static void Log(const paramType& aParam, std::wstring* aLog)
+  {
+    if (NPVARIANT_IS_VOID(aParam)) {
+      aLog->append(L"[void]");
+      return;
+    }
+
+    if (NPVARIANT_IS_NULL(aParam)) {
+      aLog->append(L"[null]");
+      return;
+    }
+
+    if (NPVARIANT_IS_BOOLEAN(aParam)) {
+      LogParam(NPVARIANT_TO_BOOLEAN(aParam), aLog);
+      return;
+    }
+
+    if (NPVARIANT_IS_INT32(aParam)) {
+      LogParam(NPVARIANT_TO_INT32(aParam), aLog);
+      return;
+    }
+
+    if (NPVARIANT_IS_DOUBLE(aParam)) {
+      LogParam(NPVARIANT_TO_DOUBLE(aParam), aLog);
+      return;
+    }
+
+    if (NPVARIANT_IS_STRING(aParam)) {
+      LogParam(NPVARIANT_TO_STRING(aParam), aLog);
+      return;
+    }
+
+    NS_ERROR("Unsupported type!");
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::void_t>
+{
+  typedef mozilla::void_t paramType;
+  static void Write(Message* aMsg, const paramType& aParam) { }
+  static bool
+  Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    *aResult = paramType();
+    return true;
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::null_t>
+{
+  typedef mozilla::null_t paramType;
+  static void Write(Message* aMsg, const paramType& aParam) { }
+  static bool
+  Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    *aResult = paramType();
+    return true;
+  }
+};
+
+template <>
+struct ParamTraits<mozilla::plugins::IPCByteRange>
+{
+  typedef mozilla::plugins::IPCByteRange paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.offset);
+    WriteParam(aMsg, aParam.length);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    paramType p;
+    if (ReadParam(aMsg, aIter, &p.offset) &&
+        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.
+// 
+// NB: these guards are based on those where struct NPEvent is defined
+// in npapi.h.  They should be kept in sync.
+#if defined(XP_MACOSX)
+#  include "mozilla/plugins/NPEventOSX.h"
+#elif defined(XP_WIN)
+#  include "mozilla/plugins/NPEventWindows.h"
+#elif defined(XP_OS2)
+#  error Sorry, OS/2 is not supported
+#elif defined(XP_UNIX) && defined(MOZ_X11)
+#  include "mozilla/plugins/NPEventX11.h"
+#else
+#  error Unsupported platform
+#endif
+
+
+#endif /* DOM_PLUGINS_PLUGINMESSAGEUTILS_H */
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -0,0 +1,1502 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * 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/
+ *
+ * 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 Plugin App.
+ *
+ * The Initial Developer of the Original Code is
+ *   Ben Turner <bent.mozilla@gmail.com>.
+ * 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 ***** */
+
+#include "mozilla/plugins/PluginModuleChild.h"
+
+#ifdef OS_LINUX
+#include <gtk/gtk.h>
+#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;
+}
+
+
+PluginModuleChild::PluginModuleChild() :
+    mLibrary(0),
+    mInitializeFunc(0),
+    mShutdownFunc(0)
+#ifdef OS_WIN
+  , mGetEntryPointsFunc(0)
+#endif
+//  ,mNextInstanceId(0)
+{
+    NS_ASSERTION(!gInstance, "Something terribly wrong here!");
+    memset(&mFunctions, 0, sizeof(mFunctions));
+    memset(&mSavedData, 0, sizeof(mSavedData));
+    gInstance = this;
+}
+
+PluginModuleChild::~PluginModuleChild()
+{
+    NS_ASSERTION(gInstance == this, "Something terribly wrong here!");
+    if (mLibrary) {
+        PR_UnloadLibrary(mLibrary);
+    }
+    gInstance = nsnull;
+}
+
+// static
+PluginModuleChild*
+PluginModuleChild::current()
+{
+    NS_ASSERTION(gInstance, "Null instance!");
+    return gInstance;
+}
+
+bool
+PluginModuleChild::Init(const std::string& aPluginFilename,
+                        base::ProcessHandle aParentProcessHandle,
+                        MessageLoop* aIOLoop,
+                        IPC::Channel* aChannel)
+{
+    _MOZ_LOG(__FUNCTION__);
+
+    NS_ASSERTION(aChannel, "need a channel");
+
+    if (!mObjectMap.Init()) {
+       NS_WARNING("Failed to initialize object hashtable!");
+       return false;
+    }
+
+    if (!InitGraphics())
+        return false;
+
+    nsCString filename;
+    filename = aPluginFilename.c_str();
+    nsCOMPtr<nsILocalFile> pluginFile;
+    NS_NewNativeLocalFile(filename,
+                          PR_TRUE,
+                          getter_AddRefs(pluginFile));
+
+    PRBool exists;
+    pluginFile->Exists(&exists);
+    NS_ASSERTION(exists, "plugin file ain't there");
+
+    nsCOMPtr<nsIFile> pluginIfile;
+    pluginIfile = do_QueryInterface(pluginFile);
+
+    nsPluginFile lib(pluginIfile);
+
+    nsresult rv = lib.LoadPlugin(mLibrary);
+    NS_ASSERTION(NS_OK == rv, "trouble with mPluginFile");
+    NS_ASSERTION(mLibrary, "couldn't open shared object");
+
+    if (!Open(aChannel, aParentProcessHandle, aIOLoop))
+        return false;
+
+    memset((void*) &mFunctions, 0, sizeof(mFunctions));
+    mFunctions.size = sizeof(mFunctions);
+
+    // TODO: use PluginPRLibrary here
+
+#if defined(OS_LINUX)
+    mShutdownFunc =
+        (NP_PLUGINSHUTDOWN) PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
+
+    // create the new plugin handler
+
+    mInitializeFunc =
+        (NP_PLUGINUNIXINIT) PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
+    NS_ASSERTION(mInitializeFunc, "couldn't find NP_Initialize()");
+
+#elif defined(OS_WIN)
+    mShutdownFunc =
+        (NP_PLUGINSHUTDOWN)PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
+
+    mGetEntryPointsFunc =
+        (NP_GETENTRYPOINTS)PR_FindSymbol(mLibrary, "NP_GetEntryPoints");
+    NS_ENSURE_TRUE(mGetEntryPointsFunc, false);
+