Merge cvs-trunk-mirror -> mozilla-central
authorbenjamin@smedbergs.us
Wed, 12 Mar 2008 16:32:37 -0400
changeset 12958 53dea32196b947f4786a8ef1795cb52541c1a4d0
parent 12892 8b08cdbcac631ee5fcf3c73f6f660ac9624b0ab3 (current diff)
parent 12957 eda42c3870f5a815c75507d92e8a22c0e4199c42 (diff)
child 13007 8f4b429275a5e05b3baa46a147237f53fe26b208
push idunknown
push userunknown
push dateunknown
milestone2.0a1pre
Merge cvs-trunk-mirror -> mozilla-central
config/autoconf.mk.in
configure.in
js/src/Makefile.ref
js/src/jsarray.cpp
js/src/jsnum.cpp
js/src/rules.mk
toolkit/toolkit-makefiles.sh
xpcom/base/nscore.h
xpcom/tests/Makefile.in
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -68,19 +68,19 @@ pref("extensions.logging.enabled", false
 // Hides the install button in the add-ons mgr
 pref("extensions.hideInstallButton", true);
 
 // Preferences for the Get Add-ons pane
 pref("extensions.getAddons.showPane", true);
 pref("extensions.getAddons.browseAddons", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%");
 pref("extensions.getAddons.maxResults", 5);
 pref("extensions.getAddons.recommended.browseURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/recommended");
-pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/list/featured/all/10");
+pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/list/featured/all/10/%OS%/%VERSION%");
 pref("extensions.getAddons.search.browseURL", "https://%LOCALE%.add-ons.mozilla.com/%LOCALE%/%APP%/search?q=%TERMS%");
-pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/search/%TERMS%");
+pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/10/%OS%/%VERSION%");
 
 // Blocklist preferences
 pref("extensions.blocklist.enabled", true);
 pref("extensions.blocklist.interval", 86400);
 pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/1/%APP_ID%/%APP_VERSION%/");
 pref("extensions.blocklist.detailsURL", "http://%LOCALE%.www.mozilla.com/%LOCALE%/blocklist/");
 
 // Dictionary download preference
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -36,24 +36,36 @@
 #
 # ***** END LICENSE BLOCK *****
 
        <menubar id="main-menubar" statusbar="statusbar-display"
                 style="border:0px;padding:0px;margin:0px;-moz-appearance:none">
             <menu id="file-menu" label="&fileMenu.label;"
                   accesskey="&fileMenu.accesskey;">
               <menupopup id="menu_FilePopup" onpopupshowing="getContentAreaFrameCount();">
-                <menuitem label="&newNavigatorCmd.label;"
+                <menuitem id="menu_newNavigator"
+                          label="&newNavigatorCmd.label;"
                           accesskey="&newNavigatorCmd.accesskey;"
                           key="key_newNavigator"
                           command="cmd_newNavigator"/>
-                <menuitem command="cmd_newNavigatorTab" key="key_newNavigatorTab"
-                          label="&tabCmd.label;" accesskey="&tabCmd.accesskey;"/>
-                <menuitem label="&openLocationCmd.label;" accesskey="&openLocationCmd.accesskey;" key="focusURLBar" command="Browser:OpenLocation"/>
-                <menuitem label="&openFileCmd.label;" accesskey="&openFileCmd.accesskey;" key="openFileKb" command="Browser:OpenFile"/>
+                <menuitem id="menu_newNavigatorTab"
+                          label="&tabCmd.label;"
+                          command="cmd_newNavigatorTab"
+                          key="key_newNavigatorTab"
+                          accesskey="&tabCmd.accesskey;"/>
+                <menuitem id="menu_openLocation"
+                          label="&openLocationCmd.label;"
+                          command="Browser:OpenLocation"
+                          key="focusURLBar"
+                          accesskey="&openLocationCmd.accesskey;"/>
+                <menuitem id="menu_openFile"
+                          label="&openFileCmd.label;"
+                          command="Browser:OpenFile"
+                          key="openFileKb"
+                          accesskey="&openFileCmd.accesskey;"/>
                 <menuitem id="menu_closeWindow" hidden="true" command="cmd_closeWindow" key="key_closeWindow" label="&closeWindow.label;" accesskey="&closeWindow.accesskey;"/>
                 <menuitem id="menu_close" label="&closeCmd.label;" key="key_close" accesskey="&closeCmd.accesskey;" command="cmd_close"/>
                 <menuseparator/>
                 <menuitem label="&savePageCmd.label;" accesskey="&savePageCmd.accesskey;" key="key_savePage" command="Browser:SavePage"/>
                 <menuitem id="menu_saveFrame" label="&saveFrameCmd.label;" accesskey="&saveFrameCmd.accesskey;" command="Browser:SaveFrame" hidden="true"/>
                 <menuitem id="menu_sendLink"  label="&sendPageCmd.label;"  accesskey="&sendPageCmd.accesskey;"  command="Browser:SendLink"/>
                 <menuseparator/>
                 <menuitem label="&printSetupCmd.label;" accesskey="&printSetupCmd.accesskey;" command="cmd_pageSetup"/>
@@ -407,18 +419,20 @@
         <menupopup id="subscribeToPageSubmenuMenupopup" 
                    onpopupshowing="return FeedHandler.buildFeedList(event.target);" 
                    oncommand="return FeedHandler.subscribeToFeed(null, event);"
                    onclick="checkForMiddleClick(this, event);"/>
       </menu>
       <menuitem label="&addCurPagesCmd.label;" 
                 command="Browser:BookmarkAllTabs" key="bookmarkAllTabsKb"/>
       <menuseparator id="organizeBookmarksSeparator"/>
-      <menuitem label="&showAllBookmarksCmd2.label;" 
-                command="Browser:ShowAllBookmarks" key="manBookmarkKb"/>
+      <menuitem id="bookmarksShowAll"
+                label="&showAllBookmarksCmd2.label;"
+                command="Browser:ShowAllBookmarks"
+                key="manBookmarkKb"/>
       <menu id="bookmarksToolbarFolderMenu"
             class="menu-iconic bookmark-item"
             container="true">
         <menupopup id="bookmarksToolbarFolderPopup"
                    type="places"
                    context="placesContext"
                    oncommand="BookmarksEventHandler.onCommand(event);"
                    onclick="BookmarksEventHandler.onClick(event);"
@@ -427,17 +441,17 @@
       <menuseparator builder="start"/>
     </menupopup>
   </menu>
 
             <menu id="tools-menu" label="&toolsMenu.label;" accesskey="&toolsMenu.accesskey;">
               <menupopup id="menu_ToolsPopup">
               <menuitem label="&search.label;" accesskey="&search.accesskey;" 
                         key="key_search" command="Tools:Search"/>
-              <menuseparator/>
+              <menuseparator id="browserToolsSeparator"/>
               <menuitem id="menu_openDownloads" label="&downloads.label;"
                         accesskey="&downloads.accesskey;"
                         key="key_openDownloads" command="Tools:Downloads"/>
               <menuitem id="menu_openAddons" label="&addons.label;"
                         accesskey="&addons.accesskey;" command="Tools:Addons"/>
               <menuseparator id="devToolsSeparator"/>
               <menuitem id="javascriptConsole" 
                         label="&errorConsoleCmd.label;" accesskey="&errorConsoleCmd.accesskey;" 
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -632,79 +632,96 @@ var BookmarksEventHandler = {
    * Handler for popupshowing event for an item in bookmarks toolbar or menu.
    * If the item isn't the main bookmarks menu, add an "Open All in Tabs"
    * menuitem to the bottom of the popup.
    * @param event 
    *        DOMEvent for popupshowing
    */
   onPopupShowing: function BM_onPopupShowing(event) {
     var target = event.originalTarget;
-    if (target.localName == "menupopup" &&
-        target.id != "bookmarksMenuPopup" &&
-        target.getAttribute("anonid") != "chevronPopup") {
-      // Add the "Open All in Tabs" menuitem if there are
-      // at least two menuitems with places result nodes.
-      // Add the "Open (Feed Name)" menuitem if it's a livemark with a siteURI.
-      var numNodes = 0;
-      var hasMultipleEntries = false;
-      var currentChild = target.firstChild;
-      while (currentChild) {
-        if (currentChild.localName == "menuitem" && currentChild.node)
-          numNodes++;
-
-        // If the menuitem already exists, do nothing.
-        if (currentChild.getAttribute("openInTabs") == "true")
-          return;
-        if (currentChild.hasAttribute("siteURI"))
-          return;
-
-        currentChild = currentChild.nextSibling;
-      }
-      if (numNodes > 1)
-        hasMultipleEntries = true;
+    if (!target.hasAttribute("placespopup"))
+      return;
 
-      var itemId = target._resultNode.itemId;
-      var siteURIString = "";
-      if (itemId != -1 && PlacesUtils.livemarks.isLivemark(itemId)) {
-        var siteURI = PlacesUtils.livemarks.getSiteURI(itemId);
-        if (siteURI)
-          siteURIString = siteURI.spec;
-      }
-
-      if (hasMultipleEntries || siteURIString) {
-        var separator = document.createElement("menuseparator");
-        target.appendChild(separator);
-
-        if (siteURIString) {
-          var openHomePage = document.createElement("menuitem");
-          openHomePage.setAttribute("siteURI", siteURIString);
-          openHomePage.setAttribute("oncommand",
-              "openUILink(this.getAttribute('siteURI'), event);");
-          // If a user middle-clicks this item we serve the oncommand event
-          // We are using checkForMiddleClick because of Bug 246720
-          // Note: stopPropagation is needed to avoid serving middle-click 
-          // with BT_onClick that would open all items in tabs
-          openHomePage.setAttribute("onclick",
-              "checkForMiddleClick(this, event); event.stopPropagation();");
-          openHomePage.setAttribute("label",
-              PlacesUtils.getFormattedString("menuOpenLivemarkOrigin.label",
-              [target.parentNode.getAttribute("label")]));
-          target.appendChild(openHomePage);
-        }
-
-        if (hasMultipleEntries) {
-          var openInTabs = document.createElement("menuitem");
-          openInTabs.setAttribute("openInTabs", "true");
-          openInTabs.setAttribute("oncommand",
-                                  "PlacesUtils.openContainerNodeInTabs(this.parentNode._resultNode, event);");
-          openInTabs.setAttribute("label",
-                     gNavigatorBundle.getString("menuOpenAllInTabs.label"));
-          target.appendChild(openInTabs);
+    // Check if the popup contains at least 2 menuitems with places nodes
+    var numNodes = 0;
+    var hasMultipleURIs = false;
+    var currentChild = target.firstChild;
+    while (currentChild) {
+      if (currentChild.localName == "menuitem" && currentChild.node) {
+        if (++numNodes == 2) {
+          hasMultipleURIs = true;
+          break;
         }
       }
+      currentChild = currentChild.nextSibling;
+    }
+
+    var itemId = target._resultNode.itemId;
+    var siteURIString = "";
+    if (itemId != -1 && PlacesUtils.livemarks.isLivemark(itemId)) {
+      var siteURI = PlacesUtils.livemarks.getSiteURI(itemId);
+      if (siteURI)
+        siteURIString = siteURI.spec;
+    }
+
+    if (!siteURIString && target._endOptOpenSiteURI) {
+        target.removeChild(target._endOptOpenSiteURI);
+        target._endOptOpenSiteURI = null;
+    }
+
+    if (!hasMultipleURIs && target._endOptOpenAllInTabs) {
+      target.removeChild(target._endOptOpenAllInTabs);
+      target._endOptOpenAllInTabs = null;
+    }
+
+    if (!(hasMultipleURIs || siteURIString)) {
+      // we don't have to show any option
+      if (target._endOptSeparator) {
+        target.removeChild(target._endOptSeparator);
+        target._endOptSeparator = null;
+        target._endMarker = -1;
+      }
+      return;
+    }
+
+    if (!target._endOptSeparator) {
+      // create a separator before options
+      target._endOptSeparator = document.createElement("menuseparator");
+      target._endOptSeparator.setAttribute("builder", "end");
+      target._endMarker = target.childNodes.length;
+      target.appendChild(target._endOptSeparator);
+    }
+
+    if (siteURIString && !target._endOptOpenSiteURI) {
+      // Add "Open (Feed Name)" menuitem if it's a livemark with a siteURI
+      target._endOptOpenSiteURI = document.createElement("menuitem");
+      target._endOptOpenSiteURI.setAttribute("siteURI", siteURIString);
+      target._endOptOpenSiteURI.setAttribute("oncommand",
+          "openUILink(this.getAttribute('siteURI'), event);");
+      // If a user middle-clicks this item we serve the oncommand event
+      // We are using checkForMiddleClick because of Bug 246720
+      // Note: stopPropagation is needed to avoid serving middle-click 
+      // with BT_onClick that would open all items in tabs
+      target._endOptOpenSiteURI.setAttribute("onclick",
+          "checkForMiddleClick(this, event); event.stopPropagation();");
+      target._endOptOpenSiteURI.setAttribute("label",
+          PlacesUtils.getFormattedString("menuOpenLivemarkOrigin.label",
+          [target.parentNode.getAttribute("label")]));
+      target.appendChild(target._endOptOpenSiteURI);
+    }
+
+    if (hasMultipleURIs && !target._endOptOpenAllInTabs) {
+        // Add the "Open All in Tabs" menuitem if there are
+        // at least two menuitems with places result nodes.
+        target._endOptOpenAllInTabs = document.createElement("menuitem");
+        target._endOptOpenAllInTabs.setAttribute("oncommand",
+            "PlacesUtils.openContainerNodeInTabs(this.parentNode._resultNode, event);");
+        target._endOptOpenAllInTabs.setAttribute("label",
+            gNavigatorBundle.getString("menuOpenAllInTabs.label"));
+        target.appendChild(target._endOptOpenAllInTabs);
     }
   },
 
   fillInBTTooltip: function(aTipElement) {
     // Fx2XP: Don't show tooltips for bookmarks under sub-folders
     if (aTipElement.localName != "toolbarbutton")
       return false;
 
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -73,16 +73,18 @@
 
       <!-- markers for start and end of valid places items -->
       <field name="_startMarker">-1</field>
       <field name="_endMarker">-1</field>
 
       <!-- This is the view that manage the popup -->
       <field name="_rootView">PlacesUtils.getViewForNode(this);</field>
 
+      <field name="_built">false</field>
+
       <method name="onDragOver">
         <parameter name="aEvent"/>
         <parameter name="aFlavour"/>
         <parameter name="aDragSession"/>
         <body><![CDATA[
           PlacesControllerDragHelper.currentDropTarget = aEvent.target;
           // check if we have a valid dropPoint
           var dropPoint = this._getDropPoint(aEvent);
@@ -226,24 +228,24 @@
         <parameter name="aEvent"/>
         <body><![CDATA[
           var target = aEvent.target;
 
           // in some view we have _startMarker and _endMarker, we should not
           // draw the drop indicator outside of them
           var betweenMarkers = true;
           if (this._startMarker != -1 &&
-              target.boxObject.y < this.childNodes[this._startMarker].boxObject.y)
+              target.boxObject.y <= this.childNodes[this._startMarker].boxObject.y)
             betweenMarkers = false;
           if (this._endMarker != -1 &&
-              target.boxObject.y > this.childNodes[this._endMarker].boxObject.y)
+              target.boxObject.y >= this.childNodes[this._endMarker].boxObject.y)
             betweenMarkers = false;
 
           // hide the dropmarker if current node is not a places bookmark item
-          return !(target && betweenMarkers && this.canDrop());
+          return !(target && target.node && betweenMarkers && this.canDrop());
         ]]></body>
       </method>
 
       <!-- This function returns information about where to drop when
            dragging over this popup insertion point -->
       <method name="_getDropPoint">
         <parameter name="aEvent"/>
           <body><![CDATA[
@@ -447,16 +449,46 @@
             this._folder.closeTimer = null;
           }
         }
       })]]></field>
 
     </implementation>
 
     <handlers>
+      <handler event="DOMMenuItemActive"><![CDATA[
+        var node = event.target;
+        if (node.parentNode != this)
+          return;
+
+#ifdef XP_MACOSX
+        // XXXschonfeld: The following check is a temporary hack
+        // until bug 420033 is resolved.
+        while (node) {
+          if (node.id == "bookmarksMenuPopup" || node.id == "goPopup")
+            return;
+
+          node = node.parentNode;
+        }
+#endif
+
+        if (window.XULBrowserWindow) {
+          var nodeItem = event.target.node;
+          if (nodeItem && PlacesUtils.nodeIsURI(nodeItem))
+            window.XULBrowserWindow.setOverLink(nodeItem.uri, null);
+        }
+      ]]></handler>
+      <handler event="DOMMenuItemInactive"><![CDATA[
+        var node = event.target;
+        if (node.parentNode != this)
+          return;
+
+        if (window.XULBrowserWindow)
+          window.XULBrowserWindow.setOverLink("", null);
+      ]]></handler>
       <handler event="draggesture" action="if (event.target.node) nsDragAndDrop.startDrag(event, this);"/>
       <handler event="dragdrop" action="nsDragAndDrop.drop(event, this);"/>
       <handler event="dragover" action="nsDragAndDrop.dragOver(event, this);"/>
       <handler event="dragexit" action="nsDragAndDrop.dragExit(event, this);"/>
     </handlers>
   </binding>
 
 
@@ -489,24 +521,23 @@
           this._initialized = true;
         ]]></body>
       </method>
 
       <property name="controller"
                 readonly="true"
                 onget="return this._controller;"/>
 
-      <field name="_built">false</field>
-
       <method name="onPopupShowing">
         <parameter name="aEvent"/>
         <body><![CDATA[
           var popup = aEvent.target;
           var resultNode = popup._resultNode;
-          resultNode.containerOpen = true;
+          if (!resultNode.containerOpen)
+            resultNode.containerOpen = true;
           if (!popup._built)
             this._rebuild(popup);
         ]]></body>
       </method>
 
       <!-- nsIPlacesView -->
       <method name="getResult">
         <body><![CDATA[
@@ -517,68 +548,16 @@
       <!-- nsIPlacesView -->
       <method name="getResultNode">
         <body><![CDATA[
           this._ensureInitialized();
           return this._resultNode;
         ]]></body>
       </method>
 
-      <method name="_cleanMenu">
-        <parameter name="aPopup"/>
-        <body><![CDATA[
-          // Find static menuitems that should go at the start
-          // and end of the menu, marked by builder="start" and
-          // builder="end" attributes, and keep track of their indices.
-          // All of the items between the start and end should be removed.
-          var items = [];
-          aPopup._startMarker = -1;
-          aPopup._endMarker = -1;
-          for (var i = 0; i < aPopup.childNodes.length; ++i) {
-            var item = aPopup.childNodes[i];
-            if (item.getAttribute("builder") == "start") {
-              aPopup._startMarker = i;
-              continue;
-            }
-            if (item.getAttribute("builder") == "end") {
-              aPopup._endMarker = i;
-              continue;
-            }
-            if ((aPopup._startMarker != -1) && (aPopup._endMarker == -1))
-              items.push(item);
-          }
-
-          // If static items at the beginning were found, remove all items between
-          // them and the static content at the end.
-          for (var i = 0; i < items.length; ++i) { 
-            // skip the empty menu item
-            if (aPopup._emptyMenuItem != items[i]) {
-              aPopup.removeChild(items[i]);
-              if (this._endMarker > 0)
-                --this._endMarker;
-            }
-          }
-
-          // If no static items were found at the beginning, remove all items before
-          // the static items at the end.
-          if (aPopup._startMarker == -1) {
-            var end = aPopup._endMarker == -1 ?
-                      aPopup.childNodes.length - 1 : aPopup._endMarker - 1;
-            for (var i = end; i >=0; i--) {
-              // skip the empty menu item
-              if (aPopup._emptyMenuItem != aPopup.childNodes[i]) {
-                aPopup.removeChild(aPopup.childNodes[i]);
-                if (aPopup._endMarker > 0)
-                  --aPopup._endMarker;
-              }
-            }
-          }
-        ]]></body>
-      </method>
-
       <method name="removeItem">
         <parameter name="child"/>
         <body><![CDATA[
           if (PlacesUtils.nodeIsContainer(child.node)) {
             for (var i=0; i < this._containerNodesMap.length; i++) {
               if (this._containerNodesMap[i].resultNode == child.node) {
                 this._containerNodesMap.splice(i, 1);
                 break;
@@ -632,17 +611,17 @@
           aPopup._emptyMenuItem.setAttribute("disabled", true);
           aPopup.appendChild(aPopup._emptyMenuItem);
         ]]></body>
       </method>
 
       <method name="_rebuild">
         <parameter name="aPopup"/>
         <body><![CDATA[
-          this._cleanMenu(aPopup);
+          PlacesUtils.cleanPlacesPopup(aPopup);
 
           var cc = aPopup._resultNode.childCount;
           if (cc > 0) {
             if (aPopup._emptyMenuItem)
               aPopup._emptyMenuItem.hidden = true;
 
             for (var i = 0; i < cc; ++i) {
               var child = aPopup._resultNode.getChild(i);
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -978,53 +978,60 @@
 
       <method name="insertNewItemToPopup">
         <parameter name="aChild"/>
         <parameter name="aParentPopup"/>
         <parameter name="aBefore"/>
         <body><![CDATA[
           var element =
             PlacesUtils.createMenuItemForNode(aChild, this._containerNodesMap);
+
           if (aBefore)
             aParentPopup.insertBefore(element, aBefore);
-          else
-            aParentPopup.appendChild(element);
+          else {
+            // Add the new element to the menu.  If there is static content at
+            // the end of the menu, add the element before that.  Otherwise,
+            // just add to the end.
+            if (aParentPopup._endMarker != -1) {
+              aParentPopup.insertBefore(element,
+                                        aParentPopup.childNodes[aParentPopup._endMarker++]);
+            }
+            else
+              aParentPopup.appendChild(element);
+          }
         ]]></body>
       </method>
 
       <method name="_containerPopupShowing">
         <parameter name="aPopup"/>
         <body><![CDATA[
           if (aPopup._built)
             return;
 
-          // remove previous menu items
-          while (aPopup.hasChildNodes())
-            aPopup.removeChild(aPopup.firstChild);
-          // restore the empty-menu item if has been created already
-          if (aPopup._emptyMenuItem)
-            aPopup.appendChild(aPopup._emptyMenuItem);
+          PlacesUtils.cleanPlacesPopup(aPopup);
 
           var resultNode = aPopup._resultNode;
           if (!resultNode.containerOpen)
             resultNode.containerOpen = true;
 
           var cc = resultNode.childCount;
           if (cc > 0) {
             if (aPopup._emptyMenuItem)
               aPopup._emptyMenuItem.hidden = true;
 
             for (var i = 0; i < cc; ++i) {
               var child = resultNode.getChild(i);
               this.insertNewItemToPopup(child, aPopup, null);
             }
           }
           else {
-            // add element to show it is empty.
-            this._showEmptyMenuItem(aPopup);
+            // This menu is empty.  If there is no static content, add
+            // an element to show it is empty.
+            if (aPopup._startMarker == -1 && aPopup._endMarker == -1)
+              this._showEmptyMenuItem(aPopup);
           }
           aPopup._built = true;
         ]]></body>
       </method>
 
       <method name="_isChevronChild">
         <parameter name="aChild"/>
         <body><![CDATA[
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -1848,17 +1848,16 @@ var PlacesUtils = {
     else {
       var iconURI = aNode.icon;
       var iconURISpec = "";
       if (iconURI)
         iconURISpec = iconURI.spec;
 
       if (this.uriTypes.indexOf(type) != -1) {
         element = document.createElement("menuitem");
-        element.setAttribute("statustext", aNode.uri);
         element.className = "menuitem-iconic bookmark-item";
       }
       else if (this.containerTypes.indexOf(type) != -1) {
         element = document.createElement("menu");
         element.setAttribute("container", "true");
 
         if (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY)
           element.setAttribute("query", "true");
@@ -1891,16 +1890,64 @@ var PlacesUtils = {
         element.setAttribute("image", iconURISpec);
     }
     element.node = aNode;
     element.node.viewIndex = 0;
 
     return element;
   },
 
+  cleanPlacesPopup: function PU_cleanPlacesPopup(aPopup) {
+    // Find static menuitems at the start and at the end of the menupopup,
+    // marked by builder="start" and builder="end" attributes, and set
+    // markers to keep track of their indices.
+    var items = [];
+    aPopup._startMarker = -1;
+    aPopup._endMarker = -1;
+    for (var i = 0; i < aPopup.childNodes.length; ++i) {
+      var item = aPopup.childNodes[i];
+      if (item.getAttribute("builder") == "start") {
+        aPopup._startMarker = i;
+        continue;
+      }
+      if (item.getAttribute("builder") == "end") {
+        aPopup._endMarker = i;
+        continue;
+      }
+      if ((aPopup._startMarker != -1) && (aPopup._endMarker == -1))
+        items.push(item);
+    }
+
+    // If static items at the beginning were found, remove all items between
+    // them and the static content at the end.
+    for (var i = 0; i < items.length; ++i) {
+      // skip the empty menu item
+      if (aPopup._emptyMenuItem != items[i]) {
+        aPopup.removeChild(items[i]);
+        if (this._endMarker > 0)
+          --this._endMarker;
+      }
+    }
+
+    // If no static items were found at the beginning, remove all items before
+    // the static items at the end.
+    if (aPopup._startMarker == -1) {
+      var end = aPopup._endMarker == -1 ?
+                aPopup.childNodes.length - 1 : aPopup._endMarker - 1;
+      for (var i = end; i >= 0; i--) {
+        // skip the empty menu item
+        if (aPopup._emptyMenuItem != aPopup.childNodes[i]) {
+          aPopup.removeChild(aPopup.childNodes[i]);
+          if (aPopup._endMarker > 0)
+            --aPopup._endMarker;
+        }
+      }
+    }
+  },
+
   getBestTitle: function PU_getBestTitle(aNode) {
     var title;
     if (!aNode.title && this.uriTypes.indexOf(aNode.type) != -1) {
       // if node title is empty, try to set the label using host and filename
       // this._uri() will throw if aNode.uri is not a valid URI
       try {
         var uri = this._uri(aNode.uri);
         var host = uri.host;
--- a/browser/locales/en-US/os2/README.txt
+++ b/browser/locales/en-US/os2/README.txt
@@ -72,16 +72,17 @@ problems and installation issues with Fi
     older MPTS versions, which may result in crashes and data loss.
 
   + Convenience Pack 2 or eComStation 1.0 or later meet these requirements
     out of the box.
 
 - Useful optional software
   The following packages enable additional features in Firefox. Download
   locations are listed below with a detailed description of the features.
+  + Remote Workplace Server (RWS), version 0.8
   + Doodle's Screen Saver (DSSaver), version 1.8 or later
 
 ================================================================================
 
                           Installation Instructions
 
 ================================================================================
 
@@ -188,20 +189,43 @@ behavior of Firefox on OS/2:
   This causes Firefox not to use OS/2's high resolution timer. Set this if
   other applications using the high resolution timer (multimedia apps) act
   strangely.
 
 - set MOZ_NO_REMOTE=1
   Use this to run two instances of Firefox simultaneously (like e.g. debug
   and optimized version).
 
+- set MOZ_NO_RWS=1
+  Use this to disable Remote Workplace Server support (see below).
+
 Find more information on this topic and other tips on
    http://www.os2bbs.com/os2news/Warpzilla.html
 
 
+Support for WPS objects in the browser
+--------------------------------------
+
+Firefox can make use of Rich Walsh's Remote Workplace Server (RWS) library to
+access Workplace Shell objects from the browser. This allows helper applications
+for downloaded files to be selected based on their default WPS association. In
+addition, the WPS icons of files will be displayed in the download dialog and in
+directory views.
+
+To enable this functionality, Firefox has to find the RWS DLLs. They have to be
+located in a directory on the LIBPATH, in the Firefox directory, or already be
+registered as a WPS class. For eComStation 2 this is already the case. If RWS
+is not yet available on your system, download it from
+   http://hobbes.nmsu.edu/cgi-bin/h-search?key=rws08dll
+
+If RWS is found on the system, it is used by Firefox automatically. In case you
+need to disable RWS support, create an environment variable MOZ_NO_RWS and set
+it to 1.
+
+
 Idle timer for internal cleanups
 --------------------------------
 
 If Doodle's Screen Saver (DSSaver) v1.8 or later is installed, Firefox can
 determine how long the user has been inactive. If the user has been inactive
 for a while, cleanup operations are performed (e.g. on the browsing history)
 and reloads of "Live Bookmarks" are suspended.
 
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -117,16 +117,17 @@ endif
 ifdef WRAP_SYSTEM_INCLUDES
 export::
 	if test ! -d system_wrappers; then mkdir system_wrappers; fi
 	$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) \
 		-DBUILD_STATIC_LIBS=$(BUILD_STATIC_LIBS) \
 		-DMOZ_TREE_CAIRO=$(MOZ_TREE_CAIRO) \
 		-DMOZ_ENABLE_LIBXUL=$(MOZ_ENABLE_LIBXUL) \
 		-DMOZ_NATIVE_HUNSPELL=$(MOZ_NATIVE_HUNSPELL) \
+		-DMOZ_NATIVE_BZ2=$(MOZ_NATIVE_BZ2) \
 		-DMOZ_NATIVE_ZLIB=$(MOZ_NATIVE_ZLIB) \
 		-DMOZ_NATIVE_PNG=$(MOZ_NATIVE_PNG) \
 		-DMOZ_NATIVE_JPEG=$(MOZ_NATIVE_JPEG) \
 		-DMOZ_NATIVE_LCMS=$(MOZ_NATIVE_LCMS) \
 		$(srcdir)/system-headers | $(PERL) $(topsrcdir)/nsprpub/config/make-system-wrappers.pl system_wrappers
 	$(INSTALL) system_wrappers $(DIST)/include
 
 GARBAGE_DIRS += system_wrappers
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -209,16 +209,17 @@ NECKO_SMALL_BUFFERS = @NECKO_SMALL_BUFFE
 NECKO_COOKIES = @NECKO_COOKIES@
 MOZ_AUTH_EXTENSION = @MOZ_AUTH_EXTENSION@
 
 MOZ_NATIVE_HUNSPELL = @SYSTEM_HUNSPELL@
 MOZ_HUNSPELL_LIBS = @MOZ_HUNSPELL_LIBS@
 MOZ_HUNSPELL_CFLAGS = @MOZ_HUNSPELL_CFLAGS@
 
 MOZ_NATIVE_ZLIB	= @SYSTEM_ZLIB@
+MOZ_NATIVE_BZ2	= @SYSTEM_BZ2@
 MOZ_NATIVE_JPEG	= @SYSTEM_JPEG@
 MOZ_NATIVE_PNG	= @SYSTEM_PNG@
 MOZ_TREE_CAIRO = @MOZ_TREE_CAIRO@
 
 MOZ_UPDATE_XTERM = @MOZ_UPDATE_XTERM@
 MOZ_MATHML = @MOZ_MATHML@
 MOZ_PERMISSIONS = @MOZ_PERMISSIONS@
 MOZ_XTF = @MOZ_XTF@
@@ -404,16 +405,26 @@ ZLIB_CFLAGS	= @MOZ_ZLIB_CFLAGS@
 ifdef MOZ_ENABLE_LIBXUL
 MOZ_ZLIB_LIBS = @MOZ_ZLIB_LIBS@
 else
 ZLIB_LIBS = @MOZ_ZLIB_LIBS@
 endif
 ZLIB_REQUIRES	= zlib
 endif
 
+ifdef MOZ_NATIVE_BZ2
+BZ2_CFLAGS	= @BZ2_CFLAGS@
+BZ2_LIBS	= @BZ2_LIBS@
+BZ2_REQUIRES	=
+else
+BZ2_CFLAGS	= @MOZ_BZ2_CFLAGS@
+BZ2_LIBS	= @MOZ_BZ2_LIBS@
+BZ2_REQUIRES	= libbz2
+endif
+
 ifdef MOZ_NATIVE_PNG
 PNG_CFLAGS	= @PNG_CFLAGS@
 PNG_LIBS	= @PNG_LIBS@
 PNG_REQUIRES	=
 else
 PNG_CFLAGS	= @MOZ_PNG_CFLAGS@
 PNG_LIBS	= @MOZ_PNG_LIBS@
 PNG_REQUIRES	= png
--- a/config/system-headers
+++ b/config/system-headers
@@ -966,8 +966,11 @@ libsn/sn-common.h
 libsn/sn-launchee.h
 libsn/sn-launcher.h
 libsn/sn-monitor.h
 libsn/sn-util.h
 #endif
 #if MOZ_NATIVE_HUNSPELL==1
 hunspell.hxx
 #endif
+#if MOZ_NATIVE_BZ2==1
+bzlib.h
+#endif
--- a/configure.in
+++ b/configure.in
@@ -916,16 +916,18 @@ WIN_TOP_SRC=
 MOZ_USER_DIR=".mozilla"
 HOST_AR='$(AR)'
 HOST_AR_FLAGS='$(AR_FLAGS)'
 
 MOZ_JPEG_CFLAGS=
 MOZ_JPEG_LIBS='$(call EXPAND_LIBNAME_PATH,mozjpeg,$(DEPTH)/jpeg)'
 MOZ_ZLIB_CFLAGS=
 MOZ_ZLIB_LIBS='$(call EXPAND_LIBNAME_PATH,mozz,$(DEPTH)/modules/zlib/src)'
+MOZ_BZ2_CFLAGS=
+MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)'
 MOZ_PNG_CFLAGS=
 MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/modules/libimg/png)'
 
 MOZ_JS_LIBS='-L$(LIBXUL_DIST)/bin -lmozjs'
 DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core'
 MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin'
 XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxpcom'
 LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) -lxul'
@@ -943,16 +945,17 @@ MOZ_GFX_TOOLKIT='$(MOZ_WIDGET_TOOLKIT)'
 MOZ_ENABLE_POSTSCRIPT=1 
 
 if test -n "$CROSS_COMPILE"; then
     OS_TARGET="${target_os}"
     OS_ARCH=`echo $target_os | sed -e 's|/|_|g'`
     OS_RELEASE=
     case "${target_os}" in
         linux*)       OS_ARCH=Linux OS_TARGET=Linux ;;
+        kfreebsd*-gnu) OS_ARCH=GNU_kFreeBSD OS_TARGET=GNU_kFreeBSD ;;
         solaris*)     OS_ARCH=SunOS OS_RELEASE=5 ;;
         mingw*)       OS_ARCH=WINNT ;;
         wince*)       OS_ARCH=WINCE ;;
         darwin*)      OS_ARCH=Darwin OS_TARGET=Darwin ;;
     esac
 else
     OS_TARGET=`uname -s`
     OS_ARCH=`uname -s | sed -e 's|/|_|g'`
@@ -1473,17 +1476,17 @@ case "$host" in
 *-darwin*)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX -DXP_MACOSX -DNO_X11"
     HOST_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     MOZ_FIX_LINK_PATHS='-Wl,-executable_path,$(LIBXUL_DIST)/bin'
     LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL -lobjc'
     ;;
 
-*-linux*)
+*-linux*|*-kfreebsd*-gnu)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
     HOST_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
     ;;
 
 *os2*)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_OS2 -DNO_X11 -Zomf"
     HOST_NSPR_MDCPUCFG='\"md/_os2.cfg\"'
@@ -2465,17 +2468,17 @@ case "$target" in
         AC_DEFINE(MOZ_OJI_REQUIRE_THREAD_SAFE_ON_STARTUP)
         ;;
 esac
 
 dnl ========================================================
 dnl = Flags to strip unused symbols from .so components
 dnl ========================================================
 case "$target" in
-    *-linux*)
+    *-linux*|*-kfreebsd*-gnu)
         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
         ;;
     *-solaris*)
         if test -z "$GNU_CC"; then
          MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-M $(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
         else
          if test -z "$GCC_USE_GNU_LD"; then
           MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,-M -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
@@ -3139,17 +3142,17 @@ then
 			AC_DEFINE(_REENTRANT)
 			AC_DEFINE(_THREAD_SAFE)
 			dnl -pthread links in -lc_r, so don't specify it explicitly.
 			if test "$ac_cv_have_dash_pthread" = "yes"; then
                 _PTHREAD_LDFLAGS="-pthread"
 			fi
 			;;
 
-	    *-*-linux*) 
+	    *-*-linux*|*-*-kfreebsd*-gnu)
 			AC_DEFINE(_REENTRANT) 
 			;;
 
 	    *-*-nto*) 
 			AC_DEFINE(_REENTRANT) 
 			;;
 
 	    *-aix4.3*|*-aix5*)
@@ -3953,32 +3956,32 @@ MOZ_ARG_WITH_BOOL(system-nss,
 if test -n "$_USE_SYSTEM_NSS"; then
     AM_PATH_NSS(3.12.0, [MOZ_NATIVE_NSS=1], [MOZ_NATIVE_NSS=])
 fi
 
 if test -n "$MOZ_NATIVE_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
    NSS_CFLAGS='-I$(LIBXUL_DIST)/include/nss'
-   NSS_DEP_LIBS='\\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(DLL_PREFIX)smime'$NSS_VERSION'$(DLL_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(DLL_PREFIX)ssl'$NSS_VERSION'$(DLL_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(DLL_PREFIX)nss'$NSS_VERSION'$(DLL_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(DLL_PREFIX)nssutil'$NSS_VERSION'$(DLL_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(DLL_PREFIX)softokn'$NSS_VERSION'$(DLL_SUFFIX)'
+   NSS_DEP_LIBS="\
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)crmf.\$(LIB_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)smime$NSS_VERSION\$(DLL_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)ssl$NSS_VERSION\$(DLL_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)nss$NSS_VERSION\$(DLL_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)nssutil$NSS_VERSION\$(DLL_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(DLL_PREFIX)softokn$NSS_VERSION\$(DLL_SUFFIX)"
 
    if test -z "$GNU_CC" && test "$OS_ARCH" = "WINNT" -o "$OS_ARCH" = "WINCE" -o "$OS_ARCH" = "OS2"; then
-       NSS_LIBS='\\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)smime'$NSS_VERSION'.$(IMPORT_LIB_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)ssl'$NSS_VERSION'.$(IMPORT_LIB_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)nss'$NSS_VERSION'.$(IMPORT_LIB_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)nssutil'$NSS_VERSION'.$(IMPORT_LIB_SUFFIX) \\\
-        $(LIBXUL_DIST)/lib/$(LIB_PREFIX)softokn'$NSS_VERSION'.$(IMPORT_LIB_SUFFIX)'
+       NSS_LIBS="\
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)crmf.\$(LIB_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)smime$NSS_VERSION.\$(IMPORT_LIB_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)ssl$NSS_VERSION.\$(IMPORT_LIB_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)nss$NSS_VERSION.\$(IMPORT_LIB_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)nssutil$NSS_VERSION.\$(IMPORT_LIB_SUFFIX) \
+        \$(LIBXUL_DIST)/lib/\$(LIB_PREFIX)softokn$NSS_VERSION.\$(IMPORT_LIB_SUFFIX)"
    else
        NSS_LIBS='$(LIBS_DIR)'" -lcrmf -lsmime$NSS_VERSION -lssl$NSS_VERSION -lnss$NSS_VERSION -lnssutil$NSS_VERSION -lsoftokn$NSS_VERSION"
    fi
 fi
 
 if test -z "$SKIP_LIBRARY_CHECKS"; then
 dnl system JPEG support
 dnl ========================================================
@@ -4055,16 +4058,45 @@ CFLAGS=$_SAVE_CFLAGS
 LDFLAGS=$_SAVE_LDFLAGS
 LIBS=$_SAVE_LIBS
 
 if test "${ZLIB_DIR}" -a -d "${ZLIB_DIR}" -a "$SYSTEM_ZLIB" = 1; then
     ZLIB_CFLAGS="-I${ZLIB_DIR}/include"
     ZLIB_LIBS="-L${ZLIB_DIR}/lib ${ZLIB_LIBS}"
 fi
 
+dnl system BZIP2 Support
+dnl ========================================================
+MOZ_ARG_WITH_STRING(system-bz2,
+[  --with-system-bz2[=PFX]
+                          Use system libbz2 [installed at prefix PFX]],
+    BZ2_DIR=$withval)
+
+_SAVE_CFLAGS=$CFLAGS
+_SAVE_LDFLAGS=$LDFLAGS
+_SAVE_LIBS=$LIBS
+if test -n "${BZ2_DIR}" -a "${BZ2_DIR}" != "yes"; then
+    CFLAGS="-I${BZ2_DIR}/include $CFLAGS"
+    LDFLAGS="-L${BZ2_DIR}/lib $LDFLAGS"
+fi
+if test -z "$BZ2_DIR" -o "$BZ2_DIR" = no; then
+    SYSTEM_BZ2=
+else
+    AC_CHECK_LIB(bz2, BZ2_bzread, [SYSTEM_BZ2=1 BZ2_LIBS="-lbz2"],
+	[SYSTEM_BZ2= BZ2_CFLAGS= BZ2_LIBS=], $BZ2_LIBS)
+fi
+CFLAGS=$_SAVE_CFLAGS
+LDFLAGS=$_SAVE_LDFLAGS
+LIBS=$_SAVE_LIBS
+
+if test "${BZ2_DIR}" -a -d "${BZ2_DIR}" -a "$SYSTEM_BZ2" = 1; then
+    BZ2_CFLAGS="-I${BZ2_DIR}/include"
+    BZ2_LIBS="-L${BZ2_DIR}/lib ${MOZ_BZ2_LIBS}"
+fi
+
 dnl system PNG Support
 dnl ========================================================
 MOZ_ARG_WITH_STRING(system-png, 
 [  --with-system-png[=PFX]
                           Use system libpng [installed at prefix PFX]],
     PNG_DIR=$withval)
 
 _SAVE_CFLAGS=$CFLAGS
@@ -7667,28 +7699,33 @@ COMPILE_CXXFLAGS=`echo \
     $_DEFINES_CXXFLAGS \
 	$_DEPEND_CFLAGS \
     $COMPILE_CXXFLAGS`
 
 AC_SUBST(SYSTEM_MAKEDEPEND)
 AC_SUBST(SYSTEM_JPEG)
 AC_SUBST(SYSTEM_PNG)
 AC_SUBST(SYSTEM_ZLIB)
+AC_SUBST(SYSTEM_BZ2)
 
 AC_SUBST(JPEG_CFLAGS)
 AC_SUBST(JPEG_LIBS)
 AC_SUBST(ZLIB_CFLAGS)
 AC_SUBST(ZLIB_LIBS)
+AC_SUBST(BZ2_CFLAGS)
+AC_SUBST(BZ2_LIBS)
 AC_SUBST(PNG_CFLAGS)
 AC_SUBST(PNG_LIBS)
 
 AC_SUBST(MOZ_JPEG_CFLAGS)
 AC_SUBST(MOZ_JPEG_LIBS)
 AC_SUBST(MOZ_ZLIB_CFLAGS)
 AC_SUBST(MOZ_ZLIB_LIBS)
+AC_SUBST(MOZ_BZ2_CFLAGS)
+AC_SUBST(MOZ_BZ2_LIBS)
 AC_SUBST(MOZ_PNG_CFLAGS)
 AC_SUBST(MOZ_PNG_LIBS)
 
 AC_SUBST(NSPR_CFLAGS)
 AC_SUBST(NSPR_LIBS)
 AC_SUBST(MOZ_NATIVE_NSPR)
 
 AC_SUBST(NSS_CFLAGS)
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -91,17 +91,17 @@
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMViewCSS.h"
 #include "nsIXBLService.h"
 #include "nsPIDOMWindow.h"
 #include "nsIBoxObject.h"
 #include "nsPIBoxObject.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIDOMNSElement.h"
-#include "nsTextRectangle.h"
+#include "nsClientRect.h"
 #ifdef MOZ_SVG
 #include "nsSVGUtils.h"
 #endif
 #include "nsLayoutUtils.h"
 #include "nsGkAtoms.h"
 #include "nsContentUtils.h"
 #include "nsIJSContextStack.h"
 
@@ -823,81 +823,81 @@ GetContainingBlockForClientRect(nsIFrame
 
 static double
 RoundFloat(double aValue)
 {
   return floor(aValue + 0.5);
 }
 
 static void
-SetTextRectangle(const nsRect& aLayoutRect, nsPresContext* aPresContext,
-                 nsTextRectangle* aRect)
+SetClientRect(const nsRect& aLayoutRect, nsPresContext* aPresContext,
+              nsClientRect* aRect)
 {
   double scale = 65536.0;
   // Round to the nearest 1/scale units. We choose scale so it can be represented
   // exactly by machine floating point.
   double scaleInv = 1/scale;
   double t2pScaled = scale/aPresContext->AppUnitsPerCSSPixel();
   double x = RoundFloat(aLayoutRect.x*t2pScaled)*scaleInv;
   double y = RoundFloat(aLayoutRect.y*t2pScaled)*scaleInv;
   aRect->SetRect(x, y,
                  RoundFloat(aLayoutRect.XMost()*t2pScaled)*scaleInv - x,
                  RoundFloat(aLayoutRect.YMost()*t2pScaled)*scaleInv - y);
 }
 
 NS_IMETHODIMP
-nsNSElementTearoff::GetBoundingClientRect(nsIDOMTextRectangle** aResult)
+nsNSElementTearoff::GetBoundingClientRect(nsIDOMClientRect** aResult)
 {
   // Weak ref, since we addref it below
-  nsTextRectangle* rect = new nsTextRectangle();
+  nsClientRect* rect = new nsClientRect();
   if (!rect)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult = rect);
   
   nsIFrame* frame = mContent->GetPrimaryFrame(Flush_Layout);
   if (!frame) {
     // display:none, perhaps? Return the empty rect
     return NS_OK;
   }
 
   nsPresContext* presContext = frame->PresContext();
   nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
           GetContainingBlockForClientRect(frame));
-  SetTextRectangle(r, presContext, rect);
+  SetClientRect(r, presContext, rect);
   return NS_OK;
 }
 
 struct RectListBuilder : public nsLayoutUtils::RectCallback {
-  nsPresContext*       mPresContext;
-  nsTextRectangleList* mRectList;
-  nsresult             mRV;
-
-  RectListBuilder(nsPresContext* aPresContext, nsTextRectangleList* aList) 
+  nsPresContext*    mPresContext;
+  nsClientRectList* mRectList;
+  nsresult          mRV;
+
+  RectListBuilder(nsPresContext* aPresContext, nsClientRectList* aList) 
     : mPresContext(aPresContext), mRectList(aList),
       mRV(NS_OK) {}
 
   virtual void AddRect(const nsRect& aRect) {
-    nsRefPtr<nsTextRectangle> rect = new nsTextRectangle();
+    nsRefPtr<nsClientRect> rect = new nsClientRect();
     if (!rect) {
       mRV = NS_ERROR_OUT_OF_MEMORY;
       return;
     }
     
-    SetTextRectangle(aRect, mPresContext, rect);
+    SetClientRect(aRect, mPresContext, rect);
     mRectList->Append(rect);
   }
 };
 
 NS_IMETHODIMP
-nsNSElementTearoff::GetClientRects(nsIDOMTextRectangleList** aResult)
+nsNSElementTearoff::GetClientRects(nsIDOMClientRectList** aResult)
 {
   *aResult = nsnull;
 
-  nsRefPtr<nsTextRectangleList> rectList = new nsTextRectangleList();
+  nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
   if (!rectList)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsIFrame* frame = mContent->GetPrimaryFrame(Flush_Layout);
   if (!frame) {
     // display:none, perhaps? Return an empty list
     *aResult = rectList.forget().get();
     return NS_OK;
@@ -2228,16 +2228,25 @@ nsGenericElement::UnbindFromTree(PRBool 
 }
 
 nsresult
 nsGenericElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   return nsGenericElement::doPreHandleEvent(this, aVisitor);
 }
 
+static nsIContent*
+FindFirstNonNativeAnonymousAncestor(nsIContent* aContent)
+{
+  while (aContent && aContent->IsNativeAnonymous()) {
+    aContent = aContent->GetParent();
+  }
+  return aContent;
+}
+
 nsresult
 nsGenericElement::doPreHandleEvent(nsIContent* aContent,
                                    nsEventChainPreVisitor& aVisitor)
 {
   //FIXME! Document how this event retargeting works, Bug 329124.
   aVisitor.mCanHandle = PR_TRUE;
 
   // Don't propagate mouseover and mouseout events when mouse is moving
@@ -2255,20 +2264,20 @@ nsGenericElement::doPreHandleEvent(nsICo
       // target is descendant of an element which is anonymous for events,
       // we may want to stop event propagation.
       // If aContent is the original target, aVisitor.mRelatedTargetIsInAnon
       // must be updated.
       if (isAnonForEvents || aVisitor.mRelatedTargetIsInAnon ||
           (aVisitor.mEvent->originalTarget == aContent &&
            (aVisitor.mRelatedTargetIsInAnon =
             relatedTarget->IsInNativeAnonymousSubtree()))) {
-        nsIContent* nonAnon = aContent->FindFirstNonNativeAnonymous();
+        nsIContent* nonAnon = FindFirstNonNativeAnonymousAncestor(aContent);
         if (nonAnon) {
           nsIContent* nonAnonRelated =
-            relatedTarget->FindFirstNonNativeAnonymous();
+            FindFirstNonNativeAnonymousAncestor(relatedTarget);
           if (nonAnonRelated) {
             if (nonAnon == nonAnonRelated ||
                 nsContentUtils::ContentIsDescendantOf(nonAnonRelated, nonAnon)) {
               aVisitor.mParentTarget = nsnull;
               // Event should not propagate to non-anon content.
               aVisitor.mCanHandle = isAnonForEvents;
               return NS_OK;
             }
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -76,16 +76,17 @@ REQUIRES	= xpcom \
 		  plugin \
 		  $(NULL)
 
 EXPORTS		= \
 		nsImageMapUtils.h \
 		$(NULL)
 
 CPPSRCS		= \
+		nsClientRect.cpp \
 		nsGenericHTMLElement.cpp \
 		nsFormSubmission.cpp \
 		nsImageMapUtils.cpp \
 		nsHTMLAnchorElement.cpp \
 		nsHTMLAreaElement.cpp \
 		nsHTMLBRElement.cpp \
 		nsHTMLBodyElement.cpp \
 		nsHTMLButtonElement.cpp \
@@ -125,17 +126,16 @@ CPPSRCS		= \
 		nsHTMLTableElement.cpp \
 		nsHTMLTableCaptionElement.cpp \
 		nsHTMLTableCellElement.cpp \
 		nsHTMLTableColElement.cpp \
 		nsHTMLTableRowElement.cpp \
 		nsHTMLTableSectionElement.cpp \
 		nsHTMLTextAreaElement.cpp \
 		nsHTMLTitleElement.cpp \
-                nsTextRectangle.cpp \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 INCLUDES	+= \
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsClientRect.cpp
@@ -0,0 +1,112 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is
+ * Novell Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsClientRect.h"
+#include "nsContentUtils.h"
+#include "nsDOMClassInfoID.h"
+
+NS_INTERFACE_TABLE_HEAD(nsClientRect)
+  NS_INTERFACE_TABLE1(nsClientRect, nsIDOMClientRect)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ClientRect)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(nsClientRect)
+NS_IMPL_RELEASE(nsClientRect)
+
+nsClientRect::nsClientRect()
+  : mX(0.0), mY(0.0), mWidth(0.0), mHeight(0.0)
+{
+}
+
+NS_IMETHODIMP
+nsClientRect::GetLeft(float* aResult)
+{
+  *aResult = mX;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClientRect::GetTop(float* aResult)
+{
+  *aResult = mY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClientRect::GetRight(float* aResult)
+{
+  *aResult = mX + mWidth;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsClientRect::GetBottom(float* aResult)
+{
+  *aResult = mY + mHeight;
+  return NS_OK;
+}
+
+NS_INTERFACE_TABLE_HEAD(nsClientRectList)
+  NS_INTERFACE_TABLE1(nsClientRectList, nsIDOMClientRectList)
+  NS_INTERFACE_TABLE_TO_MAP_SEGUE
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ClientRectList)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(nsClientRectList)
+NS_IMPL_RELEASE(nsClientRectList)
+
+
+NS_IMETHODIMP    
+nsClientRectList::GetLength(PRUint32* aLength)
+{
+  *aLength = mArray.Count();
+  return NS_OK;
+}
+
+NS_IMETHODIMP    
+nsClientRectList::Item(PRUint32 aIndex, nsIDOMClientRect** aReturn)
+{
+  if (aIndex >= PRUint32(mArray.Count())) {
+    *aReturn = nsnull;
+    return NS_OK;
+  } 
+  
+  NS_IF_ADDREF(*aReturn = mArray.ObjectAt(aIndex));
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsClientRect.h
@@ -0,0 +1,80 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is
+ * Novell Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef NSCLIENTRECT_H_
+#define NSCLIENTRECT_H_
+
+#include "nsIDOMClientRect.h"
+#include "nsIDOMClientRectList.h"
+#include "nsCOMArray.h"
+
+class nsClientRect : public nsIDOMClientRect
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  nsClientRect();
+  void SetRect(float aX, float aY, float aWidth, float aHeight) {
+    mX = aX; mY = aY; mWidth = aWidth; mHeight = aHeight;
+  }
+  virtual ~nsClientRect() {}
+  
+  NS_DECL_NSIDOMCLIENTRECT
+
+protected:
+  float mX, mY, mWidth, mHeight;
+};
+
+class nsClientRectList : public nsIDOMClientRectList
+{
+public:
+  nsClientRectList() {}
+
+  NS_DECL_ISUPPORTS
+
+  NS_DECL_NSIDOMCLIENTRECTLIST
+  
+  void Append(nsIDOMClientRect* aElement) { mArray.AppendObject(aElement); }
+
+protected:
+  virtual ~nsClientRectList() {}
+
+  nsCOMArray<nsIDOMClientRect> mArray;
+};
+
+#endif /*NSCLIENTRECT_H_*/
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -291,23 +291,16 @@ nsXMLDocument::OnChannelRedirect(nsIChan
 
   rv = nsContentUtils::GetSecurityManager()->
     CheckSameOriginURI(oldURI, newURI, PR_TRUE);
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  // XXXbz Shouldn't we look at the owner on the new channel at some point?
-  // It's not gonna be right here, but eventually it will....
-  nsCOMPtr<nsIPrincipal> principal;
-  rv = secMan->GetCodebasePrincipal(newLocation, getter_AddRefs(principal));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  SetPrincipal(principal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLDocument::EvaluateFIXptr(const nsAString& aExpression, nsIDOMRange **aRange)
 {
   nsresult rv;
   nsCOMPtr<nsIFIXptrEvaluator> e =
@@ -363,18 +356,19 @@ nsXMLDocument::Load(const nsAString& aUr
 
   // Create a new URI
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
   nsCOMPtr<nsIURI> codebase;
-  NodePrincipal()->GetURI(getter_AddRefs(codebase));
+  principal->GetURI(getter_AddRefs(codebase));
 
   // Get security manager, check to see whether the current document
   // is allowed to load this URI. It's important to use the current
   // document's principal for this check so that we don't end up in a
   // case where code with elevated privileges is calling us and
   // changing the principal of this document.
   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
 
@@ -408,17 +402,16 @@ nsXMLDocument::Load(const nsAString& aUr
 
   // Partial Reset, need to restore principal for security reasons and
   // event listener manager so that load listeners etc. will
   // remain. This should be done before the security check is done to
   // ensure that the document is reset even if the new document can't
   // be loaded.  Note that we need to hold a strong ref to |principal|
   // here, because ResetToURI will null out our node principal before
   // setting the new one.
-  nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
   nsCOMPtr<nsIEventListenerManager> elm(mListenerManager);
   mListenerManager = nsnull;
 
   // When we are called from JS we can find the load group for the page,
   // and add ourselves to it. This way any pending requests
   // will be automatically aborted if the user leaves the page.
 
   nsCOMPtr<nsILoadGroup> loadGroup;
@@ -436,33 +429,16 @@ nsXMLDocument::Load(const nsAString& aUr
   // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active,
   // which in turn keeps STOP button from becoming active  
   rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, loadGroup, this, 
                      nsIRequest::LOAD_BACKGROUND);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  // Set a principal for this document
-  // XXXbz StartDocumentLoad should handle that.... And we shouldn't be calling
-  // StartDocumentLoad until we get an OnStartRequest from this channel!
-  nsCOMPtr<nsISupports> channelOwner;
-  rv = channel->GetOwner(getter_AddRefs(channelOwner));
-
-  // We don't care if GetOwner() succeeded here, if it failed,
-  // channelOwner will be null, which is what we want in that case.
-  principal = do_QueryInterface(channelOwner);
-
-  if (NS_FAILED(rv) || !principal) {
-    rv = secMan->GetCodebasePrincipal(uri, getter_AddRefs(principal));
-    NS_ENSURE_TRUE(principal, rv);
-  }
-
-  SetPrincipal(principal);
-
   // Prepare for loading the XML document "into oneself"
   nsCOMPtr<nsIStreamListener> listener;
   if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, 
                                        loadGroup, nsnull, 
                                        getter_AddRefs(listener),
                                        PR_FALSE))) {
     NS_ERROR("nsXMLDocument::Load: Failed to start the document load.");
     return rv;
--- a/content/xul/document/test/test_bug199692.xul
+++ b/content/xul/document/test/test_bug199692.xul
@@ -59,17 +59,19 @@ xmlns="http://www.mozilla.org/keymaster/
   }
   function scrollbar_button(e) { // a bit down from upper right
     return { "x": e.boxObject.x + e.boxObject.width - d,
              "y": e.boxObject.y + d + 15 };
   }
   
   function test(ptFunc, id, message) {
     var pt = ptFunc($(id));
-    is(document.elementFromPoint(pt.x, pt.y).id, id, message);
+    var e = document.elementFromPoint(pt.x, pt.y);
+    ok(e != null, message + " (returned null)");
+    is(e.id, id, message);
   }
   
   function do_test() {
     // Avoid hardcoding x,y pixel values, to better deal with differing default
     // font sizes or other layout defaults.
     
     test(middle, 'textbox', "Point within textbox should return textbox element");
     test(lower_right, 'textbox', "Point on textbox's scrollbar should return textbox element");
--- a/dom/public/idl/base/Makefile.in
+++ b/dom/public/idl/base/Makefile.in
@@ -72,13 +72,13 @@ XPIDLSRCS =					\
 	nsIDOMPlugin.idl			\
 	nsIDOMPluginArray.idl			\
 	nsIDOMScreen.idl			\
 	nsIDOMWindowInternal.idl		\
 	nsIDOMJSWindow.idl			\
 	nsIDOMModalContentWindow.idl		\
 	nsIDOMChromeWindow.idl			\
 	nsIDOMNSFeatureFactory.idl		\
-        nsIDOMTextRectangle.idl			\
-        nsIDOMTextRectangleList.idl		\
+        nsIDOMClientRect.idl			\
+        nsIDOMClientRectList.idl		\
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/public/idl/base/domstubs.idl
+++ b/dom/public/idl/base/domstubs.idl
@@ -58,18 +58,18 @@ interface nsIDOMNSElement;
 interface nsIDOMNamedNodeMap;
 interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMNotation;
 interface nsIDOMProcessingInstruction;
 interface nsIDOMText;
 interface nsIDOMDOMStringList;
 interface nsIDOMNameList;
-interface nsIDOMTextRectangle;
-interface nsIDOMTextRectangleList;
+interface nsIDOMClientRect;
+interface nsIDOMClientRectList;
 
 // Needed for raises() in our IDL
 interface DOMException;
 interface RangeException;
 
 // Style Sheets
 interface nsIDOMStyleSheetList;
 interface nsIDOMLinkStyle;
new file mode 100644
--- /dev/null
+++ b/dom/public/idl/base/nsIDOMClientRect.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is
+ * Novell Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+[scriptable, uuid(f8583bbc-c6de-4646-b39f-df7e766442e9)]
+interface nsIDOMClientRect : nsISupports
+{
+  readonly attribute float left;
+  readonly attribute float top;
+  readonly attribute float right;
+  readonly attribute float bottom;
+};
new file mode 100644
--- /dev/null
+++ b/dom/public/idl/base/nsIDOMClientRectList.idl
@@ -0,0 +1,46 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Novell code.
+ *
+ * The Initial Developer of the Original Code is
+ * Novell Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+[scriptable, uuid(917da19d-62f5-441d-b47e-9e35f05639c9)]
+interface nsIDOMClientRectList : nsISupports
+{
+  readonly attribute unsigned long length;
+  nsIDOMClientRect              item(in unsigned long index);
+};
--- a/dom/public/idl/core/nsIDOMNSElement.idl
+++ b/dom/public/idl/core/nsIDOMNSElement.idl
@@ -63,17 +63,17 @@ interface nsIDOMNSElement : nsISupports
    *
    * Note: the boxes of overflowing children do not affect these rectangles.
    * Note: some elements have empty CSS boxes. Those return empty rectangles,
    * but the coordinates may still be meaningful.
    * Note: some elements have no CSS boxes (including display:none elements,
    * HTML AREA elements, and SVG elements that do not render). Those return
    * an empty list.
    */
-  nsIDOMTextRectangleList getClientRects();
+  nsIDOMClientRectList getClientRects();
   /**
    * Returns the union of all rectangles in the getClientRects() list. Empty
    * rectangles are ignored, except that if all rectangles are empty,
    * we return an empty rectangle positioned at the top-left of the first
    * rectangle in getClientRects().
    */
-  nsIDOMTextRectangle     getBoundingClientRect();
+  nsIDOMClientRect getBoundingClientRect();
 };
--- a/dom/public/nsDOMClassInfoID.h
+++ b/dom/public/nsDOMClassInfoID.h
@@ -385,18 +385,18 @@ enum nsDOMClassInfoID {
   // DOMParser, XMLSerializer
   eDOMClassInfo_DOMParser_id,
   eDOMClassInfo_XMLSerializer_id,
 
   // XMLHttpRequest
   eDOMClassInfo_XMLHttpProgressEvent_id,
   eDOMClassInfo_XMLHttpRequest_id,
 
-  eDOMClassInfo_TextRectangle_id,
-  eDOMClassInfo_TextRectangleList_id,
+  eDOMClassInfo_ClientRect_id,
+  eDOMClassInfo_ClientRectList_id,
 
   // We are now trying to preserve binary compat in classinfo.  No more
   // putting things in those categories up there.  New entries are to be
   // added here, which is the end of the things that are currently on by
   // default.
 
 #if defined(MOZ_SVG) && defined(MOZ_SVG_FOREIGNOBJECT)
   eDOMClassInfo_SVGForeignObjectElement_id,
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -108,18 +108,18 @@
 #include "nsPIDOMWindow.h"
 #include "nsIDOMJSWindow.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIDOMHistory.h"
 #include "nsIDOMNSHistory.h"
 #include "nsIDOMMediaList.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMConstructor.h"
-#include "nsIDOMTextRectangle.h"
-#include "nsIDOMTextRectangleList.h"
+#include "nsIDOMClientRect.h"
+#include "nsIDOMClientRectList.h"
 
 // DOM core includes
 #include "nsDOMError.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDOMNode.h"
 #include "nsIDOM3Node.h"
 #include "nsIDOM3Attr.h"
 #include "nsIDOMNodeList.h"
@@ -1180,19 +1180,19 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(XMLSerializer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(XMLHttpProgressEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(XMLHttpRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(TextRectangle, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(TextRectangleList, nsTextRectangleListSH,
+  NS_DEFINE_CLASSINFO_DATA(ClientRect, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(ClientRectList, nsClientRectListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   // Define MOZ_SVG_FOREIGNOBJECT here so that when it gets switched on,
   // we preserve binary compatibility. New classes should be added
   // at the end.
 #if defined(MOZ_SVG) && defined(MOZ_SVG_FOREIGNOBJECT)
   NS_DEFINE_CLASSINFO_DATA(SVGForeignObjectElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
@@ -3322,22 +3322,22 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLoadStatus)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(LoadStatusEvent, nsIDOMLoadStatusEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLoadStatusEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(TextRectangle, nsIDOMTextRectangle)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTextRectangle)
+  DOM_CLASSINFO_MAP_BEGIN(ClientRect, nsIDOMClientRect)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientRect)
    DOM_CLASSINFO_MAP_END
  
-  DOM_CLASSINFO_MAP_BEGIN(TextRectangleList, nsIDOMTextRectangleList)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTextRectangleList)
+  DOM_CLASSINFO_MAP_BEGIN(ClientRectList, nsIDOMClientRectList)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientRectList)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(FileList, nsIDOMFileList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileList)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
@@ -9748,26 +9748,26 @@ nsCSSRuleListSH::GetItemAt(nsISupports *
   nsIDOMCSSRule *rule = nsnull; // Weak, transfer the ownership over to aResult
   nsresult rv = list->Item(aIndex, &rule);
 
   *aResult = rule;
 
   return rv;
 }
 
-// TextRectangleList scriptable helper
+// ClientRectList scriptable helper
 
 nsresult
-nsTextRectangleListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                                 nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMTextRectangleList> list(do_QueryInterface(aNative));
+nsClientRectListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                              nsISupports **aResult)
+{
+  nsCOMPtr<nsIDOMClientRectList> list(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
 
-  nsIDOMTextRectangle *rule = nsnull; // Weak, transfer the ownership over to aResult
+  nsIDOMClientRect *rule = nsnull; // Weak, transfer the ownership over to aResult
   nsresult rv = list->Item(aIndex, &rule);
 
   *aResult = rule;
 
   return rv;
 }
 
 #ifdef MOZ_XUL
--- a/dom/src/base/nsDOMClassInfo.h
+++ b/dom/src/base/nsDOMClassInfo.h
@@ -1326,38 +1326,38 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsCSSRuleListSH(aData);
   }
 };
 
-// TextRectangleList helper
+// ClientRectList helper
 
-class nsTextRectangleListSH : public nsArraySH
+class nsClientRectListSH : public nsArraySH
 {
 protected:
-  nsTextRectangleListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
+  nsClientRectListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
 
-  virtual ~nsTextRectangleListSH()
+  virtual ~nsClientRectListSH()
   {
   }
 
   // Override nsArraySH::GetItemAt() since our list isn't a
   // nsIDOMNodeList
   virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                              nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
-    return new nsTextRectangleListSH(aData);
+    return new nsClientRectListSH(aData);
   }
 };
 
 
 #ifdef MOZ_XUL
 // TreeColumns helper
 
 class nsTreeColumnsSH : public nsNamedArraySH
--- a/extensions/cookie/Makefile.in
+++ b/extensions/cookie/Makefile.in
@@ -51,20 +51,23 @@ GRE_MODULE	= 1
 LIBXUL_LIBRARY = 1
 
 PACKAGE_FILE = cookie.pkg
 
 REQUIRES	= xpcom \
 		  string \
 		  necko \
 		  dom \
+		  content \
+		  widget \
 		  pref \
 		  windowwatcher \
 		  docshell \
 		  appshell \
+		  caps \
 		  storage \
 		  $(NULL)
 
 CPPSRCS		= \
 		nsCookieModule.cpp \
 		nsPermission.cpp \
 		nsPermissionManager.cpp \
 		nsPopupWindowManager.cpp \
@@ -80,9 +83,13 @@ XPIDLSRCS	= \
 EXTRA_DSO_LDOPTS = \
 		$(MOZ_COMPONENT_LIBS) \
 		$(NULL)
 
 ifdef MOZ_MAIL_NEWS
 DEFINES += -DMOZ_MAIL_NEWS
 endif
 
+ifdef ENABLE_TESTS
+TOOL_DIRS		+= test
+endif
+
 include $(topsrcdir)/config/rules.mk
--- a/extensions/cookie/makefiles.sh
+++ b/extensions/cookie/makefiles.sh
@@ -33,9 +33,10 @@
 # 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 *****
 
 add_makefiles "
   extensions/cookie/Makefile
+  extensions/cookie/test/Makefile
 "
--- a/extensions/cookie/nsCookiePermission.cpp
+++ b/extensions/cookie/nsCookiePermission.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * Michiel van Leeuwen (mvl@exedo.nl).
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Darin Fisher <darin@meer.net>
+ *   Daniel Witte <dwitte@stanford.edu>
  *
  * 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
@@ -44,21 +45,22 @@
 #include "nsICookieManager2.h"
 #include "nsNetUtil.h"
 #include "nsIURI.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
-#include "nsIInterfaceRequestor.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsILoadGroup.h"
+#include "nsIWebNavigation.h"
+#include "nsINode.h"
 #include "nsIChannel.h"
 #include "nsIDOMWindow.h"
+#include "nsIDOMDocument.h"
+#include "nsIPrincipal.h"
 #include "nsString.h"
 #include "nsCRT.h"
 
 /****************************************************************
  ************************ nsCookiePermission ********************
  ****************************************************************/
 
 // values for mCookiesLifetimePolicy
@@ -194,17 +196,16 @@ nsCookiePermission::SetAccess(nsIURI    
   //       the permission codes used by nsIPermissionManager.
   //       this is nice because it avoids conversion code.
   //
   return mPermMgr->Add(aURI, kPermissionType, aAccess);
 }
 
 NS_IMETHODIMP
 nsCookiePermission::CanAccess(nsIURI         *aURI,
-                              nsIURI         *aFirstURI,
                               nsIChannel     *aChannel,
                               nsCookieAccess *aResult)
 {
 #ifdef MOZ_MAIL_NEWS
   // disable cookies in mailnews if user's prefs say so
   if (mCookiesDisabledForMailNews) {
     //
     // try to examine the "app type" of the docshell owning this request.  if
@@ -230,17 +231,16 @@ nsCookiePermission::CanAccess(nsIURI    
             if (docshell)
               docshell->GetAppType(&appType);
         } while (appType != nsIDocShell::APP_TYPE_MAIL &&
                  NS_SUCCEEDED(item->GetParent(getter_AddRefs(parent))) &&
                  parent);
       }
     }
     if ((appType == nsIDocShell::APP_TYPE_MAIL) ||
-        (aFirstURI && IsFromMailNews(aFirstURI)) ||
         IsFromMailNews(aURI)) {
       *aResult = ACCESS_DENY;
       return NS_OK;
     }
   }
 #endif // MOZ_MAIL_NEWS
   
   // finally, check with permission manager...
@@ -416,16 +416,104 @@ nsCookiePermission::CanSetCookie(nsIURI 
         }
       }
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP 
+nsCookiePermission::GetOriginatingURI(nsIChannel  *aChannel,
+                                      nsIURI     **aURI)
+{
+  /* to find the originating URI, we use the loadgroup of the channel to obtain
+   * the docshell owning the load, and from there, we find the root content
+   * docshell and its URI. there are several possible cases:
+   *
+   * 1) no channel. this will occur for plugins using the nsICookieStorage
+   *    interface, since they have none to provide. other consumers should
+   *    have a channel.
+   *
+   * 2) a channel, but no docshell. this can occur when the consumer kicking
+   *    off the load doesn't provide one to the channel, and should be limited
+   *    to loads of certain types of resources (e.g. favicons).
+   *
+   * 3) a non-content docshell. this occurs for loads kicked off from chrome,
+   *    where no content docshell exists (favicons can also fall into this
+   *    category).
+   *
+   * 4) a content docshell equal to the root content docshell, with channel
+   *    loadflags LOAD_DOCUMENT_URI. this covers the case of a freshly kicked-
+   *    off load (e.g. the user typing something in the location bar, or
+   *    clicking on a bookmark), where the currentURI hasn't yet been set,
+   *    and will be bogus. we return the channel URI in this case. note that
+   *    we could also allow non-content docshells here, but that goes against
+   *    the philosophy of having an audit trail back to a URI the user typed
+   *    or clicked on.
+   *
+   * 5) a root content docshell. this covers most cases for an ordinary page
+   *    load from the location bar, and will catch nested frames within
+   *    a page, image loads, etc. we return the URI of the docshell's principal
+   *    in this case.
+   *
+   */
+
+  *aURI = nsnull;
+
+  // case 1)
+  if (!aChannel)
+    return NS_ERROR_NULL_POINTER;
+
+  // find the docshell and its root
+  nsCOMPtr<nsIDocShellTreeItem> docshell, root;
+  NS_QueryNotificationCallbacks(aChannel, docshell);
+  if (docshell)
+    docshell->GetSameTypeRootTreeItem(getter_AddRefs(root));
+
+  PRInt32 type;
+  if (root)
+    root->GetItemType(&type);
+
+  // cases 2) and 3)
+  if (!root || type != nsIDocShellTreeItem::typeContent)
+    return NS_ERROR_INVALID_ARG;
+
+  // case 4)
+  if (docshell == root) {
+    nsLoadFlags flags;
+    aChannel->GetLoadFlags(&flags);
+
+    if (flags & nsIChannel::LOAD_DOCUMENT_URI) {
+      // get the channel URI - the docshell's will be bogus
+      aChannel->GetURI(aURI);
+      if (!*aURI)
+        return NS_ERROR_NULL_POINTER;
+
+      return NS_OK;
+    }
+  }
+
+  // case 5) - get the originating URI from the docshell's principal
+  nsCOMPtr<nsIWebNavigation> webnav = do_QueryInterface(root);
+  if (webnav) {
+    nsCOMPtr<nsIDOMDocument> doc;
+    webnav->GetDocument(getter_AddRefs(doc));
+    nsCOMPtr<nsINode> node = do_QueryInterface(doc);
+    if (node)
+      node->NodePrincipal()->GetURI(aURI);
+  }
+
+  if (!*aURI)
+    return NS_ERROR_NULL_POINTER;
+
+  // all done!
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsCookiePermission::Observe(nsISupports     *aSubject,
                             const char      *aTopic,
                             const PRUnichar *aData)
 {
   nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(aSubject);
   NS_ASSERTION(!nsCRT::strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic),
                "unexpected topic - we only deal with pref changes!");
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/Makefile.in
@@ -0,0 +1,93 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = extensions/cookie/test
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE          = test_cookies
+
+_TEST_FILES = \
+  test_samedomain.html \
+  file_testcommon.js \
+  file_domain_inner.html \
+  file_domain_inner_inner.html \
+  test_differentdomain.html \
+  test_image.html \
+  file_image_inner.html \
+  file_image_inner_inner.html \
+  image1.png \
+  image1.png^headers^ \
+  image2.png \
+  image2.png^headers^ \
+  test1.css \
+  test1.css^headers^ \
+  test2.css \
+  test2.css^headers^ \
+  test_loadflags.html \
+  file_testloadflags.js \
+  file_loadflags_inner.html \
+  test_same_base_domain.html \
+  file_subdomain_inner.html \
+  test_same_base_domain_2.html \
+  test_same_base_domain_3.html \
+  test_same_base_domain_4.html \
+  file_localhost_inner.html \
+  test_same_base_domain_5.html \
+  test_same_base_domain_6.html \
+  file_loopback_inner.html \
+#  test_same_base_domain_7.html \
+	$(NULL)
+
+_BROWSER_TEST_FILES = \
+  browser_test_favicon.js \
+  $(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+libs:: $(_BROWSER_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
+
+XPCSHELL_TESTS = unit
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/browser_test_favicon.js
@@ -0,0 +1,44 @@
+// tests third party cookie blocking using a favicon load directly from chrome.
+// in this case, the docshell of the channel is chrome, not content; thus
+// the cookie should be considered third party.
+
+function test() {
+  waitForExplicitFinish();
+
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                        .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+
+  var o = new obs();
+
+  // kick off a favicon load
+  PageProxySetIcon("http://example.org/tests/extensions/cookie/test/image1.png");
+}
+
+function obs () {
+  this.os = Components.classes["@mozilla.org/observer-service;1"]
+                      .getService(Components.interfaces.nsIObserverService);
+  this.os.addObserver(this, "cookie-rejected", false);
+}
+
+obs.prototype = {
+  observe: function obs_observe (theSubject, theTopic, theData)
+  {
+    var uri = theSubject.QueryInterface(Components.interfaces.nsIURI);
+    var domain = uri.host;
+
+    if (domain == "example.org") {
+      ok(true, "foreign favicon cookie was blocked");
+
+      var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                            .getService(Components.interfaces.nsIPrefBranch);
+      prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
+      this.os.removeObserver(this, "cookie-rejected");
+      this.os = null;
+
+      finish();
+    }
+  }
+}
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_domain_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://example.org/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_domain_inner_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta2=tag2">
+  <script type="text/javascript">
+    document.cookie = "can2=has2";
+
+    // send a message to our test document, to say we're done loading
+    window.parent.opener.postMessage("message");
+  </script>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_image_inner.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+</head>
+<body>
+<iframe name="frame1" src="http://example.org/tests/extensions/cookie/test/file_image_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_image_inner_inner.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <link rel="stylesheet" type="text/css" media="all" href="http://example.org/tests/extensions/cookie/test/test1.css" />
+  <link rel="stylesheet" type="text/css" media="all" href="http://example.com/tests/extensions/cookie/test/test2.css" />
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta2=tag2">
+  <script type="text/javascript">
+    function runTest() {
+      document.cookie = "can2=has2";
+
+      // send a message to our test document, to say we're done loading
+      window.parent.opener.postMessage("message");
+    }
+  </script>
+</head>
+<body>
+<img src="http://example.org/tests/extensions/cookie/test/image1.png" onload="runTest()" />
+<img src="http://example.com/tests/extensions/cookie/test/image2.png" onload="runTest()" />
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_loadflags_inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    function runTest() {
+      document.cookie = "can=has";
+
+      // send a message to our test document, to say we're done loading
+      window.opener.postMessage("message");
+    }
+  </script>
+</head>
+<body>
+<img src="http://example.org/tests/extensions/cookie/test/image1.png" onload="runTest()" />
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_localhost_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://localhost:8888/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_loopback_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://127.0.0.1:8888/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_subdomain_inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <META HTTP-EQUIV="Set-Cookie" CONTENT="meta=tag">
+  <script type="text/javascript">
+    document.cookie = "can=has";
+
+    // send a message to our test document, to say we're done loading
+    window.opener.postMessage("message");
+  </script>
+<body>
+<iframe name="frame1" src="http://test2.example.org/tests/extensions/cookie/test/file_domain_inner_inner.html"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_testcommon.js
@@ -0,0 +1,67 @@
+SimpleTest.waitForExplicitFinish();
+
+var gPopup = null;
+
+var gExpectedCookies = 0;
+var gExpectedLoads = 0;
+var gLoads = 0;
+
+function setupTest(uri, cookies, loads) {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                        .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                      .getService(Components.interfaces.nsICookieManager2);
+  cs.removeAll();
+
+  gExpectedCookies = cookies;
+  gExpectedLoads = loads;
+
+  // load a window which contains an iframe; each will attempt to set
+  // cookies from their respective domains.
+  gPopup = window.open(uri, 'hai', 'width=100,height=100');
+}
+
+/** Receives MessageEvents to this window. */
+function messageReceiver(evt)
+{
+  ok(evt instanceof MessageEvent, "wrong event type");
+
+  if (evt.data == "message")
+    gLoads++;
+  else {
+    ok(false, "wrong message");
+    gPopup.close();
+    SimpleTest.finish();
+  }
+
+  // only run the test when all our children are done loading & setting cookies
+  if (gLoads == gExpectedLoads)
+    runTest();
+}
+
+function runTest() {
+  // set a cookie from a domain of "localhost"
+  document.cookie = "oh=hai";
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService(Components.interfaces.nsICookieManager);
+  var list = cs.enumerator;
+  var count = 0;
+  while (list.hasMoreElements()) {
+    count++;
+    list.getNext();
+  }
+  is(count, gExpectedCookies, "incorrect number of cookies");
+
+  gPopup.close();
+  cs.removeAll();
+  SimpleTest.finish();
+}
+
+document.addEventListener("message", messageReceiver, false);
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/file_testloadflags.js
@@ -0,0 +1,111 @@
+SimpleTest.waitForExplicitFinish();
+
+var gPopup = null;
+
+var gExpectedCookies = 0;
+var gExpectedLoads = 0;
+var gExpectedHeaders = 0;
+var gLoads = 0;
+var gHeaders = 0;
+
+var o = null;
+
+function setupTest(uri, domain, cookies, loads, headers) {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+
+  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
+                        .getService(Components.interfaces.nsIPrefBranch);
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                      .getService(Components.interfaces.nsICookieManager2);
+  cs.removeAll();
+  cs.add(domain, "", "oh", "hai", false, false, true, Math.pow(2, 62));
+  is(cs.countCookiesFromHost(domain), 1, "cookie wasn't inited");
+
+  o = new obs();
+
+  gExpectedCookies = cookies;
+  gExpectedLoads = loads;
+  gExpectedHeaders = headers;
+
+  // load a window which contains an iframe; each will attempt to set
+  // cookies from their respective domains.
+  gPopup = window.open(uri, 'hai', 'width=100,height=100');
+}
+
+function obs () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  this.os = Components.classes["@mozilla.org/observer-service;1"]
+                      .getService(Components.interfaces.nsIObserverService);
+  this.os.addObserver(this, "http-on-modify-request", false);
+  this.window = window;
+}
+
+obs.prototype = {
+  observe: function obs_observe (theSubject, theTopic, theData)
+  {
+    this.window.netscape.security
+        .PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var httpchannel = theSubject.QueryInterface(this.window.Components.interfaces
+                                                    .nsIHttpChannel);
+
+    var cookie = httpchannel.getRequestHeader("Cookie");
+
+    var got = cookie.indexOf("oh=hai");
+    this.window.isnot(got, -1, "cookie wasn't sent");
+    gHeaders++;
+  },
+
+  remove: function obs_remove()
+  {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    this.os.removeObserver(this, "http-on-modify-request");
+    this.os = null;
+    this.window = null;
+  }
+}
+
+/** Receives MessageEvents to this window. */
+function messageReceiver(evt)
+{
+  ok(evt instanceof MessageEvent, "wrong event type");
+
+  if (evt.data == "message")
+    gLoads++;
+  else {
+    ok(false, "wrong message");
+    o.remove();
+    gPopup.close();
+    SimpleTest.finish();
+  }
+
+  // only run the test when all our children are done loading & setting cookies
+  if (gLoads == gExpectedLoads)
+    runTest();
+}
+
+function runTest() {
+  // set a cookie from a domain of "localhost"
+  document.cookie = "o=noes";
+
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  var cs = Components.classes["@mozilla.org/cookiemanager;1"]
+                     .getService(Components.interfaces.nsICookieManager);
+  var list = cs.enumerator;
+  var count = 0;
+  while (list.hasMoreElements()) {
+    count++;
+    list.getNext();
+  }
+  is(count, gExpectedCookies, "incorrect number of cookies");
+  is(gHeaders, gExpectedHeaders, "incorrect number of request headers");
+
+  o.remove();
+  gPopup.close();
+  cs.removeAll();
+  SimpleTest.finish();
+}
+
+document.addEventListener("message", messageReceiver, false);
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4b7c102840cab57d589b4380cb1d0675498fcda9
GIT binary patch
literal 1242
zc$@*+1SR{4P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960004lX+uL$Nkc;*P;zf(X>4Tx0C=30k<TjxVHn3h??_7Q#rTm@a}ax2+PJKe
zvU@-r)~4+4ZFXj?tugyH^IH4??#fLLew35sB**;&+>{)ols`Zz7ik<`+6&3Ip87oB
zo_c<P(X^%X4PYZsVPP(76-#BS;~s-<0I;1%&gSz={HnJ*1i<Z>Ev5f^-H+-Di={FM
z6ELfqlYm*#JPnvzN-7X}z;xDa7laF>!j(b}#2%2SYCZxI70s7GqTy5(h$fH@+*$zQ
z1<1Hw<baU`lp{k0#vw3VER`)inp%XJA!xg4dF2Ss&!B&#<s}E8cNMNDTi)w30uX&S
z(c0t$0HP}k?T>N%IszU0@Ua)i?<aBmaSCk@&<vc-u<>;lVNAhax!z6Z`Ujx<{>*xR
z0Mc+g538N9xC;kQFnR$!SCH?9l_`wO^LOZ50Wg@e{aPiomFHT8xvZ6|`}HuAw&VTl
z?SD&o+X^68mpfstx~{BQDSa<xEd<VZ%9=>0GkgN=i*4c{6kO5(000SaNLh0L01FcU
z01FcV0GgZ_0008*Nkl<ZIE{T$Ye<t}7(L&&O{Z?Nd7+D};jFBPF5AR8uUV00Q5Gd)
zKT4ttQFOBm>R(axBghhpis%YaSwDm*SW%g1$|O^3ZZj?II&IEfzwiCtw_nPP?EE`C
z&pGg%=K%jf;S(z>Y{*>-00s4y4S5f;!hi4Z(WKaB&4}hqq@WS;;O=v!1|mwyG(yGy
z8c+eQqK2HqV_XubKnZe*S2&sKR$M>`s`3N5XD2m~1nMJ%o&tdU`xYM~EQS)Q?acUH
zu_(_HduHWvq^HfQUbEd;J*MF%-25<msYKaxPU3wUxmr^-w*m>W7<7C3alP#pjB_(l
zsx86kH+5iyff5F;;E}~gz%OYkYjOjC^^Tb-pup~V<#7G#KqwM~2ql^aKjOD<1X*bd
z(f^>`ZF}4^3jpMlvN%p6F6-T_+j5C7nWmhMb^3gK{AR~!cmzL#qad+~*ki7O$M47G
z#w$=MY3FzbjT>7OQiQfpk!}%0lCs&b9FFhp@P)ki>Gwg9sZco8jJIwZ<SYy(a`2{e
zE9O_v-a8?K?5n1TL9LH5C8uFvxDTE{0AX1?ignrO`PzY@HZPL>@#sq>7^Gj|3kLuK
z$j1{5GbvF!1qwbML%|S2h(k`&0(A9u!+EV6`SxB|l>(mdTDWKG`c>_&+1_1-qvLOs
z5x(~Ar&f%FfDnyCPRc^`4t3#Wy%TD?6FW!*J)kg)VOsO)vwn{{;niBxv4(Mjru}U-
zoWQ@n@!}p<8CD`lMj=VS6qyE9ni#kwiZU<2jrw^zBV-$87TuAWMp<+ZzS(|U*A>lJ
z*5Yc_PgU!nlxfjwcOc<|2TLTvK64x=0&pZ~_-4~$49EpCp-5wxe`wB4Ng$OHVZ5R*
z8OB~O>KrcVI|pv3J}t0*alys+&Uf7K{)(sn(ocYSUzWXcQz>%->~>Nd%PU!SK6);n
zOgM(N+E(N6)=crl>P!-NHh3v^T6#SIY%MBM22xYSKMhDxmS%e%O#lD@07*qoM6N<$
Eg369MXaE2J
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/image1.png^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: foo=bar
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4b7c102840cab57d589b4380cb1d0675498fcda9
GIT binary patch
literal 1242
zc$@*+1SR{4P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ
zHwB960004lX+uL$Nkc;*P;zf(X>4Tx0C=30k<TjxVHn3h??_7Q#rTm@a}ax2+PJKe
zvU@-r)~4+4ZFXj?tugyH^IH4??#fLLew35sB**;&+>{)ols`Zz7ik<`+6&3Ip87oB
zo_c<P(X^%X4PYZsVPP(76-#BS;~s-<0I;1%&gSz={HnJ*1i<Z>Ev5f^-H+-Di={FM
z6ELfqlYm*#JPnvzN-7X}z;xDa7laF>!j(b}#2%2SYCZxI70s7GqTy5(h$fH@+*$zQ
z1<1Hw<baU`lp{k0#vw3VER`)inp%XJA!xg4dF2Ss&!B&#<s}E8cNMNDTi)w30uX&S
z(c0t$0HP}k?T>N%IszU0@Ua)i?<aBmaSCk@&<vc-u<>;lVNAhax!z6Z`Ujx<{>*xR
z0Mc+g538N9xC;kQFnR$!SCH?9l_`wO^LOZ50Wg@e{aPiomFHT8xvZ6|`}HuAw&VTl
z?SD&o+X^68mpfstx~{BQDSa<xEd<VZ%9=>0GkgN=i*4c{6kO5(000SaNLh0L01FcU
z01FcV0GgZ_0008*Nkl<ZIE{T$Ye<t}7(L&&O{Z?Nd7+D};jFBPF5AR8uUV00Q5Gd)
zKT4ttQFOBm>R(axBghhpis%YaSwDm*SW%g1$|O^3ZZj?II&IEfzwiCtw_nPP?EE`C
z&pGg%=K%jf;S(z>Y{*>-00s4y4S5f;!hi4Z(WKaB&4}hqq@WS;;O=v!1|mwyG(yGy
z8c+eQqK2HqV_XubKnZe*S2&sKR$M>`s`3N5XD2m~1nMJ%o&tdU`xYM~EQS)Q?acUH
zu_(_HduHWvq^HfQUbEd;J*MF%-25<msYKaxPU3wUxmr^-w*m>W7<7C3alP#pjB_(l
zsx86kH+5iyff5F;;E}~gz%OYkYjOjC^^Tb-pup~V<#7G#KqwM~2ql^aKjOD<1X*bd
z(f^>`ZF}4^3jpMlvN%p6F6-T_+j5C7nWmhMb^3gK{AR~!cmzL#qad+~*ki7O$M47G
z#w$=MY3FzbjT>7OQiQfpk!}%0lCs&b9FFhp@P)ki>Gwg9sZco8jJIwZ<SYy(a`2{e
zE9O_v-a8?K?5n1TL9LH5C8uFvxDTE{0AX1?ignrO`PzY@HZPL>@#sq>7^Gj|3kLuK
z$j1{5GbvF!1qwbML%|S2h(k`&0(A9u!+EV6`SxB|l>(mdTDWKG`c>_&+1_1-qvLOs
z5x(~Ar&f%FfDnyCPRc^`4t3#Wy%TD?6FW!*J)kg)VOsO)vwn{{;niBxv4(Mjru}U-
zoWQ@n@!}p<8CD`lMj=VS6qyE9ni#kwiZU<2jrw^zBV-$87TuAWMp<+ZzS(|U*A>lJ
z*5Yc_PgU!nlxfjwcOc<|2TLTvK64x=0&pZ~_-4~$49EpCp-5wxe`wB4Ng$OHVZ5R*
z8OB~O>KrcVI|pv3J}t0*alys+&Uf7K{)(sn(ocYSUzWXcQz>%->~>Nd%PU!SK6);n
zOgM(N+E(N6)=crl>P!-NHh3v^T6#SIY%MBM22xYSKMhDxmS%e%O#lD@07*qoM6N<$
Eg369MXaE2J
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/image2.png^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: foo2=bar2
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test1.css
@@ -0,0 +1,2 @@
+
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test1.css^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: css=bar
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test2.css
@@ -0,0 +1,2 @@
+
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test2.css^headers^
@@ -0,0 +1,3 @@
+Cache-Control: no-cache
+Set-Cookie: css2=bar2
+
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_differentdomain.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.com/tests/extensions/cookie/test/file_domain_inner.html', 3, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_image.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_image_inner.html', 7, 3)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js"></script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_loadflags.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_loadflags_inner.html', 'example.org', 5, 1, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testloadflags.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://test1.example.org/tests/extensions/cookie/test/file_domain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_2.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://test1.example.org/tests/extensions/cookie/test/file_subdomain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_3.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_subdomain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_4.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://localhost:8888/tests/extensions/cookie/test/file_localhost_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_5.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://sub1.test1.example.org/tests/extensions/cookie/test/file_subdomain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_6.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://127.0.0.1:8888/tests/extensions/cookie/test/file_loopback_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_same_base_domain_7.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://127.1:8888/tests/extensions/cookie/test/file_loopback_inner.html', 3, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/test_samedomain.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Cross domain access to properties</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body onload="setupTest('http://example.org/tests/extensions/cookie/test/file_domain_inner.html', 5, 2)">
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript" src="file_testcommon.js">
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/extensions/cookie/test/unit/test_cookies.js
@@ -0,0 +1,49 @@
+// test third party cookie blocking, for the cases:
+// 1) with null channel
+// 2) with channel, but with no docshell parent
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function run_test() {
+  var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
+  var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
+  var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+  var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+
+  var spec = "http://foo.com/dribble.html";
+  var uri = ios.newURI(spec, null, null);
+  var channel = ios.newChannelFromURI(uri);
+
+  // test with cookies enabled
+  prefs.setIntPref("network.cookie.cookieBehavior", 0);
+  // without channel
+  cs.setCookieString(uri, null, "oh=hai", null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 1);
+  // with channel
+  cs.setCookieString(uri, null, "can=has", channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 2);
+  // without channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "cheez=burger", null, null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 3);
+  // with channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "hot=dog", null, channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 4);
+  cs.removeAll();
+
+  // test with third party cookies blocked
+  prefs.setIntPref("network.cookie.cookieBehavior", 1);
+  // without channel
+  cs.setCookieString(uri, null, "oh=hai", null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+  // with channel
+  cs.setCookieString(uri, null, "can=has", channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+  // without channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "cheez=burger", null, null);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+  // with channel, from http
+  cs.setCookieStringFromHttp(uri, null, null, "hot=dog", null, channel);
+  do_check_eq(cs.countCookiesFromHost("foo.com"), 0);
+}
+
--- a/extensions/metrics/build/Makefile.in
+++ b/extensions/metrics/build/Makefile.in
@@ -56,28 +56,28 @@ REQUIRES	= \
 		$(NULL)
 
 CPPSRCS		= \
 		nsMetricsModule.cpp \
 		$(NULL)
 
 SHARED_LIBRARY_LIBS = \
 		../src/$(LIB_PREFIX)metrics_s.$(LIB_SUFFIX) \
-		$(DEPTH)/modules/libbz2/src/$(LIB_PREFIX)bz2.$(LIB_SUFFIX) \
 		$(NULL)
 
 EXTRA_DSO_LDOPTS = $(XPCOM_GLUE_LDOPTS) \
 		   $(NSPR_LIBS) \
+		   $(BZ2_LIBS) \
 		   $(NULL)
 
 LOCAL_INCLUDES	= \
 		-I$(srcdir)/../src \
 		-I$(DIST)/public/nss \
 		-I$(DIST)/private/nss \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH)_$(GNU_CC), WINNT_)
   LDFLAGS += -NODEFAULTLIB:MSVCRT
 endif
 
-
+CXXFLAGS += $(BZ2_CFLAGS)
--- a/extensions/metrics/src/Makefile.in
+++ b/extensions/metrics/src/Makefile.in
@@ -52,17 +52,17 @@ REQUIRES	= xpcom \
 		  string \
 		  necko \
 		  pref \
 		  uriloader \
 		  dom \
 		  docshell \
 		  layout \
 		  widget \
-		  libbz2 \
+		  $(BZ2_REQUIRES) \
 		  xulapp \
 		  extensions \
 		  rdf \
 		  plugin \
 		  content \
 		  autocomplete \
 		  places \
 		  toolkitcomps \
--- a/extensions/metrics/test/Makefile.in
+++ b/extensions/metrics/test/Makefile.in
@@ -62,25 +62,27 @@ LOCAL_INCLUDES	= \
 		-I$(srcdir)/../src \
 		-I$(srcdir)/../build \
 		-I$(DIST)/public/nss \
 		-I$(DIST)/private/nss \
 		$(NULL)
 
 LIBS		= \
 		../src/$(LIB_PREFIX)metrics_s.$(LIB_SUFFIX) \
-		$(DEPTH)/modules/libbz2/src/$(LIB_PREFIX)bz2.$(LIB_SUFFIX) \
+		$(BZ2_LIBS) \
 		$(XPCOM_GLUE_LDOPTS) \
 		$(NSPR_LIBS) \
 		$(NULL)
 
 XPCSHELL_TESTS = unit
 
 include $(topsrcdir)/config/rules.mk
 
+CXXFLAGS += $(BZ2_CFLAGS)
+
 # Give the unit tests absolute paths to the data and temp directories.
 # For cygwin, we need to convert the paths to native Windows paths.
 ifdef CYGWIN_WRAPPER
 TESTDATA_DIR := `cygpath -wa $(srcdir)/data`
 TEST_TMPDIR := `cygpath -wa .`
 else
 TESTDATA_DIR := `cd $(srcdir)/data; pwd`
 TEST_TMPDIR := `pwd`
--- a/gfx/src/thebes/nsSystemFontsBeOS.cpp
+++ b/gfx/src/thebes/nsSystemFontsBeOS.cpp
@@ -40,31 +40,20 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include <Font.h>
 #include <Menu.h>
 
 #include "nsIDeviceContext.h"
 #include "nsSystemFontsBeOS.h"
 
-#define DEFAULT_PIXEL_FONT_SIZE 16.0f
-
 nsSystemFontsBeOS::nsSystemFontsBeOS()
   : mDefaultFontName(NS_LITERAL_STRING("sans-serif"))
   , mMenuFontName(NS_LITERAL_STRING("sans-serif"))
   , mCaptionFontName(NS_LITERAL_STRING("sans-serif"))
-  , mDefaultFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-                 DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-                 0.0f, PR_TRUE, PR_FALSE)
-  , mMenuFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-               DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-               0.0f, PR_TRUE, PR_FALSE)
-  , mCaptionFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-               DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-               0.0f, PR_TRUE, PR_FALSE)
 {
   menu_info info;
   get_menu_info(&info);
   BFont menuFont;
   menuFont.SetFamilyAndStyle(info.f_family, info.f_style);
   menuFont.SetSize(info.font_size);
 
   GetSystemFontInfo(be_plain_font, &mDefaultFontName, &mDefaultFontStyle);
--- a/gfx/src/thebes/nsSystemFontsGTK2.cpp
+++ b/gfx/src/thebes/nsSystemFontsGTK2.cpp
@@ -103,35 +103,21 @@ static inline void ShutdownPangoLib()
 
 static inline gboolean
 MOZ_pango_font_description_get_size_is_absolute(PangoFontDescription *desc)
 {
     pango_font_description_get_size_is_absolute(desc);
 }
 #endif
 
-#define DEFAULT_PIXEL_FONT_SIZE 16.0f
-
 nsSystemFontsGTK2::nsSystemFontsGTK2()
   : mDefaultFontName(NS_LITERAL_STRING("sans-serif"))
   , mButtonFontName(NS_LITERAL_STRING("sans-serif"))
   , mFieldFontName(NS_LITERAL_STRING("sans-serif"))
   , mMenuFontName(NS_LITERAL_STRING("sans-serif"))
-  , mDefaultFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-                 DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-                 0.0f, PR_TRUE, PR_FALSE)
-  , mButtonFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-                DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-                0.0f, PR_TRUE, PR_FALSE)
-  , mFieldFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-               DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-               0.0f, PR_TRUE, PR_FALSE)
-  , mMenuFontStyle(FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL,
-               DEFAULT_PIXEL_FONT_SIZE, NS_LITERAL_CSTRING(""),
-               0.0f, PR_TRUE, PR_FALSE)
 {
     InitPangoLib();
 
     /*
      * Much of the widget creation code here is similar to the code in
      * nsLookAndFeel::InitColors().
      */
 
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -181,16 +181,17 @@ nsThebesDeviceContext::SetDPI()
 #elif defined(XP_WIN)
         // XXX we should really look at the widget if !dc but it is currently always null
         HDC dc = GetPrintHDC();
         if (dc) {
             PRInt32 OSVal = GetDeviceCaps(dc, LOGPIXELSY);
 
             dpi = 144;
             mPrintingScale = float(OSVal)/dpi;
+            dotsArePixels = PR_FALSE;
         } else {
             dc = GetDC((HWND)nsnull);
 
             PRInt32 OSVal = GetDeviceCaps(dc, LOGPIXELSY);
 
             ReleaseDC((HWND)nsnull, dc);
 
             if (OSVal != 0)
@@ -388,19 +389,17 @@ nsThebesDeviceContext::GetSystemFont(nsS
 #elif XP_MACOSX
         gSystemFonts = new nsSystemFontsMac();
 #else
 #error Need to know how to create gSystemFonts, fix me!
 #endif
     }
 
     nsString fontName;
-    gfxFontStyle fontStyle(NS_FONT_STYLE_NORMAL, FONT_WEIGHT_NORMAL, 16.0f,
-                           NS_LITERAL_CSTRING(""), 0.0f, PR_TRUE,
-                           PR_FALSE);
+    gfxFontStyle fontStyle;
     nsresult rv = gSystemFonts->GetSystemFont(aID, &fontName, &fontStyle);
     NS_ENSURE_SUCCESS(rv, rv);
 
     aFont->name = fontName;
     aFont->style = fontStyle.style;
     aFont->systemFont = fontStyle.systemFont;
     aFont->variant = NS_FONT_VARIANT_NORMAL;
     aFont->familyNameQuirks = fontStyle.familyNameQuirks;
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/crashtests/420945-1.html
@@ -0,0 +1,4 @@
+<html>
+<head></head>
+<body dir="rtl"><div>&#x200C;&#x2028;</div></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/crashtests/420962-1.html
@@ -0,0 +1,4 @@
+<html>
+<head></head>
+<body><div>&#x0301;&#x2029;</div></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/crashtests/421393-1.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+<script type="text/javascript">
+
+function boom()
+{
+  document.body.appendChild(document.createTextNode("\uCEDD\u5C76\u000D\uCA34"));
+}
+
+</script>
+</head>
+
+<body onload="boom();"><span>&#x202E;&#x05BC;</span></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/crashtests/421813-1.html
@@ -0,0 +1,4 @@
+<html>
+<head></head>
+<body onload="document.body.appendChild(document.createTextNode('y'));">x&#x2028;&#x200D;&#x202D;<span>&#x0643;</span></body>
+</html>
--- a/gfx/thebes/crashtests/crashtests.list
+++ b/gfx/thebes/crashtests/crashtests.list
@@ -23,9 +23,12 @@ load 402307-1.html
 load 404112-1.html
 load 404112-2.html
 load 405268-1.xhtml
 load 407761-1.html
 load 407842.html
 load 410728-1.xml
 load 416637-1.html
 load 419095-1.html
-
+load 420945-1.html
+load 420962-1.html
+load 421393-1.html
+load 421813-1.html
--- a/gfx/thebes/public/gfxFont.h
+++ b/gfx/thebes/public/gfxFont.h
@@ -67,16 +67,17 @@ class gfxFontGroup;
 #define FONT_STYLE_OBLIQUE             2
 
 #define FONT_WEIGHT_NORMAL             400
 #define FONT_WEIGHT_BOLD               700
 
 #define FONT_MAX_SIZE                  2000.0
 
 struct THEBES_API gfxFontStyle {
+    gfxFontStyle();
     gfxFontStyle(PRUint8 aStyle, PRUint16 aWeight, gfxFloat aSize,
                  const nsACString& aLangGroup,
                  float aSizeAdjust, PRPackedBool aSystemFont,
                  PRPackedBool aFamilyNameQuirks);
     gfxFontStyle(const gfxFontStyle& aStyle);
 
     // The style of font (normal, italic, oblique)
     PRUint8 style : 7;
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -868,16 +868,25 @@ gfxFontGroup::MakeSpaceTextRun(const Par
         textRun->SetSpaceGlyph(font, aParams->mContext, 0);
     }
     // Note that the gfxGlyphExtents glyph bounds storage for the font will
     // always contain an entry for the font's space glyph, so we don't have
     // to call FetchGlyphExtents here.
     return textRun.forget();
 }
 
+#define DEFAULT_PIXEL_FONT_SIZE 16.0f
+
+gfxFontStyle::gfxFontStyle() :
+    style(FONT_STYLE_NORMAL), systemFont(PR_TRUE), familyNameQuirks(PR_FALSE),
+    weight(FONT_WEIGHT_NORMAL), size(DEFAULT_PIXEL_FONT_SIZE),
+    langGroup(NS_LITERAL_CSTRING("x-western")), sizeAdjust(0.0f)
+{
+}
+
 gfxFontStyle::gfxFontStyle(PRUint8 aStyle, PRUint16 aWeight, gfxFloat aSize,
                            const nsACString& aLangGroup,
                            float aSizeAdjust, PRPackedBool aSystemFont,
                            PRPackedBool aFamilyNameQuirks) :
     style(aStyle), systemFont(aSystemFont),
     familyNameQuirks(aFamilyNameQuirks), weight(aWeight),
     size(aSize), langGroup(aLangGroup), sizeAdjust(aSizeAdjust)
 {
--- a/intl/unicharutil/util/nsBidiUtils.cpp
+++ b/intl/unicharutil/util/nsBidiUtils.cpp
@@ -37,16 +37,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #include "nsBidiUtils.h"
 #include "symmtable.h"
 #include "bidicattable.h"
+#include "nsCharTraits.h"
 
 #define FE_TO_06_OFFSET 0xfe70
 
 static const PRUnichar FE_TO_06 [][2] = {
     {0x064b,0x0000},{0x064b,0x0640},{0x064c,0x0000},
     {0x0000,0x0000},{0x064d,0x0000},{0x0000,0x0000},
     {0x064e,0x0000},{0x064e,0x0640},{0x064f,0x0000},
     {0x064f,0x0640},{0x0650,0x0000},{0x0650,0x0640},
@@ -608,16 +609,32 @@ PRBool IsBidiCategory(PRUint32 aChar, eB
 PRBool IsBidiControl(PRUint32 aChar)
 {
   // This method is used when stripping Bidi control characters for
   // display, so it will return TRUE for LRM and RLM as
   // well as the characters with category eBidiCat_CC
   return (eBidiCat_CC == GetBidiCat(aChar) || ((aChar)&0xfffffe)==LRM_CHAR);
 }
 
+PRBool HasRTLChars(nsAString& aString)
+{
+  PRInt32 length = aString.Length();
+  for (PRInt32 i = 0; i < length; i++) {
+    if ((UCS2_CHAR_IS_BIDI(aString.CharAt(i)) ) ||
+        ((NS_IS_HIGH_SURROGATE(aString.CharAt(i))) &&
+         (++i < length) &&
+         (NS_IS_LOW_SURROGATE(aString.CharAt(i))) &&
+         (UTF32_CHAR_IS_BIDI(SURROGATE_TO_UCS4(aString.CharAt(i-1),
+                                               aString.CharAt(i)))))) {
+      return PR_TRUE;
+    }
+  }
+  return PR_FALSE;
+}
+
 nsCharType GetCharType(PRUint32 aChar)
 {
   nsCharType oResult;
   eBidiCategory bCat = GetBidiCat(aChar);
   if (eBidiCat_CC != bCat) {
     NS_ASSERTION(bCat < (sizeof(ebc2ucd)/sizeof(nsCharType)), "size mismatch");
     if(bCat < (sizeof(ebc2ucd)/sizeof(nsCharType)))
       oResult = ebc2ucd[bCat];
--- a/intl/unicharutil/util/nsBidiUtils.h
+++ b/intl/unicharutil/util/nsBidiUtils.h
@@ -198,16 +198,22 @@ typedef enum nsCharType nsCharType;
 
   /**
    * Give a UTF-32 codepoint
    * return PR_TRUE if the codepoint is a Bidi control character (LRE, RLE, PDF, LRO, RLO, LRM, RLM)
    * return PR_FALSE, otherwise
    */
   PRBool IsBidiControl(PRUint32 aChar);
 
+  /**
+   * Give an nsString.
+   * @return PR_TRUE if the string contains right-to-left characters
+   */
+  PRBool HasRTLChars(nsAString& aString);
+
 // --------------------------------------------------
 // IBMBIDI 
 // --------------------------------------------------
 //
 // These values are shared with Preferences dialog
 //  ------------------
 //  If Pref values are to be changed
 //  in the XUL file of Prefs. the values
--- a/js/src/Makefile.ref
+++ b/js/src/Makefile.ref
@@ -79,16 +79,17 @@ ifdef JS_HAS_FILE_OBJECT
 DEFINES += -DJS_HAS_FILE_OBJECT
 endif
 
 #
 # XCFLAGS may be set in the environment or on the gmake command line
 #
 #CFLAGS += -DDEBUG -DDEBUG_brendan -DJS_ARENAMETER -DJS_HASHMETER -DJS_DUMP_PROPTREE_STATS -DJS_DUMP_SCOPE_METERS -DJS_SCOPE_DEPTH_METER -DJS_BASIC_STATS
 CFLAGS          += $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+INTERP_CFLAGS   += $(INTERP_OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(INTERP_XCFLAGS)
 
 LDFLAGS		= $(XLDFLAGS)
 
 ifdef MOZ_SHARK
 DEFINES += -DMOZ_SHARK
 CFLAGS += -F/System/Library/PrivateFrameworks
 LDFLAGS += -F/System/Library/PrivateFrameworks -framework CHUD
 endif
--- a/js/src/config.mk
+++ b/js/src/config.mk
@@ -114,27 +114,31 @@ CP = cp
 else
 INSTALL	= $(DIST)/bin/nsinstall
 CP = cp
 endif
 
 ifdef BUILD_OPT
 ifdef USE_MSVC
 OPTIMIZER  = -O2 -GL
+INTERP_OPTIMIZER = -O2 -GL
 LDFLAGS    += -LTCG
 else
 OPTIMIZER  = -Os
+INTERP_OPTIMIZER = -Os
 endif
 DEFINES    += -UDEBUG -DNDEBUG -UDEBUG_$(USER)
 OBJDIR_TAG = _OPT
 else
 ifdef USE_MSVC
 OPTIMIZER  = -Zi
+INTERP_OPTIMIZER = -Zi
 else
 OPTIMIZER  = -g3
+INTERP_OPTIMIZER = -g3
 endif
 DEFINES    += -DDEBUG -DDEBUG_$(USER)
 OBJDIR_TAG = _DBG
 endif
 
 SO_SUFFIX = so
 
 NS_USE_NATIVE = 1
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2473,17 +2473,17 @@ array_slice(JSContext *cx, uintN argc, j
             }
             end = (jsuint)d;
         }
     }
 
     if (begin > end)
         begin = end;
 
-    if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+    if (OBJ_IS_DENSE_ARRAY(cx, obj) && end <= ARRAY_DENSE_LENGTH(obj)) {
         nobj = js_NewArrayObject(cx, end - begin, obj->dslots + begin);
         if (!nobj)
             return JS_FALSE;
         *vp = OBJECT_TO_JSVAL(nobj);
         return JS_TRUE;
     }
 
     /* Create a new Array object and root it using *vp. */
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -736,17 +736,17 @@ js_ValueToNumber(JSContext *cx, jsval *v
              * be interpreted as decimal by js_strtod and will never get
              * passed to js_strtointeger (which would interpret them as
              * octal).
              */
             JSSTRING_CHARS_AND_END(str, bp, end);
             if ((!js_strtod(cx, bp, end, &ep, &d) ||
                  js_SkipWhiteSpace(ep, end) != end) &&
                 (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
-              js_SkipWhiteSpace(ep, end) != end)) {
+                 js_SkipWhiteSpace(ep, end) != end)) {
                 break;
             }
 
             /*
              * JSVAL_TRUE indicates that double jsval was never constructed
              * for the result.
              */
             *vp = JSVAL_TRUE;
--- a/js/src/rules.mk
+++ b/js/src/rules.mk
@@ -72,30 +72,37 @@ endif
 	@$(MAKE_OBJDIR)
 	$(CXX) -o $@ $(CFLAGS) $*.cpp $(LDFLAGS)
 
 # This rule must come before the rule with no dep on header
 $(OBJDIR)/%.o: %.cpp %.h
 	@$(MAKE_OBJDIR)
 	$(CXX) -o $@ -c $(CFLAGS) $*.cpp
 
+$(OBJDIR)/jsinterp.o: jsinterp.c jsinterp.h
+	@$(MAKE_OBJDIR)
+	$(CC) -o $@ -c $(INTERP_CFLAGS) jsinterp.c
 
 $(OBJDIR)/%.o: %.cpp
 	@$(MAKE_OBJDIR)
 	$(CXX) -o $@ -c $(CFLAGS) $*.cpp
 
 $(OBJDIR)/%.o: %.s
 	@$(MAKE_OBJDIR)
 	$(AS) -o $@ $(ASFLAGS) $*.s
 
 # This rule must come before rule with no dep on header
 $(OBJDIR)/%.obj: %.cpp %.h
 	@$(MAKE_OBJDIR)
 	$(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $*.cpp
 
+$(OBJDIR)/jsinterp.obj: jsinterp.cpp jsinterp.h
+	@$(MAKE_OBJDIR)
+	$(CXX) -Fo$(OBJDIR)/ -c $(INTERP_CFLAGS) $(JSDLL_CFLAGS) jsinterp.c
+
 $(OBJDIR)/%.obj: %.cpp
 	@$(MAKE_OBJDIR)
 	$(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $*.cpp
 
 $(OBJDIR)/js.obj: js.cpp
 	@$(MAKE_OBJDIR)
 	$(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $<
 
--- a/js/tests/ecma/shell.js
+++ b/js/tests/ecma/shell.js
@@ -154,21 +154,25 @@ function DaysInYear( y ) {
 }
 function TimeInYear( y ) {
   return ( DaysInYear(y) * msPerDay );
 }
 function DayNumber( t ) {
   return ( Math.floor( t / msPerDay ) );
 }
 function TimeWithinDay( t ) {
-  if ( t < 0 ) {
-    return ( (t % msPerDay) + msPerDay );
-  } else {
-    return ( t % msPerDay );
+
+  var r = t % msPerDay;
+
+  if (r < 0)
+  {
+    r += msPerDay;
   }
+  return r;
+
 }
 function YearNumber( t ) {
 }
 function TimeFromYear( y ) {
   return ( msPerDay * DayFromYear(y) );
 }
 function DayFromYear( y ) {
   return ( 365*(y-1970) +
new file mode 100755
--- /dev/null
+++ b/js/tests/ecma_3/Date/15.9.1.2-01.js
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is JavaScript Engine testing utilities.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * 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 ***** */
+
+var gTestfile = '15.9.1.2-01.js';
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 264727;
+var summary = '15.9.1.2 - TimeWithinDay(TIME_1900) == 0';
+var actual = '';
+var expect = '';
+
+
+//-----------------------------------------------------------------------------
+test();
+//-----------------------------------------------------------------------------
+
+function test()
+{
+  enterFunc ('test');
+  printBugNumber(BUGNUMBER);
+  printStatus (summary);
+ 
+  expect = 0;
+  actual = TimeWithinDay(TIME_1900);
+
+  reportCompare(expect, actual, summary);
+
+  exitFunc ('test');
+}
--- a/js/tests/ecma_3/Date/shell.js
+++ b/js/tests/ecma_3/Date/shell.js
@@ -148,21 +148,25 @@ function DaysInYear( y ) {
 }
 function TimeInYear( y ) {
   return ( DaysInYear(y) * msPerDay );
 }
 function DayNumber( t ) {
   return ( Math.floor( t / msPerDay ) );
 }
 function TimeWithinDay( t ) {
-  if ( t < 0 ) {
-    return ( (t % msPerDay) + msPerDay );
-  } else {
-    return ( t % msPerDay );
+
+  var r = t % msPerDay;
+
+  if (r < 0)
+  {
+    r += msPerDay;
   }
+  return r;
+
 }
 function YearNumber( t ) {
 }
 function TimeFromYear( y ) {
   return ( msPerDay * DayFromYear(y) );
 }
 function DayFromYear( y ) {
   return ( 365*(y-1970) +
--- a/js/tests/public-failures.txt
+++ b/js/tests/public-failures.txt
@@ -146,17 +146,17 @@ TEST_ID=js1_5/Array/regress-330812.js, T
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory`|`BUGNUMBER: 330812; STATUS: Making Array(1<<29).sort() less problematic; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 3 ---; STATUS: This test passes if the browser does not hang or crash; STATUS: This test expects exit code 0 or 3 to indicate out of memory`)`
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory`)`
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=(browser|shell), TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 330812; STATUS: Making Array(1<<29).sort() less problematic; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 3 ---; STATUS: This test passes if the browser does not hang or crash; STATUS: This test expects exit code 0 or 3 to indicate out of memory
 TEST_ID=js1_5/Array/regress-330812.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: CRASHED 5 `.``*`/js1_5/Array/regress-330812.js:`.``*`: out of memory
 TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
-TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=shell, TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
+TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=(browser|shell), TEST_OS=mac, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: TIMED OUT
 TEST_ID=js1_5/Array/regress-350256-03.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Array/regress-350256-03.js:`.``*`: `(`InternalError: `)``?`script stack space quota is exhausted
 TEST_ID=js1_5/Error/regress-354246.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`/js1_5/Error/regress-354246.js:`.``*`: x is not defined
 TEST_ID=js1_5/Expressions/regress-394673.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*``(`InternalError:`|`reason:`)``?` too much recursion
 TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338001.js:`.``*`: out of memory
 TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=(1.8.1|1.9.0), TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338001; STATUS: integer overflow in jsfun.c:Function; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
 TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Function/regress-338001.js:`.``*`: out of memory
 TEST_ID=js1_5/Function/regress-338001.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 338001; STATUS: integer overflow in jsfun.c:Function; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
 TEST_ID=js1_5/Function/regress-338121-01.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: CRASHED `.``*`/js1_5/Function/regress-338121-01.js:`.``*`: out of memory
@@ -202,17 +202,17 @@ TEST_ID=js1_5/Regress/regress-303213.js,
 TEST_ID=js1_5/Regress/regress-312588.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: CRASHED`|`EXIT STATUS: TIMED OUT`|``.``*`/js1_5/Regress/regress-312588.js:`.``*`: out of memory`)`
 TEST_ID=js1_5/Regress/regress-319384.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: `.``*`/js1_5/Regress/regress-319384.js:`.``*`: can't convert "foo" to an integer
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: arguments no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: arity no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: caller no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-320119.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=(browser|shell), TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=delegating objects and arguments, arity, caller, name: name no longer shared expected: false actual: true reason: Expected value 'false', Actual value 'true'
 TEST_ID=js1_5/Regress/regress-328897.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: :0: uncaught exception: Permission denied to get property UnnamedClass.classes
 TEST_ID=js1_5/Regress/regress-328897.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=JS_ReportPendingException should expected: Error actual: No Error reason: Expected value 'Error', Actual value 'No Error'
-TEST_ID=js1_5/Regress/regress-328897.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: :0: uncaught exception: Permission denied to get property XPCComponents.classes
+TEST_ID=js1_5/Regress/regress-328897.js, TEST_BRANCH=1.9.0, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`reason: javascript:Components.classes:1: Permission denied to get property XPCComponents.classes
 TEST_ID=js1_5/Regress/regress-329530.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=opt, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 329530; STATUS: Do not crash when calling toString on a deeply nested function; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---
 TEST_ID=js1_5/Regress/regress-330352.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(linux|mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: CRASHED `.``*`, `)``?`BUGNUMBER: 330352; STATUS: Very non-greedy regexp causes crash in jsregexp.c; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 0 ---; --- NOTE: IN THIS TESTCASE, WE EXPECT EXIT CODE 5 ---`(`; JavaScript error: `.``*`/js1_5/Regress/regress-330352.js:`.``*`: out of memory;`)``?`
 TEST_ID=js1_5/Regress/regress-330352.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=2.6.9.*ELsmp, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Regress/regress-330352.js:`.``*`: out of memory
 TEST_ID=js1_5/Regress/regress-346237.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=browser, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=BUGNUMBER: 346237; STATUS: RegExp - /(|)??x/g.exec("y")
 TEST_ID=js1_5/Regress/regress-346237.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=(mac|win32), TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Regress/regress-346237.js:`.``*`: out of memory
 TEST_ID=js1_5/Regress/regress-346237.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=(debug|opt), TEST_TYPE=shell, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=EXIT STATUS: CRASHED `.``*`/js1_5/Regress/regress-346237.js:`.``*`: out of memory
 TEST_ID=js1_5/Regress/regress-346237.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=linux, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`(`EXIT STATUS: CRASHED `.``*`, `)``?`BUGNUMBER: 346237; STATUS: RegExp - /(|)??x/g.exec("y"); JavaScript error: `.``*`/js1_5/Regress/regress-346237.js:`.``*`: out of memory
 TEST_ID=js1_5/Regress/regress-346237.js, TEST_BRANCH=1.8.1, TEST_RESULT=FAILED, TEST_BUILDTYPE=debug, TEST_TYPE=browser, TEST_OS=win32, TEST_MACHINE=.*, TEST_PROCESSORTYPE=.*, TEST_KERNEL=.*, TEST_DATE=.*, TEST_TIMEZONE=.*, TEST_DESCRIPTION=`.``*`/js1_5/Regress/regress-346237.js:`.``*`: out of memory
new file mode 100644
--- /dev/null
+++ b/layout/generic/crashtests/415685-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+<style type="text/css">
+
+div { height: 10px; margin: 1em; outline: 1px inset black; }
+
+</style>
+</head>
+
+<body onload="document.getElementById('a').style.padding = '12em 0';" style="-moz-column-count: 2; width: 1px;"><div id="a">aaaa aaaa aaaa</div><div style="border: medium solid blue;"></div><div style="border: medium solid green; margin: 10em 0pt;"></div><div style="border: medium solid magenta;"></div>xxxx xxxx xxxx</body>
+
+</html>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -87,9 +87,10 @@ load 400232-1.html
 load 403576-1.html
 load 404146-1.html
 load 404204-1.html
 load 406380.html
 load 407009-1.xhtml
 load 408749-1.xhtml
 load 408883-1.html
 load 410228-1.html
+load 415685-1.html
 load 421404-1.html
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -115,16 +115,28 @@ nsBulletFrame::GetFrameName(nsAString& a
 #endif
 
 nsIAtom*
 nsBulletFrame::GetType() const
 {
   return nsGkAtoms::bulletFrame;
 }
 
+PRBool
+nsBulletFrame::IsEmpty()
+{
+  return IsSelfEmpty();
+}
+
+PRBool
+nsBulletFrame::IsSelfEmpty() 
+{
+  return GetStyleList()->mListStyleType == NS_STYLE_LIST_STYLE_NONE;
+}
+
 NS_IMETHODIMP
 nsBulletFrame::DidSetStyleContext()
 {
   imgIRequest *newRequest = GetStyleList()->mListStyleImage;
 
   if (newRequest) {
 
     if (!mListener) {
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -96,16 +96,19 @@ public:
                                   nsString& aResult);
 
   /* get list item text, with '.' */
   PRBool GetListItemText(const nsStyleList& aStyleList,
                          nsString& aResult);
                          
   void PaintBullet(nsIRenderingContext& aRenderingContext, nsPoint aPt,
                    const nsRect& aDirtyRect);
+  
+  virtual PRBool IsEmpty();
+  virtual PRBool IsSelfEmpty();
 
 protected:
   void GetDesiredSize(nsPresContext* aPresContext,
                       nsIRenderingContext *aRenderingContext,
                       nsHTMLReflowMetrics& aMetrics);
 
   void GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup);
 
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -655,50 +655,62 @@ nsContainerFrame::DoInlineIntrinsicWidth
   const nsStylePadding *stylePadding = GetStylePadding();
   const nsStyleBorder *styleBorder = GetStyleBorder();
   const nsStyleMargin *styleMargin = GetStyleMargin();
 
   // This goes at the beginning no matter how things are broken and how
   // messy the bidi situations are, since per CSS2.1 section 8.6
   // (implemented in bug 328168), the startSide border is always on the
   // first line.
-  aData->currentLine +=
-    GetCoord(stylePadding->mPadding.Get(startSide), 0) +
-    styleBorder->GetBorderWidth(startSide) +
-    GetCoord(styleMargin->mMargin.Get(startSide), 0);
+  // This frame is a first-in-flow, but it might have a previous bidi
+  // continuation, in which case that continuation should handle the startSide 
+  // border.
+  if (!GetPrevContinuation()) {
+    aData->currentLine +=
+      GetCoord(stylePadding->mPadding.Get(startSide), 0) +
+      styleBorder->GetBorderWidth(startSide) +
+      GetCoord(styleMargin->mMargin.Get(startSide), 0);
+  }
 
   const nsLineList_iterator* savedLine = aData->line;
 
+  nsContainerFrame *lastInFlow;
   for (nsContainerFrame *nif = this; nif;
        nif = (nsContainerFrame*) nif->GetNextInFlow()) {
     for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
          kid = kid->GetNextSibling()) {
       if (aType == nsLayoutUtils::MIN_WIDTH)
         kid->AddInlineMinWidth(aRenderingContext,
                                static_cast<InlineMinWidthData*>(aData));
       else
         kid->AddInlinePrefWidth(aRenderingContext,
                                 static_cast<InlinePrefWidthData*>(aData));
     }
     
     // After we advance to our next-in-flow, the stored line may not
     // longer be the correct line. Just forget it.
     aData->line = nsnull;
+    lastInFlow = nif;
   }
   
   aData->line = savedLine;
 
   // This goes at the end no matter how things are broken and how
   // messy the bidi situations are, since per CSS2.1 section 8.6
   // (implemented in bug 328168), the endSide border is always on the
   // last line.
-  aData->currentLine +=
-    GetCoord(stylePadding->mPadding.Get(endSide), 0) +
-    styleBorder->GetBorderWidth(endSide) +
-    GetCoord(styleMargin->mMargin.Get(endSide), 0);
+  // We reached the last-in-flow, but it might have a next bidi
+  // continuation, in which case that continuation should handle 
+  // the endSide border.
+  if (!lastInFlow->GetNextContinuation()) {
+    aData->currentLine +=
+      GetCoord(stylePadding->mPadding.Get(endSide), 0) +
+      styleBorder->GetBorderWidth(endSide) +
+      GetCoord(styleMargin->mMargin.Get(endSide), 0);
+  }
 }
 
 /* virtual */ nsSize
 nsContainerFrame::ComputeAutoSize(nsIRenderingContext *aRenderingContext,
                                   nsSize aCBSize, nscoord aAvailableWidth,
                                   nsSize aMargin, nsSize aBorder,
                                   nsSize aPadding, PRBool aShrinkWrap)
 {
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -863,20 +863,22 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
   
   pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
   pfd->mJustificationNumLetters = mTextJustificationNumLetters;
 
   // See if the frame is a placeholderFrame and if it is process
   // the float. At the same time, check if the frame has any non-collapsed-away
   // content.
   PRBool placedFloat = PR_FALSE;
-  PRBool hasNoncollapsedContent = PR_TRUE;
-  if (frameType) {
+  PRBool isEmpty;
+  if (!frameType) {
+    isEmpty = pfd->mFrame->IsEmpty();
+  } else {
     if (nsGkAtoms::placeholderFrame == frameType) {
-      hasNoncollapsedContent = PR_FALSE;
+      isEmpty = PR_TRUE;
       pfd->SetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE, PR_TRUE);
       nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
       if (outOfFlowFrame) {
         nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(aFrame);
         // XXXldb What is this test supposed to be?
         if (!NS_SUBTREE_DIRTY(aFrame)) {
           // incremental reflow of child
           placedFloat = InitFloat(placeholder, aReflowStatus);
@@ -888,19 +890,18 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
                        GetFirstLetterStyleOK()),
                     "FirstLetterStyle set on line with floating first letter");
       }
     }
     else if (nsGkAtoms::textFrame == frameType) {
       // Note non-empty text-frames for inline frame compatibility hackery
       pfd->SetFlag(PFD_ISTEXTFRAME, PR_TRUE);
       nsTextFrame* textFrame = static_cast<nsTextFrame*>(pfd->mFrame);
-      if (!textFrame->HasNoncollapsedCharacters()) {
-        hasNoncollapsedContent = PR_FALSE;
-      } else {
+      isEmpty = !textFrame->HasNoncollapsedCharacters();
+      if (!isEmpty) {
         pfd->SetFlag(PFD_ISNONEMPTYTEXTFRAME, PR_TRUE);
         nsIContent* content = textFrame->GetContent();
 
         const nsTextFragment* frag = content->GetText();
         if (frag) {
           pfd->SetFlag(PFD_ISNONWHITESPACETEXTFRAME,
                        !content->TextIsOnlyWhitespace());
 // fix for bug 40882
@@ -919,23 +920,25 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
             }
           }
 #endif // IBMBIDI
         }
       }
     }
     else if (nsGkAtoms::brFrame == frameType) {
       pfd->SetFlag(PFD_SKIPWHENTRIMMINGWHITESPACE, PR_TRUE);
+      isEmpty = PR_FALSE;
     } else {
       if (nsGkAtoms::letterFrame==frameType) {
         pfd->SetFlag(PFD_ISLETTERFRAME, PR_TRUE);
       }
-      if (pfd->mSpan &&
-          !pfd->mSpan->mHasNonemptyContent && pfd->mFrame->IsSelfEmpty()) {
-        hasNoncollapsedContent = PR_FALSE;
+      if (pfd->mSpan) {
+        isEmpty = !pfd->mSpan->mHasNonemptyContent && pfd->mFrame->IsSelfEmpty();
+      } else {
+        isEmpty = pfd->mFrame->IsEmpty();
       }
     }
   }
 
   mSpaceManager->Translate(-tx, -ty);
 
   NS_ASSERTION(metrics.width>=0, "bad width");
   NS_ASSERTION(metrics.height>=0,"bad height");
@@ -1007,17 +1010,17 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
     }
 
     // See if we can place the frame. If we can't fit it, then we
     // return now.
     PRBool optionalBreakAfterFits;
     if (CanPlaceFrame(pfd, reflowState, notSafeToBreak, continuingTextRun,
                       savedOptionalBreakContent != nsnull, metrics,
                       aReflowStatus, &optionalBreakAfterFits)) {
-      if (hasNoncollapsedContent) {
+      if (!isEmpty) {
         psd->mHasNonemptyContent = PR_TRUE;
       }
 
       // Place the frame, updating aBounds with the final size and
       // location.  Then apply the bottom+right margins (as
       // appropriate) to the frame.
       PlaceFrame(pfd, metrics);
       PerSpanData* span = pfd->mSpan;
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -47,17 +47,16 @@
 #include "nsPageContentFrame.h"
 #include "nsDisplayList.h"
 #include "nsLayoutUtils.h" // for function BinarySearchForPosition
 #include "nsCSSRendering.h"
 #include "nsSimplePageSequence.h" // for nsSharedPageData
 #include "nsTextFormatter.h" // for page number localization formatting
 #ifdef IBMBIDI
 #include "nsBidiUtils.h"
-#include "nsBidiPresUtils.h"
 #endif
 #include "nsIFontMetrics.h"
 #include "nsIPrintSettings.h"
 #include "nsRegion.h"
 
 #include "prlog.h"
 #ifdef PR_LOGGING 
 extern PRLogModuleInfo * kLayoutPrintingLogMod;
@@ -364,16 +363,18 @@ nsPageFrame::DrawHeaderFooter(nsIRenderi
         } else {
           // We can only fit 3 or fewer chars.  Just show nothing
           str.Truncate();
         }
       }
     } else { 
       return; // bail if couldn't find the correct length
     }
+    
+    PresContext()->SetBidiEnabled(HasRTLChars(str));
 
     // cacl the x and y positions of the text
     nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
     nscoord y;
     if (aHeaderFooter == eHeader) {
       y = aRect.y + mPD->mExtraMargin.top + mPD->mEdgePaperMargin.top;
     } else {
       y = aRect.YMost() - aHeight - mPD->mExtraMargin.bottom - mPD->mEdgePaperMargin.bottom;
--- a/layout/reftests/bidi/reftest.list
+++ b/layout/reftests/bidi/reftest.list
@@ -12,14 +12,14 @@ fails-if(MOZ_WIDGET_TOOLKIT!="windows") 
 == mixedChartype-00.html mixedChartype-00-ref.html
 == mixedChartype-00-j.html mixedChartype-00-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == mixedChartype-01.html mixedChartype-01-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == mixedChartype-01-j.html mixedChartype-01-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == mixedChartype-02.html mixedChartype-02-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == mixedChartype-02-j.html mixedChartype-02-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == mixedChartype-03.html mixedChartype-03-ref.html
 random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == mixedChartype-03-j.html mixedChartype-03-ref.html
-== 386339.html 386339-ref.html
+random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == 386339.html 386339-ref.html
 == 409375.html 409375-ref.html
 == 413542-1.html 413542-1-ref.html
 == 413542-2.html 413542-2-ref.html
 == 413928-1.html 413928-1-ref.html
 == 413928-2.html 413928-2-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/421419-1-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<style type="text/css">
+div {
+	float: left;
+	border: medium solid black;
+}
+</style>
+</head>
+<body>
+<div><span style="padding-right: 10em;"><br>&lrm;</span></div>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/421419-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<style type="text/css">
+div {
+	float: left;
+	border: medium solid black;
+}
+</style>
+</head>
+<body>
+<div><span style="padding-right: 10em;"><br>&rlm;</span></div>
+</body>
+</html>
\ No newline at end of file
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -747,10 +747,11 @@ random == 403134-1.html 403134-1-ref.htm
 == 417246-1.html 417246-1-ref.html
 == 417676.html 417676-ref.html
 == 418766-1a.html 418766-1-ref.html
 == 418766-1b.html 418766-1-ref.html
 == 419060.html 419060-ref.html
 == 419531-1.html 419531-1-ref.html
 == 420069-1.html 420069-1-ref.html
 == 420069-2.html 420069-2-ref.html
-# == 420351-1.html 420351-1-ref.html
+== 420351-1.html 420351-1-ref.html
 == 421234-1.html 421234-1-ref.html
+== 421419-1.html 421419-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/image-scaling-01.svg
@@ -0,0 +1,21 @@
+<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=421780
+
+     Test related to bug 421780; make sure that 1-pixel, single-colour images
+     are correctly scaled to the right size.
+
+     This test makes sure that images aren't sized too big; it takes a 100%
+     width lime rect, overlaid with a 183x183 width stretched red image,
+     overlaid with a 183x183 lime rect.
+
+     183 in particular is used because 183*183 > 2^16, and we can easily run
+     into double-scaling bugs that will overflow in pixman.  -->
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <title> Ensure images aren't scaled too big </title>
+
+  <rect width="100%" height="100%" fill="lime"/>
+  <image width="183" height="183" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAxJREFUCNdj+M/AAAADAQEAGN2NsAAAAABJRU5ErkJggg"/>
+  <rect width="183" height="183" fill="lime"/>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/image-scaling-02.svg
@@ -0,0 +1,21 @@
+<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=421780
+
+     Test related to bug 421780; make sure that 1-pixel, single-colour images
+     are correctly scaled to the right size.
+
+     This test makes sure that images aren't sized too small; it takes a 100%
+     width lime rect, overlaid with a 183x183 width red rect, overlaid with a
+     183x183 stretched lime image.
+
+     183 in particular is used because 183*183 > 2^16, and we can easily run
+     into double-scaling bugs that will overflow in pixman.  -->
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <title> Ensure images aren't scaled too small </title>
+
+  <rect width="100%" height="100%" fill="lime"/>
+  <rect width="183" height="183" fill="red"/>
+  <image width="183" height="183" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAABGdBTUEAALGPC%2FxhBQAAAAxJREFUGFdjYPjPAAACAgEA0dNGRAAAAABJRU5ErkJggg%3D%3D"/>
+
+</svg>
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -27,16 +27,18 @@ include moz-only/reftest.list
 == foreignObject-01.svg pass.svg
 == foreignObject-ancestor-style-change-01.svg foreignObject-ancestor-style-change-01-ref.svg
 == foreignObject-change-transform-01.svg pass.svg
 == foreignObject-display-01.svg pass.svg
 == foreignObject-move-repaint-01.svg pass.svg
 == foreignObject-overflow-01.svg pass.svg
 == getElementById-a-element-01.svg pass.svg
 fails == inline-in-xul-basic-01.xul pass.svg
+== image-scaling-01.svg pass.svg
+== image-scaling-02.svg pass.svg
 == linearGradient-basic-01.svg pass.svg
 == linearGradient-basic-02.svg pass.svg
 == nested-viewBox-01.svg pass.svg
 == objectBoundingBox-and-pattern-01a.svg objectBoundingBox-and-pattern-01-ref.svg
 == objectBoundingBox-and-pattern-01b.svg objectBoundingBox-and-pattern-01-ref.svg
 == objectBoundingBox-and-pattern-01c.svg objectBoundingBox-and-pattern-01-ref.svg
 fails-if(MOZ_WIDGET_TOOLKIT=="cocoa") == opacity-and-gradient-01.svg pass.svg # bug 379610
 == opacity-and-pattern-01.svg pass.svg
--- a/layout/svg/base/src/nsSVGImageFrame.cpp
+++ b/layout/svg/base/src/nsSVGImageFrame.cpp
@@ -283,17 +283,21 @@ nsSVGImageFrame::PaintSVG(nsSVGRenderSta
     // fill-opacity doesn't affect <image>, so if we're allowed to
     // optimize group opacity, the opacity used for compositing the
     // image into the current canvas is just the group opacity.
     float opacity = 1.0f;
     if (nsSVGUtils::CanOptimizeOpacity(this)) {
       opacity = GetStyleDisplay()->mOpacity;
     }
 
-    nsSVGUtils::CompositePatternMatrix(gfx, thebesPattern, fini, width, height, opacity);
+    PRInt32 nativeWidth, nativeHeight;
+    currentFrame->GetWidth(&nativeWidth);
+    currentFrame->GetHeight(&nativeHeight);
+
+    nsSVGUtils::CompositePatternMatrix(gfx, thebesPattern, fini, nativeWidth, nativeHeight, opacity);
 
     if (GetStyleDisplay()->IsScrollableOverflow())
       gfx->Restore();
   }
 
   return rv;
 }
 
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -604,27 +604,18 @@ nsTextBoxFrame::CalculateTitleForWidth(n
 
     // see if the text will completely fit in the width given
     mTitleWidth = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
                                                 mTitle.get(), mTitle.Length());
 
     if (mTitleWidth <= aWidth) {
         mCroppedTitle = mTitle;
 #ifdef IBMBIDI
-        PRInt32 length = mTitle.Length();
-        for (PRInt32 i = 0; i < length; i++) {
-          if ((UCS2_CHAR_IS_BIDI(mTitle.CharAt(i)) ) ||
-              ((NS_IS_HIGH_SURROGATE(mTitle.CharAt(i))) &&
-               (++i < length) &&
-               (NS_IS_LOW_SURROGATE(mTitle.CharAt(i))) &&
-               (UTF32_CHAR_IS_BIDI(SURROGATE_TO_UCS4(mTitle.CharAt(i-1),
-                                                     mTitle.CharAt(i)))))) {
+        if (HasRTLChars(mTitle)) {
             mState |= NS_FRAME_IS_BIDI;
-            break;
-          }
         }
 #endif // IBMBIDI
         return;  // fits, done.
     }
 
     const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
     // start with an ellipsis
     mCroppedTitle.Assign(kEllipsis);
--- a/netwerk/cookie/public/nsICookiePermission.idl
+++ b/netwerk/cookie/public/nsICookiePermission.idl
@@ -14,16 +14,17 @@
  * The Original Code is cookie manager code.
  *
  * The Initial Developer of the Original Code is
  * Michiel van Leeuwen (mvl@exedo.nl).
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ * Daniel Witte <dwitte@stanford.edu>
  *
  * 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
@@ -40,17 +41,17 @@ interface nsICookie2;
 interface nsIURI;
 interface nsIChannel;
 
 typedef long nsCookieAccess;
 
 /**
  * An interface to test for cookie permissions
  */
-[scriptable, uuid(91f1c3ec-73a0-4bf0-bdc5-348a1f181b0e)]
+[scriptable, uuid(4b1a775d-f6d3-4389-be2e-9dfbaf2ab47b)]
 interface nsICookiePermission : nsISupports
 {
   /**
    * nsCookieAccess values
    */
   const nsCookieAccess ACCESS_DEFAULT = 0;
   const nsCookieAccess ACCESS_ALLOW   = 1;
   const nsCookieAccess ACCESS_DENY    = 2;
@@ -81,42 +82,39 @@ interface nsICookiePermission : nsISuppo
   /**
    * canAccess
    *
    * this method is called to test whether or not the given URI/channel may
    * access the cookie database, either to set or get cookies.
    *
    * @param aURI
    *        the URI trying to access cookies
-   * @param aFirstURI
-   *        the URI initiated by the user that resulted in aURI being loaded
    * @param aChannel
    *        the channel corresponding to aURI
    *
    * @return one of the following nsCookieAccess values:
    *         ACCESS_DEFAULT, ACCESS_ALLOW, or ACCESS_DENY
    */
   nsCookieAccess canAccess(in nsIURI     aURI,
-                           in nsIURI     aFirstURI,
                            in nsIChannel aChannel);
 
   /**
    * canSetCookie
    *
    * this method is called to test whether or not the given URI/channel may
    * set a specific cookie.  this method is always preceded by a call to
    * canAccess. it may modify the isSession and expiry attributes of the
    * cookie via the aIsSession and aExpiry parameters, in order to limit
    * or extend the lifetime of the cookie. this is useful, for instance, to
    * downgrade a cookie to session-only if it fails to meet certain criteria.
    *
    * @param aURI
    *        the URI trying to set the cookie
    * @param aChannel
-   *        the corresponding to aURI
+   *        the channel corresponding to aURI
    * @param aCookie
    *        the cookie being added to the cookie database
    * @param aIsSession
    *        when canSetCookie is invoked, this is the current isSession attribute
    *        of the cookie. canSetCookie may leave this value unchanged to
    *        preserve this attribute of the cookie.
    * @param aExpiry
    *        when canSetCookie is invoked, this is the current expiry time of
@@ -125,16 +123,32 @@ interface nsICookiePermission : nsISuppo
    *
    * @return true if the cookie can be set.
    */
   boolean canSetCookie(in nsIURI     aURI,
                        in nsIChannel aChannel,
                        in nsICookie2 aCookie,
                        inout boolean aIsSession,
                        inout PRInt64 aExpiry);
+
+  /**
+   * getOriginatingURI
+   *
+   * determines the originating URI for a load given a channel, for third-party
+   * cookie blocking. this is done by leveraging the loadgroup of the channel to
+   * find the root content docshell, and the URI associated with its principal.
+   * if the root content docshell or its principal's URI cannot be obtained,
+   * this method will throw.
+   *
+   * @param aChannel
+   *        the channel for the load trying to get or set cookies
+   *
+   * @return the originating URI.
+   */
+  nsIURI getOriginatingURI(in nsIChannel aChannel);
 };
 
 %{ C++
 /**
  * The nsICookiePermission implementation is an XPCOM service registered
  * under the ContractID:
  */
 #define NS_COOKIEPERMISSION_CONTRACTID "@mozilla.org/cookie/permission;1"
--- a/netwerk/cookie/src/nsCookieService.cpp
+++ b/netwerk/cookie/src/nsCookieService.cpp
@@ -43,19 +43,16 @@
 #include "nsIIOService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefBranch2.h"
 #include "nsIPrefService.h"
 #include "nsICookiePermission.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsIChannel.h"
-#include "nsIHttpChannel.h"
-#include "nsIHttpChannelInternal.h" // evil hack!
-#include "nsIPrompt.h"
 #include "nsIFile.h"
 #include "nsIObserverService.h"
 #include "nsILineInputStream.h"
 #include "nsIEffectiveTLDService.h"
 
 #include "nsCOMArray.h"
 #include "nsArrayEnumerator.h"
 #include "nsAutoPtr.h"
@@ -443,16 +440,18 @@ nsCookieService::Init()
 
   mObserverService = do_GetService("@mozilla.org/observer-service;1");
   if (mObserverService) {
     mObserverService->AddObserver(this, "profile-before-change", PR_TRUE);
     mObserverService->AddObserver(this, "profile-do-change", PR_TRUE);
   }
 
   mPermissionService = do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
+  if (!mPermissionService)
+    NS_WARNING("nsICookiePermission implementation not available - some features won't work!");
 
   return NS_OK;
 }
 
 nsresult
 nsCookieService::InitDB()
 {
   nsCOMPtr<nsIFile> cookieFile;
@@ -642,85 +641,67 @@ nsCookieService::Observe(nsISupports    
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::GetCookieString(nsIURI     *aHostURI,
                                  nsIChannel *aChannel,
                                  char       **aCookie)
 {
-  // try to determine first party URI
-  nsCOMPtr<nsIURI> firstURI;
-  if (aChannel) {
-    nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
-    if (httpInternal)
-      httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
-  }
-
-  GetCookieInternal(aHostURI, firstURI, aChannel, PR_FALSE, aCookie);
+  GetCookieInternal(aHostURI, aChannel, PR_FALSE, aCookie);
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::GetCookieStringFromHttp(nsIURI     *aHostURI,
                                          nsIURI     *aFirstURI,
                                          nsIChannel *aChannel,
                                          char       **aCookie)
 {
-  GetCookieInternal(aHostURI, aFirstURI, aChannel, PR_TRUE, aCookie);
+  GetCookieInternal(aHostURI, aChannel, PR_TRUE, aCookie);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieString(nsIURI     *aHostURI,
                                  nsIPrompt  *aPrompt,
                                  const char *aCookieHeader,
                                  nsIChannel *aChannel)
 {
-  // try to determine first party URI
-  nsCOMPtr<nsIURI> firstURI;
-
-  if (aChannel) {
-    nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
-    if (httpInternal)
-      httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
-  }
-
-  return SetCookieStringInternal(aHostURI, firstURI, aPrompt, aCookieHeader, nsnull, aChannel, PR_FALSE);
+  return SetCookieStringInternal(aHostURI, aPrompt, aCookieHeader, nsnull, aChannel, PR_FALSE);
 }
 
 NS_IMETHODIMP
 nsCookieService::SetCookieStringFromHttp(nsIURI     *aHostURI,
                                          nsIURI     *aFirstURI,
                                          nsIPrompt  *aPrompt,
                                          const char *aCookieHeader,
                                          const char *aServerTime,
                                          nsIChannel *aChannel) 
 {
-  return SetCookieStringInternal(aHostURI, aFirstURI, aPrompt, aCookieHeader, aServerTime, aChannel, PR_TRUE);
+  return SetCookieStringInternal(aHostURI, aPrompt, aCookieHeader, aServerTime, aChannel, PR_TRUE);
 }
 
 nsresult
 nsCookieService::SetCookieStringInternal(nsIURI     *aHostURI,
-                                         nsIURI     *aFirstURI,
                                          nsIPrompt  *aPrompt,
                                          const char *aCookieHeader,
                                          const char *aServerTime,
                                          nsIChannel *aChannel,
                                          PRBool      aFromHttp) 
 {
   if (!aHostURI) {
     COOKIE_LOGFAILURE(SET_COOKIE, nsnull, aCookieHeader, "host URI is null");
     return NS_OK;
   }
 
   // check default prefs
-  PRUint32 cookieStatus = CheckPrefs(aHostURI, aFirstURI, aChannel, aCookieHeader);
+  PRUint32 cookieStatus = CheckPrefs(aHostURI, aChannel, aCookieHeader);
   // fire a notification if cookie was rejected (but not if there was an error)
   switch (cookieStatus) {
   case STATUS_REJECTED:
     NotifyRejected(aHostURI);
   case STATUS_REJECTED_WITH_ERROR:
     return NS_OK;
   }
 
@@ -1114,30 +1095,29 @@ nsCookieService::ImportCookies(nsIFile *
  * private GetCookie/SetCookie helpers
  ******************************************************************************/
 
 // helper function for GetCookieList
 static inline PRBool ispathdelimiter(char c) { return c == '/' || c == '?' || c == '#' || c == ';'; }
 
 void
 nsCookieService::GetCookieInternal(nsIURI      *aHostURI,
-                                   nsIURI      *aFirstURI,
                                    nsIChannel  *aChannel,
                                    PRBool       aHttpBound,
                                    char       **aCookie)
 {
   *aCookie = nsnull;
 
   if (!aHostURI) {
     COOKIE_LOGFAILURE(GET_COOKIE, nsnull, nsnull, "host URI is null");
     return;
   }
 
   // check default prefs
-  PRUint32 cookieStatus = CheckPrefs(aHostURI, aFirstURI, aChannel, nsnull);
+  PRUint32 cookieStatus = CheckPrefs(aHostURI, aChannel, nsnull);
   // for GetCookie(), we don't fire rejection notifications.
   switch (cookieStatus) {
   case STATUS_REJECTED:
   case STATUS_REJECTED_WITH_ERROR:
     return;
   }
 
   // get host and path from the nsIURI
@@ -1724,25 +1704,21 @@ nsCookieService::ParseAttributes(nsDepen
  * nsCookieService impl:
  * private domain & permission compliance enforcement functions
  ******************************************************************************/
 
 PRBool
 nsCookieService::IsForeign(nsIURI *aHostURI,
                            nsIURI *aFirstURI)
 {
-  // if aFirstURI is null, default to not foreign
-  if (!aFirstURI) {
-    return PR_FALSE;
-  }
-
   // Get hosts
   nsCAutoString currentHost, firstHost;
   if (NS_FAILED(aHostURI->GetAsciiHost(currentHost)) ||
       NS_FAILED(aFirstURI->GetAsciiHost(firstHost))) {
+    // assume foreign
     return PR_TRUE;
   }
   // trim trailing dots
   currentHost.Trim(".");
   firstHost.Trim(".");
 
   // fast path: check if the two hosts are identical.
   // this also covers two special cases:
@@ -1753,110 +1729,81 @@ nsCookieService::IsForeign(nsIURI *aHost
   // error if the URI is an IP address.
   // 2) we also need this for the (rare) case where the site is actually an eTLD,
   // e.g. http://co.tv; GetBaseDomain() will throw an error and we might
   // erroneously think currentHost is foreign. so we consider this case non-
   // foreign only if the hosts exactly match.
   if (firstHost.Equals(currentHost))
     return PR_FALSE;
 
-  // chrome URLs are never foreign (otherwise sidebar cookies won't work).
-  // eventually we want to have a protocol whitelist here,
-  // _or_ do something smart with nsIProtocolHandler::protocolFlags.
-  PRBool isChrome = PR_FALSE;
-  nsresult rv = aFirstURI->SchemeIs("chrome", &isChrome);
-  if (NS_SUCCEEDED(rv) && isChrome) {
-    return PR_FALSE;
-  }
-
   // get the base domain for the originating URI.
   // e.g. for "images.bbc.co.uk", this would be "bbc.co.uk".
   nsCAutoString baseDomain;
-  rv = mTLDService->GetBaseDomain(aFirstURI, 0, baseDomain);
+  nsresult rv = mTLDService->GetBaseDomain(aFirstURI, 0, baseDomain);
   if (NS_FAILED(rv)) {
     // URI is an IP, eTLD, or something else went wrong - assume foreign
     return PR_TRUE;
   }  
   baseDomain.Trim(".");
 
   // ensure the host domain is derived from the base domain.
   // we prepend dots before the comparison to ensure e.g.
   // "mybbc.co.uk" isn't matched as a superset of "bbc.co.uk".
   currentHost.Insert(NS_LITERAL_CSTRING("."), 0);
   baseDomain.Insert(NS_LITERAL_CSTRING("."), 0);
   return !StringEndsWith(currentHost, baseDomain);
 }
 
 PRUint32
 nsCookieService::CheckPrefs(nsIURI     *aHostURI,
-                            nsIURI     *aFirstURI,
                             nsIChannel *aChannel,
                             const char *aCookieHeader)
 {
-  // pref tree:
-  // 0) get the scheme strings from the two URI's
-  // 1) disallow ftp
-  // 2) disallow mailnews, if pref set
-  // 3) perform a permissionlist lookup to see if an entry exists for this host
-  //    (a match here will override defaults in 4)
-  // 4) go through enumerated permissions to see which one we have:
-  // -> cookies disabled: return
-  // -> dontacceptforeign: check if cookie is foreign
-
-  // first, get the URI scheme for further use
-  // if GetScheme fails on aHostURI, reject; aFirstURI is optional, so failing is ok
-  nsCAutoString currentURIScheme, firstURIScheme;
-  nsresult rv, rv2 = NS_OK;
-  rv = aHostURI->GetScheme(currentURIScheme);
-  if (aFirstURI) {
-    rv2 = aFirstURI->GetScheme(firstURIScheme);
-  }
-  if (NS_FAILED(rv) || NS_FAILED(rv2)) {
-    COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "couldn't get scheme of host URI");
-    return STATUS_REJECTED_WITH_ERROR;
-  }
+  nsresult rv;
 
   // don't let ftp sites get/set cookies (could be a security issue)
-  if (currentURIScheme.EqualsLiteral("ftp")) {
+  PRBool ftp;
+  if (NS_SUCCEEDED(aHostURI->SchemeIs("ftp", &ftp)) && ftp) {
     COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "ftp sites cannot read cookies");
     return STATUS_REJECTED_WITH_ERROR;
   }
 
   // check the permission list first; if we find an entry, it overrides
   // default prefs. see bug 184059.
   if (mPermissionService) {
     nsCookieAccess access;
-    rv = mPermissionService->CanAccess(aHostURI, aFirstURI, aChannel, &access);
+    rv = mPermissionService->CanAccess(aHostURI, aChannel, &access);
 
     // if we found an entry, use it
     if (NS_SUCCEEDED(rv)) {
       switch (access) {
       case nsICookiePermission::ACCESS_DENY:
         COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "cookies are blocked for this site");
         return STATUS_REJECTED;
 
       case nsICookiePermission::ACCESS_ALLOW:
         return STATUS_ACCEPTED;
       }
     }
   }
 
-  // check default prefs - go thru enumerated permissions
+  // check default prefs
   if (mCookiesPermissions == BEHAVIOR_REJECT) {
     COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "cookies are disabled");
     return STATUS_REJECTED;
 
   } else if (mCookiesPermissions == BEHAVIOR_REJECTFOREIGN) {
-    // check if cookie is foreign.
-    // if aFirstURI is null, allow by default
+    // check if cookie is foreign
+    if (!mPermissionService)
+      return STATUS_REJECTED;
 
-    // note: this can be circumvented if we have http redirects within html,
-    // since the documentURI attribute isn't always correctly
-    // passed to the redirected channels. (or isn't correctly set in the first place)
-    if (IsForeign(aHostURI, aFirstURI)) {
+    nsCOMPtr<nsIURI> firstURI;
+    rv = mPermissionService->GetOriginatingURI(aChannel, getter_AddRefs(firstURI));
+
+    if (NS_FAILED(rv) || IsForeign(aHostURI, firstURI)) {
       COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "originating server test failed");
       return STATUS_REJECTED;
     }
   }
 
   // if nothing has complained, accept cookie
   return STATUS_ACCEPTED;
 }
--- a/netwerk/cookie/src/nsCookieService.h
+++ b/netwerk/cookie/src/nsCookieService.h
@@ -49,19 +49,16 @@
 #include "nsCookie.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 
 struct nsCookieAttributes;
 struct nsListIter;
 struct nsEnumerationData;
 
-class nsAutoVoidArray;
-
-class nsIPrefBranch;
 class nsICookiePermission;
 class nsIEffectiveTLDService;
 class nsIPrefBranch;
 class nsIObserverService;
 class nsIURI;
 class nsIChannel;
 class mozIStorageConnection;
 class mozIStorageStatement;
@@ -163,27 +160,27 @@ class nsCookieService : public nsICookie
     static nsCookieService*       GetSingleton();
     nsresult                      Init();
 
   protected:
     void                          PrefChanged(nsIPrefBranch *aPrefBranch);
     nsresult                      InitDB();
     nsresult                      CreateTable();
     nsresult                      Read();
-    void                          GetCookieInternal(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie);
-    nsresult                      SetCookieStringInternal(nsIURI *aHostURI, nsIURI *aFirstURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp);
+    void                          GetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, PRBool aHttpBound, char **aCookie);
+    nsresult                      SetCookieStringInternal(nsIURI *aHostURI, nsIPrompt *aPrompt, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, PRBool aFromHttp);
     PRBool                        SetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, nsDependentCString &aCookieHeader, PRInt64 aServerTime, PRBool aFromHttp);
     void                          AddInternal(nsCookie *aCookie, PRInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
     void                          RemoveCookieFromList(nsListIter &aIter);
     PRBool                        AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB = PR_TRUE);
     void                          UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed);
     static PRBool                 GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, PRBool &aEqualsFound);
     static PRBool                 ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
     PRBool                        IsForeign(nsIURI *aHostURI, nsIURI *aFirstURI);
-    PRUint32                      CheckPrefs(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, const char *aCookieHeader);
+    PRUint32                      CheckPrefs(nsIURI *aHostURI, nsIChannel *aChannel, const char *aCookieHeader);
     PRBool                        CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI);
     static PRBool                 CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
     static PRBool                 GetExpiry(nsCookieAttributes &aCookie, PRInt64 aServerTime, PRInt64 aCurrentTime);
     void                          RemoveAllFromMemory();
     void                          RemoveExpiredCookies(PRInt64 aCurrentTime);
     PRBool                        FindCookie(const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
     void                          FindOldestCookie(nsEnumerationData &aData);
     PRUint32                      CountCookiesFromHostInternal(const nsACString &aHost, nsEnumerationData &aData);
--- a/netwerk/protocol/http/src/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/src/nsHttpChannel.cpp
@@ -595,17 +595,20 @@ nsHttpChannel::SetupTransaction()
         return NS_ERROR_OUT_OF_MEMORY;
     NS_ADDREF(mTransaction);
 
     nsCOMPtr<nsIAsyncInputStream> responseStream;
     rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead,
                             mUploadStream, mUploadStreamHasHeaders,
                             NS_GetCurrentThread(), callbacks, this,
                             getter_AddRefs(responseStream));
-    if (NS_FAILED(rv)) return rv;
+    if (NS_FAILED(rv)) {
+        NS_RELEASE(mTransaction);
+        return rv;
+    }
 
     rv = nsInputStreamPump::Create(getter_AddRefs(mTransactionPump),
                                    responseStream);
     return rv;
 }
 
 void
 nsHttpChannel::AddCookiesToRequest()
--- a/netwerk/test/TestCookie.cpp
+++ b/netwerk/test/TestCookie.cpp
@@ -198,18 +198,19 @@ PrintResult(const PRBool aResult[], PRUi
     }
     return !failed;
 }
 
 void
 InitPrefs(nsIPrefBranch *aPrefBranch)
 {
     // init some relevant prefs, so the tests don't go awry.
-    // we use the most restrictive set of prefs we can.
-    aPrefBranch->SetIntPref(kCookiesPermissions, 1); // 'reject foreign'
+    // we use the most restrictive set of prefs we can;
+    // however, we don't test third party blocking here.
+    aPrefBranch->SetIntPref(kCookiesPermissions, 0); // accept all
     aPrefBranch->SetBoolPref(kCookiesDisabledForMailNews, PR_TRUE);
     aPrefBranch->SetBoolPref(kCookiesLifetimeEnabled, PR_TRUE);
     aPrefBranch->SetIntPref(kCookiesLifetimeCurrentSession, 0);
     aPrefBranch->SetIntPref(kCookiesLifetimeDays, 1);
     aPrefBranch->SetBoolPref(kCookiesAskPermission, PR_FALSE);
 }
 
 class ScopedXPCOM
@@ -507,86 +508,16 @@ main(PRInt32 argc, char *argv[])
       rv[7] = CheckResult(cookie.get(), MUST_NOT_CONTAIN, "test=different");
       SetACookie(cookieService, "http://multiple.cookies/", nsnull,  "newtest=dead; max-age=0", nsnull);
       GetACookie(cookieService, "http://multiple.cookies/", nsnull, getter_Copies(cookie));
       rv[8] = CheckResult(cookie.get(), MUST_BE_NULL);
 
       allTestsPassed = PrintResult(rv, 9) && allTestsPassed;
 
 
-      // *** foreign cookie tests
-      printf("*** Beginning foreign cookie tests...\n");
-
-      // test the blocking of foreign cookies, under various circumstances.
-      // order of URI arguments is hostURI, firstURI
-      SetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[0] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://weather.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://notweather.yahoo.com/", "http://sport.yahoo.com/", getter_Copies(cookie));
-      rv[1] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://moose.yahoo.com/", "http://canada.yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://sport.yahoo.com/", getter_Copies(cookie));
-      rv[2] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://sport.yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[3] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://jack.yahoo.com/", "http://jill.yahoo.com/", "test=foreign; domain=.yahoo.com; max-age=0", nsnull);
-      GetACookie(cookieService, "http://jane.yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[4] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      SetACookie(cookieService, "http://moose.yahoo.com/", "http://foo.moose.yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[5] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://foo.bar.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[6] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      SetACookie(cookieService, "http://foo.bar.yahoo.com/", "http://yahoo.com/", "test=foreign; domain=.yahoo.com; max-age=0", nsnull);
-      GetACookie(cookieService, "http://yahoo.com/", "http://yahoo.com/", getter_Copies(cookie));
-      rv[7] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      // test handling of IP addresses by the foreign blocking algo
-      SetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", "test=foreign; domain=192.168.54.33", nsnull);
-      GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie));
-      rv[8] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://192.168.54.33./", "http://.192.168.54.33../", getter_Copies(cookie));
-      rv[9] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://192.168.54.33/", nsnull, getter_Copies(cookie));
-      rv[10] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://192.168.54.33/", "http://148.168.54.33", getter_Copies(cookie));
-      rv[11] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", "test=foreign; domain=192.168.54.33; max-age=0", nsnull);
-      GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie));
-      rv[12] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://192.168.54.33/", "http://148.168.54.33/", "test=foreign; domain=192.168.54.33", nsnull);
-      GetACookie(cookieService, "http://192.168.54.33/", "http://192.168.54.33/", getter_Copies(cookie));
-      rv[13] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      // test the case where the host is an eTLD, e.g. http://co.tv/ (a legitimate site)
-      SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign; domain=.co.uk", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      // should be rejected, can't set a domain cookie for .co.uk
-      rv[14] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      // should be allowed, hostURI == firstURI and it's not a domain cookie
-      rv[15] = CheckResult(cookie.get(), MUST_EQUAL, "test=foreign");
-      GetACookie(cookieService, "http://oblivious.co.uk/", nsnull, getter_Copies(cookie));
-      rv[16] = CheckResult(cookie.get(), MUST_BE_NULL);
-      // remove cookie
-      SetACookie(cookieService, "http://co.uk/", "http://co.uk/", "test=foreign; max-age=0", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      rv[17] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://co.uk/", "http://evil.co.uk/", "test=foreign", nsnull);
-      GetACookie(cookieService, "http://co.uk/", "http://co.uk/", getter_Copies(cookie));
-      // should be rejected, hostURI != firstURI and hostURI is an eTLD
-      rv[18] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      allTestsPassed = PrintResult(rv, 19) && allTestsPassed;
-
-
       // *** parser tests
       printf("*** Beginning parser tests...\n");
 
       // test the cookie header parser, under various circumstances.
       SetACookie(cookieService, "http://parser.test/", nsnull, "test=parser; domain=.parser.test; ;; ;=; ,,, ===,abc,=; abracadabra! max-age=20;=;;", nsnull);
       GetACookie(cookieService, "http://parser.test/", nsnull, getter_Copies(cookie));
       rv[0] = CheckResult(cookie.get(), MUST_EQUAL, "test=parser");
       SetACookie(cookieService, "http://parser.test/", nsnull, "test=parser; domain=.parser.test; max-age=0", nsnull);
@@ -634,25 +565,17 @@ main(PRInt32 argc, char *argv[])
       GetACookie(cookieService, "mailbox://mail.co.uk/", nsnull, getter_Copies(cookie));
       rv[2] = CheckResult(cookie.get(), MUST_BE_NULL);
       GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
       rv[3] = CheckResult(cookie.get(), MUST_EQUAL, "test=mailnews");
       SetACookie(cookieService, "http://mail.co.uk/", nsnull, "test=mailnews; max-age=0", nsnull);
       GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
       rv[4] = CheckResult(cookie.get(), MUST_BE_NULL);
 
-      // test non-null firstURI's, i) from mailnews ii) not from mailnews
-      SetACookie(cookieService, "mailbox://mail.co.uk/", "http://mail.co.uk/", "test=mailnews", nsnull);
-      GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
-      rv[5] = CheckResult(cookie.get(), MUST_BE_NULL);
-      SetACookie(cookieService, "http://mail.co.uk/", "mailbox://mail.co.uk/", "test=mailnews", nsnull);
-      GetACookie(cookieService, "http://mail.co.uk/", nsnull, getter_Copies(cookie));
-      rv[6] = CheckResult(cookie.get(), MUST_BE_NULL);
-
-      allTestsPassed = PrintResult(rv, 7) && allTestsPassed;
+      allTestsPassed = PrintResult(rv, 5) && allTestsPassed;
 
 
       // *** path ordering tests
       printf("*** Beginning path ordering tests...\n");
 
       // test that cookies are returned in path order - longest to shortest.
       // if the header doesn't specify a path, it's taken from the host URI.
       SetACookie(cookieService, "http://multi.path.tests/", nsnull, "test1=path; path=/one/two/three", nsnull);
--- a/other-licenses/bsdiff/Makefile.in
+++ b/other-licenses/bsdiff/Makefile.in
@@ -42,17 +42,19 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 # This program is output to dist/host/bin because it is only needed by the
 # build system and is not intended to be included in Mozilla distributions.
 HOST_PROGRAM = mbsdiff$(BIN_SUFFIX)
 HOST_CSRCS = bsdiff.c
-HOST_LIBS += $(DEPTH)/modules/libbz2/src/$(LIB_PREFIX)bz2.$(LIB_SUFFIX)
+HOST_LIBS += $(BZ2_LIBS)
 
 ifeq (WINNT,$(OS_ARCH))
 HOST_EXTRA_LIBS += $(call EXPAND_LIBNAME,Ws2_32)
 endif
 
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/mozapps/update/src/updater
 
 include $(topsrcdir)/config/rules.mk
+
+CXXFLAGS += $(BZ2_CFLAGS)
--- a/parser/htmlparser/Makefile.in
+++ b/parser/htmlparser/Makefile.in
@@ -42,15 +42,11 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= htmlparser
 DIRS		= public src
 
 ifdef ENABLE_TESTS
 TOOL_DIRS	+= tests
-
-ifndef MOZ_ENABLE_LIBXUL
-TOOL_DIRS	+= robot
-endif
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/components/feeds/src/FeedProcessor.js
+++ b/toolkit/components/feeds/src/FeedProcessor.js
@@ -1416,16 +1416,19 @@ FeedProcessor.prototype = {
     this._reader.parseAsync(requestObserver);
   },
 
   // nsIStreamListener 
 
   // The XMLReader will throw sensible exceptions if these get called
   // out of order.
   onStartRequest: function FP_onStartRequest(request, context) {
+    var channel = request.QueryInterface(Ci.nsIChannel);
+    if (channel)
+      channel.contentType = "application/xml";
     this._reader.onStartRequest(request, context);
   },
 
   onStopRequest: function FP_onStopRequest(request, context, statusCode) {
     try {
       this._reader.onStopRequest(request, context, statusCode);
     }
     finally {
--- a/toolkit/components/passwordmgr/src/storage-Legacy.js
+++ b/toolkit/components/passwordmgr/src/storage-Legacy.js
@@ -695,17 +695,17 @@ LoginManagerStorage_legacy.prototype = {
          *       aLogin.password.
          */
 
         // closures in cleanupURL
         var ioService = this._ioService;
         var log = this.log;
 
         function cleanupURL(aURL) {
-            var newURL, username = null;
+            var newURL, username = null, pathname = "";
 
             try {
                 var uri = ioService.newURI(aURL, null, null);
 
                 var scheme = uri.scheme;
                 newURL = scheme + "://" + uri.host;
 
                 // If the URL explicitly specified a port, only include it when
@@ -715,71 +715,89 @@ LoginManagerStorage_legacy.prototype = {
                     var handler = ioService.getProtocolHandler(scheme);
                     if (port != handler.defaultPort)
                         newURL += ":" + port;
                 }
 
                 // Could be a channel login with a username. 
                 if (scheme != "http" && scheme != "https" && uri.username)
                     username = uri.username;
-                
+
+                if (uri.path != "/")
+                    pathname = uri.path;
+
             } catch (e) {
-                log("Can't cleanup URL: " + aURL);
+                log("Can't cleanup URL: " + aURL + " e: " + e);
                 newURL = aURL;
             }
 
             if (newURL != aURL)
                 log("2E upgrade: " + aURL + " ---> " + newURL);
 
-            return [newURL, username];
+            return [newURL, username, pathname];
         }
 
+        const isMailNews = /^(ldaps?|smtp|imap|news|mailbox):\/\//;
+
+        // Old mailnews logins were protocol logins with a username/password
+        // field name set.
         var isFormLogin = (aLogin.formSubmitURL ||
                            aLogin.usernameField ||
-                           aLogin.passwordField);
+                           aLogin.passwordField) &&
+                          !isMailNews.test(aLogin.hostname);
 
-        var [hostname, username] = cleanupURL(aLogin.hostname);
+        var [hostname, username, pathname] = cleanupURL(aLogin.hostname);
         aLogin.hostname = hostname;
 
         // If a non-HTTP URL contained a username, it wasn't stored in the
         // encrypted username field (which contains an encrypted empty value)
         // (Don't do this if it's a form login, though.)
         if (username && !isFormLogin) {
             var [encUsername, userCanceled] = this._encrypt(username);
             if (!userCanceled)
                 aLogin.wrappedJSObject.encryptedUsername = encUsername;
         }
 
 
         if (aLogin.formSubmitURL) {
-            [hostname, username] = cleanupURL(aLogin.formSubmitURL);
+            [hostname, username, pathname] = cleanupURL(aLogin.formSubmitURL);
             aLogin.formSubmitURL = hostname;
             // username, if any, ignored.
         }
 
 
         /*
          * For logins stored from non-HTTP channels
          *    - Set httpRealm so they don't look like form logins
          *     "ftp://site.com" --> "ftp://site.com (ftp://site.com)"
          *
          * Tricky: Form logins and non-HTTP channel logins are stored in the
          * same format, and we don't want to add a realm to a form login.
          * Form logins have field names, so only update the realm if there are
          * no field names set. [Any login with a http[s]:// hostname is always
          * a form login, so explicitly ignore those just to be safe.]
-         *
-         * Bug 403790: mail entries (imap://, ldaps://, mailbox:// smtp:// have
-         * fieldnames set to "\=username=\" and "\=password=\" (non-escaping
-         * backslash). More work is needed to upgrade these properly.
          */
         const isHTTP = /^https?:\/\//;
+        const isLDAP = /^ldaps?:\/\//;
         if (!isHTTP.test(aLogin.hostname) && !isFormLogin) {
-            aLogin.httpRealm = aLogin.hostname;
+            // LDAP logins need to keep the path.
+            if (isLDAP.test(aLogin.hostname))
+                aLogin.httpRealm = aLogin.hostname + pathname;
+            else
+                aLogin.httpRealm = aLogin.hostname;
+
             aLogin.formSubmitURL = null;
+
+            // Null out the form items because mailnews will no longer treat
+            // or expect these as form logins
+            if (isMailNews.test(aLogin.hostname)) {
+                aLogin.usernameField = "";
+                aLogin.passwordField = "";
+            }
+
             this.log("2E upgrade: set empty realm to " + aLogin.httpRealm);
         }
 
         return upgradedLogins;
     },
 
 
     /*
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/unit/data/signons-403790.txt
@@ -0,0 +1,14 @@
+#2c
+.
+mailbox://bugzilla@localhost
+\=username=\
+~
+*\=password=\
+~dGVzdHBhc3Mx
+.
+ldap://localhost1:389/dc=test
+\=username=\
+~
+*\=password=\
+~dGVzdHBhc3My
+.
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/unit/test_storage_legacy_4.js
@@ -0,0 +1,131 @@
+/*
+ * Test suite for storage-Legacy.js -- mailnews specific tests.
+ *
+ * This test interfaces directly with the legacy login storage module,
+ * bypassing the normal login manager usage.
+ *
+ */
+
+const Cm = Components.manager;
+const BASE_CONTRACTID = "@mozilla.org/network/protocol;1?name=";
+const LDAPPH_CID = Components.ID("{08eebb58-8d1a-4ab5-9fca-e35372697828}");
+const MAILBOXPH_CID = Components.ID("{edb1dea3-b226-405a-b93d-2a678a68a198}");
+
+function genericProtocolHandler(scheme, defaultPort) {
+    this.scheme = scheme;
+    this.defaultPort = defaultPort;
+}
+
+genericProtocolHandler.prototype = {
+    scheme: "",
+    defaultPort: 0,
+
+    QueryInterface: function gph_QueryInterface(aIID) {
+        if (!aIID.equals(Ci.nsISupports) &&
+            !aIID.equals(Ci.nsIProtocolHandler)) {
+            throw Cr.NS_ERROR_NO_INTERFACE;
+        }
+        return this;
+    },
+
+    get protocolFlags() {
+        throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+    },
+
+    newURI: function gph_newURI(aSpec, anOriginalCharset, aBaseURI) {
+        var uri = Components.classes["@mozilla.org/network/standard-url;1"].
+                             createInstance(Ci.nsIStandardURL);
+
+        uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, this.defaultPort, aSpec,
+                  anOriginalCharset, aBaseURI);
+
+        return uri;
+    },
+
+    newChannel: function gph_newChannel(aUri) {
+        throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+    },
+
+    allowPort: function gph_allowPort(aPort, aScheme) {
+        return false;
+    }
+}
+
+function generateFactory(protocol, defaultPort)
+{
+    return {
+        createInstance: function (outer, iid) {
+            if (outer != null)
+                throw Components.results.NS_ERROR_NO_AGGREGATION;
+
+            return (new genericProtocolHandler(protocol, defaultPort)).
+                    QueryInterface(iid);
+        }
+    };
+}
+
+function run_test() {
+Cm.nsIComponentRegistrar.registerFactory(LDAPPH_CID, "LDAPProtocolFactory",
+                                         BASE_CONTRACTID + "ldap",
+                                         generateFactory("ldap", 389));
+Cm.nsIComponentRegistrar.registerFactory(MAILBOXPH_CID,
+                                         "MailboxProtocolFactory",
+                                         BASE_CONTRACTID + "mailbox",
+                                         generateFactory("mailbox", 0));
+
+try {
+/* ========== 0 ========== */
+var testnum = 0;
+var testdesc = "Initial connection to storage module"
+
+var storage = Cc["@mozilla.org/login-manager/storage/legacy;1"].
+              createInstance(Ci.nsILoginManagerStorage);
+if (!storage)
+    throw "Couldn't create storage instance.";
+
+// Create a couple of dummy users to match what we expect to be translated
+// from the input file.
+var dummyuser1 = Cc["@mozilla.org/login-manager/loginInfo;1"].
+                 createInstance(Ci.nsILoginInfo);
+var dummyuser2 = Cc["@mozilla.org/login-manager/loginInfo;1"].
+                 createInstance(Ci.nsILoginInfo);
+var dummyuser3 = Cc["@mozilla.org/login-manager/loginInfo;1"].
+                 createInstance(Ci.nsILoginInfo);
+
+
+dummyuser1.init("mailbox://localhost", null, "mailbox://localhost",
+    "bugzilla", "testpass1", "", "");
+
+dummyuser2.init("ldap://localhost1", null,
+    "ldap://localhost1/dc=test",
+    "", "testpass2", "", "");
+
+dummyuser3.init("http://dummyhost.mozilla.org", "", null,
+    "testuser1", "testpass1", "put_user_here", "put_pw_here");
+
+/*
+ * ---------------------- Bug 403790 ----------------------
+ * Migrating mailnews style username/passwords
+ */
+
+/* ========== 1 ========== */
+testnum++;
+
+testdesc = "checking reading of mailnews-like old logins";
+LoginTest.initStorage(storage, INDIR, "signons-403790.txt",
+                      OUTDIR, "output-403790.txt");
+LoginTest.checkStorageData(storage, [], [dummyuser1, dummyuser2]);
+
+storage.addLogin(dummyuser3); // trigger a write
+LoginTest.checkStorageData(storage, [], [dummyuser1, dummyuser2, dummyuser3]);
+
+testdesc = "[flush and reload for verification]";
+LoginTest.initStorage(storage, OUTDIR, "output-403790.txt");
+LoginTest.checkStorageData(storage, [], [dummyuser1, dummyuser2, dummyuser3]);
+
+/* ========== end ========== */
+} catch (e) {
+    throw ("FAILED in test #" + testnum + " -- " + testdesc + ": " + e);
+}
+
+};
--- a/toolkit/components/places/tests/chrome/Makefile.in
+++ b/toolkit/components/places/tests/chrome/Makefile.in
@@ -42,22 +42,25 @@ VPATH		= @srcdir@
 relativesrcdir  = toolkit/components/places/tests/chrome
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _HTTP_FILES	= \
 		sample_feed.atom \
 		bad_links.atom \
+		rss_as_html.rss \
+		rss_as_html.rss^headers^ \
 		$(NULL)
 
 _CHROME_FILES	= \
 		test_371798.xul \
 		test_342484.xul \
 		test_341972a.xul \
+		test_381357.xul \
 		$(NULL)
 
 libs:: $(_HTTP_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
 
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/chrome/rss_as_html.rss
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
+<channel>
+<title>sadfasdfasdfasfasdf</title>
+<link>http://www.example.com</link>
+<description>asdfasdfasdf.example.com</description>
+<language>de</language>
+<copyright>asdfasdfasdfasdf</copyright>
+<lastBuildDate>Tue, 11 Mar 2008 18:52:52 +0100</lastBuildDate>
+<docs>http://blogs.law.harvard.edu/tech/rss</docs>
+<ttl>10</ttl>
+<item>
+<title>The First Title</title>
+<link>http://www.example.com/index.html</link>
+<pubDate>Tue, 11 Mar 2008 18:24:43 +0100</pubDate>
+<content:encoded>
+<![CDATA[
+<p>
+askdlfjas;dfkjas;fkdj
+</p>
+]]>
+</content:encoded>
+<description>aklsjdhfasdjfahasdfhj</description>
+<guid>http://foo.example.com/asdfasdf</guid>
+</item>
+</channel>
+</rss>
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/chrome/rss_as_html.rss^headers^
@@ -0,0 +1,2 @@
+HTTP 200 OK
+Content-Type: text/html
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/chrome/test_381357.xul
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet
+  href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<window title="Add Livemarks from RSS feed served as text/html"
+  xmlns:html="http://www.w3.org/1999/xhtml"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+   src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+   src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <body xmlns="http://www.w3.org/1999/xhtml" />
+
+<script type="application/javascript">
+<![CDATA[
+/*
+ Test loading feeds with text/html 
+ */
+SimpleTest.waitForExplicitFinish();
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+var iosvc = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+
+function uri(spec) {
+  return iosvc.newURI(spec, null, null);
+}
+
+var lmsvc = Cc["@mozilla.org/browser/livemark-service;2"].
+              getService(Ci.nsILivemarkService);
+var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
+              getService(Ci.nsINavBookmarksService);
+var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
+                getService(Ci.nsINavHistoryService);
+
+var toolbarFolderId = bmsvc.toolbarFolder;
+
+var observer =
+{
+  QueryInterface: function(iid) {
+    if (iid.equals(Ci.nsINavBookmarkObserver) ||
+        iid.equals(Ci.nsISupports))
+      return this;
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  },
+
+  // nsINavBookmarkObserve
+  onBeginUpdateBatch: function(){},
+  onEndUpdateBatch: function(){
+  },
+  onItemAdded: function(itemId, folder, index) {
+    var title = bmsvc.getItemTitle(itemId);
+    if (title == "The First Title") {
+      ok(true, "Item with title loaded");
+      bmsvc.removeObserver(this);
+      SimpleTest.finish();
+    }
+  },
+  onItemRemoved: function(itemId, folder, index){},
+  onItemChanged: function(itemId, property, isAnnotationProperty, value){},
+  onItemVisited: function(itemId, aVisitID, time){},
+  onItemMoved: function(itemId, oldParent, oldIndex, newParent, newIndex){},
+
+};
+
+var root = bmsvc.bookmarksRoot;
+const FEEDSPEC = "http://localhost:8888/tests/toolkit/components/places/tests/chrome/rss_as_html.rss";
+
+gLivemarkId = lmsvc.createLivemarkFolderOnly(toolbarFolderId, "foo",
+                                             uri("http:/localhost/"),
+                                             uri(FEEDSPEC), -1);
+bmsvc.addObserver(observer, false);
+lmsvc.reloadLivemarkFolder(gLivemarkId);
+]]>
+</script>
+
+</window>
--- a/toolkit/content/tests/widgets/test_popup_button.xul
+++ b/toolkit/content/tests/widgets/test_popup_button.xul
@@ -10,17 +10,17 @@
   <title>Menu Button Popup Tests</title>
   <script type="application/javascript" src="/MochiKit/packed.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>      
 
 <script>
 SimpleTest.waitForExplicitFinish();
 function runTest()
 {
-  window.open("window_popup_button.xul", "_blank", "width=600,height=700");
+  window.open("window_popup_button.xul", "_blank", "width=700,height=700");
 }
 </script>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
 <p id="display">
 </p>
 <div id="content" style="display: none">
 </div>
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -740,17 +740,17 @@ panel[type="autocomplete"] {
 textbox[type="autocomplete"] {
   -moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete");
 }
 
 panel[type="autocomplete"] {
   -moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete-result-popup");
 }
 
-panel[type="rich-autocomplete"] {
+panel[type="autocomplete-richlistbox"] {
   -moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup");
 }
 
 .autocomplete-tree {
   -moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete-tree");
   -moz-user-focus: ignore;
 }
 
--- a/toolkit/crashreporter/client/crashreporter_osx.h
+++ b/toolkit/crashreporter/client/crashreporter_osx.h
@@ -81,17 +81,17 @@
 }
 
 - (void)showCrashUI:(const std::string&)dumpfile
     queryParameters:(const StringTable&)queryParameters
             sendURL:(const std::string&)sendURL;
 - (void)showErrorUI:(const std::string&)dumpfile;
 - (void)showReportInfo;
 - (void)maybeSubmitReport;
-- (void)closeMeDown;
+- (void)closeMeDown:(id)unused;
 
 - (IBAction)submitReportClicked:(id)sender;
 - (IBAction)viewReportClicked:(id)sender;
 - (IBAction)viewReportOkClicked:(id)sender;
 - (IBAction)closeClicked:(id)sender;
 - (IBAction)restartClicked:(id)sender;
 - (IBAction)includeURLClicked:(id)sender;
 - (IBAction)emailMeClicked:(id)sender;
--- a/toolkit/crashreporter/client/crashreporter_osx.mm
+++ b/toolkit/crashreporter/client/crashreporter_osx.mm
@@ -231,17 +231,17 @@ static bool RestartApplication()
     [mProgressIndicator startAnimation:self];
     gDidTrySend = true;
     [self sendReport];
   } else {
     [NSApp terminate:self];
   }
 }
 
--(void)closeMeDown
+- (void)closeMeDown:(id)unused
 {
   [NSApp terminate:self];
 }
 
 -(IBAction)submitReportClicked:(id)sender
 {
   [self updateSubmit];
 }
--- a/toolkit/mozapps/downloads/tests/browser/Makefile.in
+++ b/toolkit/mozapps/downloads/tests/browser/Makefile.in
@@ -47,16 +47,17 @@ include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
   browser_basic_functionality.js \
   browser_bug_394039.js \
   browser_bug_406857.js \
   browser_bug_410289.js \
   browser_bug_411172.js \
   browser_bug_412360.js \
+  browser_bug_413093.js \
   browser_bug_413985.js \
   browser_bug_416303.js \
   $(NULL)
 
 ifneq (,$(filter cocoa, $(MOZ_WIDGET_TOOLKIT)))
 _BROWSER_FILES += \
   browser_bug_411172_mac.js \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/downloads/tests/browser/browser_bug_413093.js
@@ -0,0 +1,174 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ * 
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *   Edward Lee <edward.lee@engineering.uiuc.edu>
+ *
+ * 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 bug413093obs()
+{
+  this.mDownload = null;
+  this.wasPaused = false;
+}
+bug413093obs.prototype = {
+  observe: function(aSubject, aTopic, aData)
+  {
+    if ("domwindowopened" == aTopic) {
+      let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+               getService(Ci.nsIWindowWatcher);
+      ww.unregisterNotification(this);
+
+      // If we opened before we were paused, we need to set up our proper state
+      // We also should not try to resume (we weren't paused!)
+      if (!this.wasPaused) {
+        dump("domwindowopened callback - not pausing or resuming\n");
+        this.wasPaused = true;
+        return;
+      }
+
+      dump("domwindowopened callback - resuming download\n");
+      
+      // Resume the download now that UI is up and running
+      let dm = Cc["@mozilla.org/download-manager;1"].
+                getService(Ci.nsIDownloadManager);
+      dm.resumeDownload(this.mDownload.id);
+    } else if ("timer-callback" == aTopic) {
+      this.setPref(false);
+
+      let dmui = Cc["@mozilla.org/download-manager-ui;1"].
+                 getService(Ci.nsIDownloadManagerUI);
+      ok(!dmui.visible, "Download Manager UI is not showing");
+
+      finish();
+    }
+  },
+
+  onDownloadStateChange: function(aOldState, aDownload)
+  {
+    if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_DOWNLOADING &&
+        !this.wasPaused) {
+      dump("onDownloadStateChange - pausing download\n");
+      this.wasPaused = true;
+
+      // Pause the download until the UI shows up
+      let dm = Cc["@mozilla.org/download-manager;1"].
+                getService(Ci.nsIDownloadManager);
+      dm.pauseDownload(aDownload.id);
+    }
+
+    if (aDownload.state == Ci.nsIDownloadManager.DOWNLOAD_FINISHED) {
+      aDownload.targetFile.remove(false);
+
+      let dm = Cc["@mozilla.org/download-manager;1"].
+                getService(Ci.nsIDownloadManager);
+      dm.removeListener(this);
+
+      // We have to do this on a timer so other JS stuff that handles the UI
+      // can actually catch up to us...
+      let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+      timer.init(this, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
+    }
+  },
+  onStateChange: function(a, b, c, d, e) { },
+  onProgressChange: function(a, b, c, d, e, f, g) { },
+  onSecurityChange: function(a, b, c, d) { },
+
+  setPref: function(aDoTest)
+  {
+    let prefs = Cc["@mozilla.org/preferences-service;1"].
+                getService(Ci.nsIPrefBranch);
+
+    // If we're testing, set retention to auto-remove and auto-close
+    prefs.setIntPref("browser.download.manager.retention", aDoTest ? 0 : 2);
+    prefs.setBoolPref("browser.download.manager.closeWhenDone", aDoTest);
+  }
+};
+function test()
+{
+  function addDownload() {
+    function createURI(aObj) {
+      let ios = Cc["@mozilla.org/network/io-service;1"].
+                getService(Ci.nsIIOService);
+      return (aObj instanceof Ci.nsIFile) ? ios.newFileURI(aObj) :
+                                            ios.newURI(aObj, null, null);
+    }
+
+    const nsIWBP = Ci.nsIWebBrowserPersist;
+    let persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
+                  .createInstance(Ci.nsIWebBrowserPersist);
+    persist.persistFlags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
+                           nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
+                           nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
+
+    let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
+                 getService(Ci.nsIProperties);
+    let destFile = dirSvc.get("ProfD", Ci.nsIFile);
+    destFile.append("download.result");
+    if (destFile.exists())
+      destFile.remove(false);
+
+    let src = createURI("http://example.com/httpd.js");
+    let target = createURI(destFile);
+    let tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
+    tr.init(src, target, "test download", null, Math.round(Date.now() * 1000),
+            null, persist);
+    persist.progressListener = tr;
+    persist.saveURI(src, null, null, null, null, destFile);
+  }
+
+  // First, we clear out the database
+  let dm = Cc["@mozilla.org/download-manager;1"].
+           getService(Ci.nsIDownloadManager);
+  dm.DBConnection.executeSimpleSQL("DELETE FROM moz_downloads");
+
+  // See if the DM is already open, and if it is, close it!
+  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].
+           getService(Ci.nsIWindowMediator);
+  let win = wm.getMostRecentWindow("Download:Manager");
+  if (win)
+    win.close();
+
+  let obs = new bug413093obs();
+  dm.addListener(obs);
+  obs.setPref(true);
+
+  // Start the test when the download manager window loads
+  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
+           getService(Ci.nsIWindowWatcher);
+  ww.registerNotification(obs);
+
+  addDownload();
+
+  waitForExplicitFinish();
+}
--- a/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
+++ b/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
@@ -2673,18 +2673,16 @@ ExtensionManager.prototype = {
 
   /**
    * See nsIExtensionManager.idl
    */
   start: function(commandLine) {
     var isDirty = false;
     var forceAutoReg = false;
 
-    this._showUpdatesWindow();
-
     // Somehow the component list went away, and for that reason the new one
     // generated by this function is going to result in a different compreg.
     // We must force a restart.
     var componentList = getFile(KEY_PROFILEDIR, [FILE_EXTENSION_MANIFEST]);
     if (!componentList.exists())
       forceAutoReg = true;
 
     // Check for missing manifests - e.g. missing extensions.ini, missing
@@ -2696,16 +2694,18 @@ ExtensionManager.prototype = {
 
     // Configure any items that are being installed, uninstalled or upgraded
     // by being added, removed or modified by another process. We must do this
     // on every startup since there is no way we can tell if this has happened
     // or not!
     if (this._checkForFileChanges())
       isDirty = true;
 
+    this._showUpdatesWindow();
+
     if (PendingOperations.size != 0)
       isDirty = true;
 
     // Extension Changes
     if (isDirty) {
       var needsRestart = this._finishOperations();
 
       if (forceAutoReg) {
--- a/toolkit/mozapps/update/src/updater/Makefile.in
+++ b/toolkit/mozapps/update/src/updater/Makefile.in
@@ -49,22 +49,22 @@ CPPSRCS = \
 	bspatch.cpp \
 	archivereader.cpp \
 	$(NULL)
 
 PROGRAM = updater$(BIN_SUFFIX)
 
 REQUIRES	= \
 		libmar \
-		libbz2 \
+		$(BZ2_REQUIRES) \
 		$(NULL)
 
 LIBS += \
 	$(DEPTH)/modules/libmar/src/$(LIB_PREFIX)mar.$(LIB_SUFFIX) \
-	$(DEPTH)/modules/libbz2/src/$(LIB_PREFIX)bz2.$(LIB_SUFFIX) \
+	$(BZ2_LIBS) \
 	$(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 USE_STATIC_LIBS = 1
 HAVE_PROGRESSUI = 1
 RCINCLUDE = updater.rc
 CPPSRCS += progressui_win.cpp
 OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32)
@@ -125,8 +125,10 @@ libs::
 	rm -f $(DIST)/bin/updater
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 # Pick up nsWindowsRestart.cpp
 LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre
 REQUIRES += string
 endif
+
+CXXFLAGS += $(BZ2_CFLAGS)
--- a/toolkit/mozapps/update/src/updater/updater.cpp
+++ b/toolkit/mozapps/update/src/updater/updater.cpp
@@ -133,17 +133,21 @@ void LaunchChild(int argc, char **argv);
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
 #define USE_EXECV
 #endif
 
 //-----------------------------------------------------------------------------
 
 // This variable lives in libbz2.  It's declared in bzlib_private.h, so we just
 // declare it here to avoid including that entire header file.
+#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+extern "C"  __attribute__((visibility("default"))) unsigned int BZ2_crc32Table[256];
+#else
 extern "C" unsigned int BZ2_crc32Table[256];
+#endif
 
 static unsigned int
 crc32(const unsigned char *buf, unsigned int len)
 {
   unsigned int crc = 0xffffffffL;
 
   const unsigned char *end = buf + len;
   for (; buf != end; ++buf)
--- a/toolkit/themes/gnomestripe/global/button.css
+++ b/toolkit/themes/gnomestripe/global/button.css
@@ -149,22 +149,17 @@ button[type="menu-button"] {
   -moz-box-align: center;
   -moz-box-pack: center;
   margin: 0;
   border: none;
 }
 
 .button-menu-dropmarker,
 .button-menubutton-dropmarker {
-  -moz-appearance: none !important;
-  margin: 1px;
-  background-color: transparent !important;
-  border: none !important;
-  min-width:11px;
-  min-height:11px;
+  -moz-appearance: toolbarbutton-dropdown !important;
 }
   
 .button-menubutton-dropmarker[open="true"] {
   margin-top: 2px;
   margin-bottom: 0px;
   -moz-margin-start: 2px;
   -moz-margin-end: 0px;
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/themes/gnomestripe/global/dropmarker.css
@@ -0,0 +1,3 @@
+dropmarker {
+  -moz-appearance: menulist-button;
+}
--- a/toolkit/themes/gnomestripe/global/jar.mn
+++ b/toolkit/themes/gnomestripe/global/jar.mn
@@ -2,16 +2,17 @@ classic.jar:
 +  skin/classic/global/autocomplete.css
 +  skin/classic/global/popup.css
 +  skin/classic/global/menu.css
 +  skin/classic/global/menulist.css
 +  skin/classic/global/numberbox.css
 +  skin/classic/global/tabbox.css
 +  skin/classic/global/toolbar.css
 +  skin/classic/global/toolbarbutton.css
++  skin/classic/global/dropmarker.css
 +  skin/classic/global/button.css
 +  skin/classic/global/checkbox.css
 +  skin/classic/global/splitter.css
 +  skin/classic/global/radio.css
 +  skin/classic/global/global.css
 +  skin/classic/global/tree.css
 +  skin/classic/global/listbox.css
 +  skin/classic/global/groupbox.css
--- a/toolkit/themes/gnomestripe/global/toolbarbutton.css
+++ b/toolkit/themes/gnomestripe/global/toolbarbutton.css
@@ -111,22 +111,20 @@ toolbarbutton[checked="true"]:hover:acti
   background-color: -moz-buttonhoverface !important;
 }
 
 /* ::::: toolbarbutton menu ::::: */
 
 .toolbarbutton-menu-dropmarker {
   -moz-appearance: toolbarbutton-dropdown !important;
   list-style-image: none;
-  width: 13px;
-  height: 13px;
   border: none !important;
   background-color: transparent !important;
   padding: 0;
-  margin: 2px;
+  margin: 0;
 }
 
 .toolbarbutton-menu-dropmarker[disabled="true"] {
   padding: 0 !important;
 }
 
 /* ::::: toolbarbutton menu-button ::::: */
 
@@ -156,16 +154,9 @@ toolbarbutton[type="menu-button"][disabl
 /* .......... dropmarker .......... */
 
 .toolbarbutton-menubutton-dropmarker {
   border: none !important;
   background-color: transparent !important;
   padding: 3px;
   -moz-appearance: toolbarbutton-dropdown !important;
   list-style-image: none;
-  width: 12px;
-  height: 12px;
 }
-
-.toolbarbutton-menubutton-dropmarker[disabled="true"] {
-  padding: 3px !important;
-}
-
--- a/toolkit/toolkit-makefiles.sh
+++ b/toolkit/toolkit-makefiles.sh
@@ -744,25 +744,21 @@ MAKEFILES_accessible="
   accessible/src/base/Makefile
   accessible/src/html/Makefile
   accessible/src/xul/Makefile
   accessible/src/msaa/Makefile
   accessible/src/atk/Makefile
   accessible/src/mac/Makefile
   accessible/build/Makefile
 "
+
 MAKEFILES_zlib="
   modules/zlib/standalone/Makefile
 "
 
-MAKEFILES_libbz2="
-  modules/libbz2/Makefile
-  modules/libbz2/src/Makefile
-"
-
 MAKEFILES_libmar="
   modules/libmar/Makefile
   modules/libmar/src/Makefile
   modules/libmar/tool/Makefile
 "
 
 add_makefiles "
   $MAKEFILES_db
@@ -801,17 +797,16 @@ add_makefiles "
   $MAKEFILES_xpcom_tests
   $MAKEFILES_xpinstall
   $MAKEFILES_xpfe
   $MAKEFILES_embedding
   $MAKEFILES_xulapp
   $MAKEFILES_libpr0n
   $MAKEFILES_accessible
   $MAKEFILES_zlib
-  $MAKEFILES_libbz2
   $MAKEFILES_libmar
 "
 
 #
 # Conditional makefiles
 #
 
 if [ "$MOZ_COMPOSER" ]; then
@@ -975,16 +970,23 @@ fi
 
 if [ ! "$SYSTEM_ZLIB" ]; then
   add_makefiles "
     modules/zlib/Makefile
     modules/zlib/src/Makefile
   "
 fi
 
+if [ ! "$SYSTEM_BZ2" ]; then
+  add_makefiles "
+    modules/libbz2/Makefile
+    modules/libbz2/src/Makefile
+  "
+fi
+
 if test -n "$MOZ_UPDATE_PACKAGING"; then
   add_makefiles "
     tools/update-packaging/Makefile
     other-licenses/bsdiff/Makefile
   "
 fi
 
 if [ ! "$SYSTEM_PNG" ]; then
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -59,17 +59,19 @@ tier_external_dirs	+= jpeg
 endif
 
 # Installer needs standalone libjar, hence standalone zlib
 ifdef MOZ_INSTALLER
 tier_external_dirs	+= modules/zlib/standalone
 endif
 
 ifdef MOZ_UPDATER
+ifndef MOZ_NATIVE_BZ2
 tier_external_dirs += modules/libbz2
+endif
 tier_external_dirs += modules/libmar
 endif
 
 ifndef MOZ_NATIVE_LCMS
 tier_external_dirs	+= modules/lcms
 endif
 
 #
--- a/tools/release/Bootstrap/Step/Updates.pm
+++ b/tools/release/Bootstrap/Step/Updates.pm
@@ -89,17 +89,18 @@ sub Execute {
       logFile => catfile($logDir, 'updates_patcher-download.log'),
       dir => catfile($versionedUpdateDir, 'patcher'),
     );
 
     # Create partial patches and snippets
     $this->Shell(
       cmd => './patcher2.pl',
       cmdArgs => ['--create-patches', '--app=' . $product, 
-                    '--config=../config/' . $patcherConfig],
+                  '--config=../config/' . $patcherConfig,
+                  '--partial-patchlist-file=patchlist.cfg'],
       logFile => catfile($logDir, 'updates_patcher-create-patches.log'),
       dir => catfile($versionedUpdateDir, 'patcher'),
       timeout => 18000,
     );
     
     ### quick verification
     my $fullUpdateDir = catfile($versionedUpdateDir, 'patcher', 'temp', 
                           $product, $oldVersion . '-' . $version);
--- a/tools/release/configs/fx-moz18-bootstrap.cfg
+++ b/tools/release/configs/fx-moz18-bootstrap.cfg
@@ -1,21 +1,21 @@
-version         = 2.0.0.12
-milestone       = 1.8.1.12
+version         = 2.0.0.13
+milestone       = 1.8.1.13
 # _RCn and _RELEASE will be appended as-needed
-productTag      = FIREFOX_2_0_0_12
+productTag      = FIREFOX_2_0_0_13
 # Branch name and pull dates to use for base tag
 branchTag       = MOZILLA_1_8_BRANCH
 #RelbranchOverride = GECKO181_20080128_RELBRANCH
-pullDate        = 2008-02-01 20:00 PST
-l10n_pullDate   = 2008-01-28 16:00 PST
-rc              = 4
+pullDate        = 2008-03-09 23:00 PDT
+l10n_pullDate   = 2008-03-09 23:00 PDT
+rc              = 1
 # oldVersion and oldRc refer to the previous release
-oldVersion      = 2.0.0.11
-oldRc           = 1
+oldVersion      = 2.0.0.12
+oldRc           = 4
 appName         = browser
 product         = firefox
 # Absolute path to tinderbox build directory
 linux_buildDir       = /builds/tinderbox/Fx-Mozilla1.8-Release
 macosx_buildDir      = /builds/tinderbox/Fx-Mozilla1.8-Release
 win32_buildDir       = /cygdrive/c/builds/tinderbox/Fx-Mozilla1.8-Release
 linux_l10n_buildDir  = /builds/tinderbox/Fx-Mozilla1.8-l10n-Release
 macosx_l10n_buildDir = /builds/tinderbox/Fx-Mozilla1.8-l10n-Release
@@ -42,17 +42,17 @@ win32_buildPlatform   = WINNT_5.2_Depend
 linux_l10n_buildPlatform   = Linux_2.4.21-27.0.4.EL_Depend
 macosx_l10n_buildPlatform  = Darwin_8.7.0_Depend
 win32_l10n_buildPlatform   = WINNT_5.2_Depend
 from            = bootstrap@mozilla.org
 to              = build@mozilla.org
 cc              = nobody@mozilla.org
 patcherConfig   = moz18-branch-patcher2.cfg
 # Tag to use for building MAR/MBSDIFF and other update tools
-patcherToolsRev = UPDATE_PACKAGING_R1
+patcherToolsRev = UPDATE_PACKAGING_R2
 linux_verifyConfig    = moz18-firefox-linux.cfg
 win32_verifyConfig    = moz18-firefox-win32.cfg
 macosx_verifyConfig   = moz18-firefox-mac.cfg
 blat            = /cygdrive/c/moztools/bin/blat.exe
 sendmail        = /usr/sbin/sendmail
 # dump Log output to stdout
 dumpLogs        = 1
 # username and server to push update snippets to
--- a/tools/release/configs/fx-moz18-nightly-staging-bootstrap.cfg
+++ b/tools/release/configs/fx-moz18-nightly-staging-bootstrap.cfg
@@ -1,13 +1,13 @@
 version         = nightly
 milestone       = nightly
 # _RCn and _RELEASE will be appended as-needed
 # not used by nightly
-productTag      = FIREFOX_2_0_0_12pre
+productTag      = FIREFOX_2_0_0_13pre
 # Branch name and pull dates to use for base tag
 branchTag       = MOZILLA_1_8_BRANCH
 # manually tagged from GECKO181_20070712_RELBRANCH
 # RelbranchOverride = GECKO181_20070712_RELBRANCH
 # not used by nightly
 pullDate        = 2007-08-21 03:07 PDT
 l10n_pullDate   = 2007-08-21 03:07 PDT
 rc              = 1
@@ -82,9 +82,9 @@ sshServer       = staging-1.8-master.bui
 useTalkback     = 0
 symbolServer     = staging-1.8-master.mozilla.org
 symbolServerUser = cltbld
 symbolServerPath = /data/symbols
 symbolServerKey  = /home/cltbld/.ssh/id_dsa
 symbolDir        = /builds/symbols
 # turn off tests
 testsPhoneHome   = 0
-bootstrapTag     = RELEASE_AUTOMATION_M7_1
+bootstrapTag     = RELEASE_AUTOMATION_M7_2
--- a/tools/release/configs/fx-moz19-nightly-bootstrap.cfg
+++ b/tools/release/configs/fx-moz19-nightly-bootstrap.cfg
@@ -1,85 +1,91 @@
 version         = nightly
-milestone       = 1.9b2
+milestone       = nightly
 # _RCn and _RELEASE will be appended as-needed
-productTag      = FIREFOX_3_0b2
+# not used by nightly
+productTag      = FIREFOX_3_0b5pre
 # Branch name and pull dates to use for base tag
 branchTag       = HEAD
 #RelbranchOverride = GECKO190_20071207_RELBRANCH
+# not used by nightly
 pullDate        = 2008-01-08 18:00 PST
 l10n_pullDate   = 2008-01-08 18:00 PST
 rc              = 1
 # oldVersion and oldRc refer to the previous release
+# not used by nightly
 oldVersion      = 3.0b1
 oldRc           = 3
+# app name and product name
 appName         = browser
 product         = firefox
 # Absolute path to tinderbox build directory
 # The win32 ones are kept short because of a long path issue detailed in
 # bug# 400846
 linux_buildDir       = /builds/tinderbox/Fx-Mozilla1.9-Nightly
 macosx_buildDir      = /builds/tinderbox/Fx-Mozilla1.9-Nightly
 win32_buildDir       = /e/fx19nit
 linux_l10n_buildDir  = /builds/tinderbox/Fx-Mozilla1.9-l10n-Nightly
 macosx_l10n_buildDir = /builds/tinderbox/Fx-Mozilla1.9-l10n-Nightly
 win32_l10n_buildDir  = /e/fx19l10nit
 # Absolute path to store bootstrap's logs
 linux_logDir    = /builds/logs.nightly
 macosx_logDir   = /builds/logs.nightly
 win32_logDir    = /builds/logs.nightly
-mozillaCvsroot  = staging-1.9-master.build.mozilla.org:/builds/cvsmirror/cvsroot
-l10nCvsroot     = staging-1.9-master.build.mozilla.org:/builds/cvsmirror/l10n
-mofoCvsroot     = staging-1.9-master.build.mozilla.org:/builds/cvsmirror/mofo
-anonCvsroot	= staging-1.9-master.build.mozilla.org:/builds/cvsmirror/cvsroot
+mozillaCvsroot  = :ext:cltbld@cvs.mozilla.org:/cvsroot
+l10nCvsroot     = :ext:cltbld@cvs.mozilla.org:/l10n
+mofoCvsroot     = :ext:cltbld@cvs.mozilla.org:/mofo
+anonCvsroot	    = :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
 # private staging area 
 stageHome       = /data/cltbld
 updateDir       = /builds/updates
 verifyDir       = /builds/verify
 tagDir          = /builds/tags
 configBumpDir   = /builds/config
 # Build platform, as specified by tinderbox
 linux_buildPlatform   = Linux_2.6.18-53.1.13.el5_Depend
 macosx_buildPlatform  = Darwin_8.8.4_Depend
 win32_buildPlatform   = WINNT_5.2_Depend
 linux_l10n_buildPlatform   = Linux_2.6.18-53.1.13.el5_Depend
 macosx_l10n_buildPlatform  = Darwin_8.8.4_Depend
 win32_l10n_buildPlatform   = WINNT_5.2_Depend
-from            = staging-bootstrap@mozilla.org
+from            = bootstrap@mozilla.org
 to              = build-announce@mozilla.org
 cc              = nobody@mozilla.org
+# not used by nightly
 patcherConfig   = moz19-patcher2.cfg
 # Tag to use for building MAR/MBSDIFF and other update tools
 patcherToolsRev = UPDATE_PACKAGING_R1
 linux_verifyConfig    = moz19-firefox-linux.cfg
 win32_verifyConfig    = moz19-firefox-win32.cfg
 macosx_verifyConfig   = moz19-firefox-mac.cfg
 blat            = /d/mozilla-build/blat261/full/blat.exe
 sendmail        = /usr/sbin/sendmail
 # dump Log output to stdout
 dumpLogs        = 1
-# symbol server variables
-symbolServer     = staging-1.9-master.build.mozilla.org
-symbolServerUser = cltbld
-symbolServerPath = /data/symbols
-symbolServerKey  = /home/cltbld/.ssh/id_dsa
 # username and server to push update snippets to
-ausUser         = cltbld
-ausServer       = staging-1.9-master.build.mozilla.org
-ausServerUrl    = http://staging-1.9-master.build.mozilla.org
-buildTree       = MozillaTest
+ausUser           = cltbld
+ausServer         = aus2-staging.mozilla.org
+ausServerUrl      = https://aus2.mozilla.org
+buildTree       = Firefox
 # where QA updates/builds go
 stagingUser     = cltbld
-stagingServer   = staging-1.9-master.build.mozilla.org
+stagingServer   = stage.mozilla.org
 externalStagingUser     = cltbld
-externalStagingServer   = fx-linux-1.9-slave1.build.mozilla.org
+externalStagingServer   = ftp.mozilla.org
 # where beta updates/builds go
-ftpServer       = staging-1.9-master.build.mozilla.org
+ftpServer       = ftp.mozilla.org
 # where release updates/builds go
-bouncerServer   = staging-1.9-master.build.mozilla.org
+bouncerServer   = download.mozilla.org
 # username and server to push builds
-sshUser         = cltbld
-sshServer       = staging-1.9-master.build.mozilla.org
+sshUser         = ffxbld
+sshServer       = stage.mozilla.org
 useTalkback     = 0
+# symbol server variables
+symbolServer     = stage.mozilla.org
+symbolServerUser = ffxbld
+symbolServerPath = /mnt/netapp/breakpad/symbols_ffx
+win32_symbolServerKey  = /c/Documents and Settings/cltbld/.ssh/ffxbld_dsa
+linux_symbolServerKey  = /home/cltbld/.ssh/ffxbld_dsa
+macosx_symbolServerKey  = /Users/cltbld/.ssh/ffxbld_dsa
 useCvsCompression = 1
-# turn off tests
-runMozillaTests  = 0
-bootstrapTag    = RELEASE_AUTOMATION_M7_1
+testsPhoneHome   = 0
+bootstrapTag     = RELEASE_AUTOMATION_M8
new file mode 100644
--- /dev/null
+++ b/tools/release/configs/fx-moz19-nightly-staging-bootstrap.cfg
@@ -0,0 +1,92 @@
+version         = nightly
+milestone       = nightly
+# _RCn and _RELEASE will be appended as-needed
+# not used by nightly
+productTag      = FIREFOX_3_0b2pre
+# Branch name and pull dates to use for base tag
+branchTag       = HEAD
+#RelbranchOverride = GECKO190_20071207_RELBRANCH
+# not used by nightly
+pullDate        = 2008-01-08 18:00 PST
+l10n_pullDate   = 2008-01-08 18:00 PST
+rc              = 1
+# oldVersion and oldRc refer to the previous release
+# not used by nightly
+oldVersion      = 3.0b1
+oldRc           = 3
+# app name and product name
+appName         = browser
+product         = firefox
+# Absolute path to tinderbox build directory
+# The win32 ones are kept short because of a long path issue detailed in
+# bug# 400846
+linux_buildDir       = /builds/tinderbox/Fx-Mozilla1.9-Nightly
+macosx_buildDir      = /builds/tinderbox/Fx-Mozilla1.9-Nightly
+win32_buildDir       = /e/fx19nit
+linux_l10n_buildDir  = /builds/tinderbox/Fx-Mozilla1.9-l10n-Nightly
+macosx_l10n_buildDir = /builds/tinderbox/Fx-Mozilla1.9-l10n-Nightly
+win32_l10n_buildDir  = /e/fx19l10nit
+# Absolute path to store bootstrap's logs
+linux_logDir    = /builds/logs.nightly
+macosx_logDir   = /builds/logs.nightly
+win32_logDir    = /builds/logs.nightly
+mozillaCvsroot  = staging-1.9-master.build.mozilla.org:/builds/cvsmirror/cvsroot
+l10nCvsroot     = staging-1.9-master.build.mozilla.org:/builds/cvsmirror/l10n
+mofoCvsroot     = staging-1.9-master.build.mozilla.org:/builds/cvsmirror/mofo
+anonCvsroot	= staging-1.9-master.build.mozilla.org:/builds/cvsmirror/cvsroot
+# private staging area 
+stageHome       = /data/cltbld
+updateDir       = /builds/updates
+verifyDir       = /builds/verify
+tagDir          = /builds/tags
+configBumpDir   = /builds/config
+# Build platform, as specified by tinderbox
+linux_buildPlatform   = Linux_2.6.18-53.1.13.el5_Depend
+macosx_buildPlatform  = Darwin_8.8.4_Depend
+win32_buildPlatform   = WINNT_5.2_Depend
+linux_l10n_buildPlatform   = Linux_2.6.18-53.1.13.el5_Depend
+macosx_l10n_buildPlatform  = Darwin_8.8.4_Depend
+win32_l10n_buildPlatform   = WINNT_5.2_Depend
+from            = staging-bootstrap@mozilla.org
+to              = build-announce@mozilla.org
+cc              = nobody@mozilla.org
+# not used by nightly
+patcherConfig   = moz19-patcher2.cfg
+# Tag to use for building MAR/MBSDIFF and other update tools
+patcherToolsRev = UPDATE_PACKAGING_R1
+linux_verifyConfig    = moz19-firefox-linux.cfg
+win32_verifyConfig    = moz19-firefox-win32.cfg
+macosx_verifyConfig   = moz19-firefox-mac.cfg
+blat            = /d/mozilla-build/blat261/full/blat.exe
+sendmail        = /usr/sbin/sendmail
+# dump Log output to stdout
+dumpLogs        = 1
+# username and server to push update snippets to
+ausUser         = cltbld
+ausServer       = staging-1.9-master.build.mozilla.org
+ausServerUrl    = http://staging-1.9-master.build.mozilla.org
+buildTree       = Firefox-Staging
+# where QA updates/builds go
+stagingUser     = cltbld
+stagingServer   = staging-1.9-master.build.mozilla.org
+externalStagingUser     = cltbld
+externalStagingServer   = fx-linux-1.9-slave1.build.mozilla.org
+# where beta updates/builds go
+ftpServer       = staging-1.9-master.build.mozilla.org
+# where release updates/builds go
+bouncerServer   = staging-1.9-master.build.mozilla.org
+# username and server to push builds
+sshUser         = cltbld
+sshServer       = staging-1.9-master.build.mozilla.org
+useTalkback     = 0
+# symbol server variables
+symbolServer     = staging-1.9-master.build.mozilla.org
+symbolServerUser = cltbld
+symbolServerPath = /data/symbols
+win32_symbolServerKey  = /c/Documents and Settings/cltbld/.ssh/ffxbld_dsa
+linux_symbolServerKey  = /home/cltbld/.ssh/ffxbld_dsa
+macosx_symbolServerKey  = /Users/cltbld/.ssh/ffxbld_dsa
+useCvsCompression = 1
+# turn off tests
+testsPhoneHome   = 0
+bootstrapTag     = RELEASE_AUTOMATION_M8
--- a/tools/release/configs/fx-moz19-staging-bootstrap.cfg
+++ b/tools/release/configs/fx-moz19-staging-bootstrap.cfg
@@ -4,18 +4,18 @@ milestone       = 1.9b3
 productTag      = FIREFOX_3_0b3
 # Branch name and pull dates to use for base tag
 branchTag       = HEAD
 #RelbranchOverride = GECKO190_20071207_RELBRANCH
 pullDate        = 2008-01-07 09:00 PST
 l10n_pullDate   = 2008-01-07 09:00 PST
 rc              = 1
 # oldVersion and oldRc refer to the previous release
-oldVersion      = 3.0b2
-oldRc           = 1
+oldVersion      = 3.0b4
+oldRc           = 3
 appName         = browser
 product         = firefox
 # Absolute path to tinderbox build directory
 # The win32 ones are kept short because of a long path issue detailed in
 # bug# 400846
 linux_buildDir       = /builds/tinderbox/Fx-Mozilla1.9-Release
 macosx_buildDir      = /builds/tinderbox/Fx-Mozilla1.9-Release
 win32_buildDir       = /e/fx19rel
--- a/widget/src/gtk2/gtk2drawing.c
+++ b/widget/src/gtk2/gtk2drawing.c
@@ -53,29 +53,30 @@
 
 #define XTHICKNESS(style) (style->xthickness)
 #define YTHICKNESS(style) (style->ythickness)
 #define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window))
 
 static GtkWidget* gProtoWindow;
 static GtkWidget* gButtonWidget;
 static GtkWidget* gToggleButtonWidget;
+static GtkWidget* gButtonArrowWidget;
 static GtkWidget* gCheckboxWidget;
 static GtkWidget* gRadiobuttonWidget;
 static GtkWidget* gHorizScrollbarWidget;
 static GtkWidget* gVertScrollbarWidget;
 static GtkWidget* gSpinWidget;
 static GtkWidget* gHScaleWidget;
 static GtkWidget* gVScaleWidget;
 static GtkWidget* gEntryWidget;
-static GtkWidget* gArrowWidget;
 static GtkWidget* gOptionMenuWidget;
 static GtkWidget* gComboBoxEntryWidget;
-static GtkWidget* gDropdownEntryWidget;
-static GtkWidget* gDropdownButtonWidget;
+static GtkWidget* gComboBoxEntryTextareaWidget;
+static GtkWidget* gComboBoxEntryButtonWidget;
+static GtkWidget* gComboBoxEntryArrowWidget;
 static GtkWidget* gHandleBoxWidget;
 static GtkWidget* gToolbarWidget;
 static GtkWidget* gFrameWidget;
 static GtkWidget* gStatusbarWidget;
 static GtkWidget* gProgressWidget;
 static GtkWidget* gTabWidget;
 static GtkWidget* gTooltipWidget;
 static GtkWidget* gMenuBarWidget;
@@ -89,21 +90,17 @@ static GtkWidget* gTreeHeaderCellWidget;
 static GtkWidget* gTreeHeaderSortArrowWidget;
 static GtkWidget* gExpanderWidget;
 static GtkWidget* gToolbarSeparatorWidget;
 static GtkWidget* gMenuSeparatorWidget;
 static GtkWidget* gHPanedWidget;
 static GtkWidget* gVPanedWidget;
 static GtkWidget* gScrolledWindowWidget;
 
-static GtkShadowType gMenuBarShadowType;
-static GtkShadowType gToolbarShadowType;
-
 static style_prop_t style_prop_func;
-static gboolean have_menu_shadow_type;
 static gboolean have_arrow_scaling;
 static gboolean is_initialized;
 
 gint
 moz_gtk_enable_style_props(style_prop_t styleGetProp)
 {
     style_prop_func = styleGetProp;
     return MOZ_GTK_SUCCESS;
@@ -172,16 +169,29 @@ ensure_toggle_button_widget()
         setup_widget_prototype(gToggleButtonWidget);
         /* toggle button must be set active to get the right style on hover. */
         GTK_TOGGLE_BUTTON(gToggleButtonWidget)->active = TRUE;
   }
   return MOZ_GTK_SUCCESS;
 }
 
 static gint
+ensure_button_arrow_widget()
+{
+    if (!gButtonArrowWidget) {
+        ensure_toggle_button_widget();
+
+        gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+        gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
+        gtk_widget_realize(gButtonArrowWidget);
+    }
+    return MOZ_GTK_SUCCESS;
+}
+
+static gint
 ensure_checkbox_widget()
 {
     if (!gCheckboxWidget) {
         gCheckboxWidget = gtk_check_button_new_with_label("M");
         setup_widget_prototype(gCheckboxWidget);
     }
     return MOZ_GTK_SUCCESS;
 }
@@ -265,113 +275,104 @@ ensure_option_menu_widget()
  * of weak pointer since they are explicit children of gProtoWindow and as
  * such GTK holds a strong reference to them. */
 
 static void
 moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
                                           gpointer client_data)
 {
     if (GTK_IS_TOGGLE_BUTTON(widget)) {
-        gDropdownButtonWidget = widget;
+        gComboBoxEntryButtonWidget = widget;
         g_object_add_weak_pointer(G_OBJECT(widget),
-                                  (gpointer) &gDropdownButtonWidget);
+                                  (gpointer) &gComboBoxEntryButtonWidget);
     } else if (GTK_IS_ENTRY(widget)) {
-        gDropdownEntryWidget = widget;
+        gComboBoxEntryTextareaWidget = widget;
         g_object_add_weak_pointer(G_OBJECT(widget),
-                                  (gpointer) &gDropdownEntryWidget);
+                                  (gpointer) &gComboBoxEntryTextareaWidget);
     } else
         return;
     gtk_widget_realize(widget);
 }
 
 static void
 moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data)
 {
     if (GTK_IS_ARROW(widget)) {
-        gArrowWidget = widget;
+        gComboBoxEntryArrowWidget = widget;
         g_object_add_weak_pointer(G_OBJECT(widget),
-                                  (gpointer) &gArrowWidget);
+                                  (gpointer) &gComboBoxEntryArrowWidget);
         gtk_widget_realize(widget);
     }
 }
 
 static gint
 ensure_combo_box_entry_widgets()
 {
-    if (!gDropdownEntryWidget ||
-        !gDropdownButtonWidget ||
-        !gArrowWidget) {
+    if (!gComboBoxEntryTextareaWidget ||
+        !gComboBoxEntryButtonWidget ||
+        !gComboBoxEntryArrowWidget) {
         GtkWidget* buttonChild;
 
         /* Create a ComboBoxEntry if needed */
         if (!gComboBoxEntryWidget) {
             gComboBoxEntryWidget = gtk_combo_box_entry_new();
             setup_widget_prototype(gComboBoxEntryWidget);
         }
 
         /* Get its inner Entry and Button */
         gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget),
                              moz_gtk_get_combo_box_entry_inner_widgets,
                              NULL);
 
-        if (!gDropdownEntryWidget) {
+        if (!gComboBoxEntryTextareaWidget) {
             ensure_entry_widget();
-            gDropdownEntryWidget = gEntryWidget;
+            gComboBoxEntryTextareaWidget = gEntryWidget;
         }
 
-        if (gDropdownButtonWidget) {
+        if (gComboBoxEntryButtonWidget) {
             /* Get the Arrow inside the Button */
-            buttonChild = GTK_BIN(gDropdownButtonWidget)->child;
+            buttonChild = GTK_BIN(gComboBoxEntryButtonWidget)->child;
             if (GTK_IS_HBOX(buttonChild)) {
                 /* appears-as-list = FALSE, cell-view = TRUE; the button
                  * contains an hbox. This hbox is there because ComboBoxEntry
                  * inherits from ComboBox which needs to place a cell renderer,
                  * a separator, and an arrow in the button when appears-as-list
                  * is FALSE. Here the hbox should only contain an arrow, since
                  * a ComboBoxEntry doesn't need all those widgets in the
                  * button. */
                 gtk_container_forall(GTK_CONTAINER(buttonChild),
                                      moz_gtk_get_combo_box_entry_arrow,
                                      NULL);
             } else if(GTK_IS_ARROW(buttonChild)) {
                 /* appears-as-list = TRUE, or cell-view = FALSE;
                  * the button only contains an arrow */
-                gArrowWidget = buttonChild;
-                g_object_add_weak_pointer(G_OBJECT(buttonChild),
-                                          (gpointer) &gArrowWidget);
-                gtk_widget_realize(gArrowWidget);
+                gComboBoxEntryArrowWidget = buttonChild;
+                g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer)
+                                          &gComboBoxEntryArrowWidget);
+                gtk_widget_realize(gComboBoxEntryArrowWidget);
             }
         } else {
             /* Shouldn't be reached with current internal gtk implementation;
              * we use a generic toggle button as last resort fallback to avoid
              * crashing. */
             ensure_toggle_button_widget();
-            gDropdownButtonWidget = gToggleButtonWidget;
+            gComboBoxEntryButtonWidget = gToggleButtonWidget;
         }
 
-        if (!gArrowWidget) {
+        if (!gComboBoxEntryArrowWidget) {
             /* Shouldn't be reached with current internal gtk implementation;
-             * we use a generic down arrow as last resort fallback to avoid
+             * we gButtonArrowWidget as last resort fallback to avoid
              * crashing. */
-            gArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
-            setup_widget_prototype(gArrowWidget);
+            ensure_button_arrow_widget();
+            gComboBoxEntryArrowWidget = gButtonArrowWidget;
         }
     }
     return MOZ_GTK_SUCCESS;
 }
 
-/* Will go away when bug 416003 lands (Use different arrow widgets for
- * arrows in different context) */
-static gint
-ensure_arrow_widget()
-{
-    if (!gArrowWidget)
-        ensure_combo_box_entry_widgets();
-    return MOZ_GTK_SUCCESS;
-}
 
 static gint
 ensure_handlebox_widget()
 {
     if (!gHandleBoxWidget) {
         gHandleBoxWidget = gtk_handle_box_new();
         setup_widget_prototype(gHandleBoxWidget);
     }
@@ -381,18 +382,16 @@ ensure_handlebox_widget()
 static gint
 ensure_toolbar_widget()
 {
     if (!gToolbarWidget) {
         ensure_handlebox_widget();
         gToolbarWidget = gtk_toolbar_new();
         gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
         gtk_widget_realize(gToolbarWidget);
-        gtk_widget_style_get(gToolbarWidget, "shadow_type", &gToolbarShadowType,
-                             NULL);
     }
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 ensure_toolbar_separator_widget()
 {
     if (!gToolbarSeparatorWidget) {
@@ -456,18 +455,16 @@ ensure_frame_widget()
 }
 
 static gint
 ensure_menu_bar_widget()
 {
     if (!gMenuBarWidget) {
         gMenuBarWidget = gtk_menu_bar_new();
         setup_widget_prototype(gMenuBarWidget);
-       gtk_widget_style_get(gMenuBarWidget, "shadow_type", &gMenuBarShadowType,
-                            NULL);
     }
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 ensure_menu_bar_item_widget()
 {
     if (!gMenuBarItemWidget) {
@@ -734,19 +731,16 @@ moz_gtk_button_paint(GdkDrawable* drawab
     GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_DEFAULT);
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_init()
 {
     is_initialized = TRUE;
-    have_menu_shadow_type =
-        (gtk_major_version > 2 ||
-         (gtk_major_version == 2 && gtk_minor_version >= 1));
     have_arrow_scaling = (gtk_major_version > 2 ||
                           (gtk_major_version == 2 && gtk_minor_version >= 12));
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing)
@@ -918,28 +912,28 @@ moz_gtk_toggle_paint(GdkDrawable* drawab
                             focus_width, focus_height);
         }
     }
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
-calculate_arrow_dimensions(GdkRectangle* rect, GdkRectangle* arrow_rect,
-                           GtkTextDirection direction)
+calculate_arrow_rect(GtkWidget* arrow, GdkRectangle* rect,
+                     GdkRectangle* arrow_rect, GtkTextDirection direction)
 {
     /* defined in gtkarrow.c */
     gfloat arrow_scaling = 0.7;
     gfloat xalign, xpad;
     gint extent;
-    GtkMisc* misc = GTK_MISC(gArrowWidget);
+    GtkMisc* misc = GTK_MISC(arrow);
 
     if (have_arrow_scaling)
-        gtk_widget_style_get(gArrowWidget,
-                             "arrow_scaling", &arrow_scaling, NULL);
+        gtk_widget_style_get(arrow, "arrow_scaling", &arrow_scaling, NULL);
+
     extent = MIN((rect->width - misc->xpad * 2),
                  (rect->height - misc->ypad * 2)) * arrow_scaling;
 
     xalign = direction == GTK_TEXT_DIR_LTR ? misc->xalign : 1.0 - misc->xalign;
     xpad = misc->xpad + (rect->width - extent) * xalign;
 
     arrow_rect->x = direction == GTK_TEXT_DIR_LTR ?
                         floor(rect->x + xpad) : ceil(rect->x + xpad);
@@ -1132,17 +1126,18 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWi
 
     adj->lower = 0;
     adj->value = state->curpos;
     adj->upper = state->maxpos;
     gtk_adjustment_changed(adj);
 
     style = GTK_WIDGET(scrollbar)->style;
     
-    gtk_widget_style_get(scrollbar, "activate-slider", &activate_slider, NULL);
+    gtk_widget_style_get(GTK_WIDGET(scrollbar), "activate-slider",
+                         &activate_slider, NULL);
     
     if (activate_slider && state->active) {
         shadow_type = GTK_SHADOW_IN;
         state_type = GTK_STATE_ACTIVE;
     }
 
     TSOffsetStyleGCs(style, rect->x, rect->y);
 
@@ -1635,93 +1630,94 @@ static gint
 moz_gtk_downarrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
                         GdkRectangle* cliprect, GtkWidgetState* state)
 {
     GtkStyle* style;
     GtkStateType state_type = ConvertGtkState(state);
     GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
     GdkRectangle arrow_rect;
 
-    ensure_arrow_widget();
-    style = gArrowWidget->style;
-
-    arrow_rect.x = rect->x + 1 + XTHICKNESS(style);
-    arrow_rect.y = rect->y + 1 + YTHICKNESS(style);
-    arrow_rect.width = MAX(1, rect->width - (arrow_rect.x - rect->x) * 2);
-    arrow_rect.height = MAX(1, rect->height - (arrow_rect.y - rect->y) * 2);
+    ensure_button_arrow_widget();
+    style = gButtonArrowWidget->style;
+
+    calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
+                         GTK_TEXT_DIR_LTR);
 
     TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y);
     gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
-                    gArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
+                    gButtonArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
                     arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height);
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
-moz_gtk_dropdown_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect,
-                             GdkRectangle* cliprect, GtkWidgetState* state,
-                             gboolean input_focus, GtkTextDirection direction)
+moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect,
+                                     GdkRectangle* cliprect,
+                                     GtkWidgetState* state,
+                                     gboolean input_focus,
+                                     GtkTextDirection direction)
 {
     GtkBorder inner_border;
     gboolean interior_focus;
     gint focus_width, focus_pad;
     gint x_displacement, y_displacement;
     GdkRectangle arrow_rect, real_arrow_rect;
     GtkStateType state_type = ConvertGtkState(state);
     GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
     GtkStyle* style;
 
     ensure_combo_box_entry_widgets();
 
     if (input_focus) {
         /* Some themes draw a complementary focus ring for the dropdown button
          * when the dropdown entry has focus */
-        GTK_WIDGET_SET_FLAGS(gDropdownEntryWidget, GTK_HAS_FOCUS);
+        GTK_WIDGET_SET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
     }
 
     moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL,
-                         gDropdownButtonWidget, direction);
+                         gComboBoxEntryButtonWidget, direction);
 
     if (input_focus)
-        GTK_WIDGET_UNSET_FLAGS(gDropdownEntryWidget, GTK_HAS_FOCUS);
+        GTK_WIDGET_UNSET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS);
 
     /* This mirrors gtkbutton's child positioning */
-    style = gDropdownButtonWidget->style;
-
-    moz_gtk_button_get_inner_border(gDropdownButtonWidget, &inner_border);
-    moz_gtk_widget_get_focus(gDropdownButtonWidget, &interior_focus,
+    style = gComboBoxEntryButtonWidget->style;
+
+    moz_gtk_button_get_inner_border(gComboBoxEntryButtonWidget, &inner_border);
+    moz_gtk_widget_get_focus(gComboBoxEntryButtonWidget, &interior_focus,
                              &focus_width, &focus_pad);
 
     arrow_rect.x = rect->x + XTHICKNESS(style) + focus_width + focus_pad;
     arrow_rect.x += direction == GTK_TEXT_DIR_LTR ?
                         inner_border.left : inner_border.right;
     arrow_rect.y = rect->y + inner_border.top + YTHICKNESS(style) +
                    focus_width + focus_pad;
     arrow_rect.width = MAX(1, rect->width - inner_border.left -
        inner_border.right - (XTHICKNESS(style) + focus_pad + focus_width) * 2);
     arrow_rect.height = MAX(1, rect->height - inner_border.top -
        inner_border.bottom - (YTHICKNESS(style) + focus_pad + focus_width) * 2);
 
     if (state_type == GTK_STATE_ACTIVE) {
-        gtk_widget_style_get(gDropdownButtonWidget,
+        gtk_widget_style_get(gComboBoxEntryButtonWidget,
                              "child-displacement-x", &x_displacement,
                              "child-displacement-y", &y_displacement,
                              NULL);
         arrow_rect.x += x_displacement;
         arrow_rect.y += y_displacement;
     }
 
-    calculate_arrow_dimensions(&arrow_rect, &real_arrow_rect, direction);
-
-    style = gArrowWidget->style;
+    calculate_arrow_rect(gComboBoxEntryArrowWidget,
+                         &arrow_rect, &real_arrow_rect, direction);
+
+    style = gComboBoxEntryArrowWidget->style;
     TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y);
 
     gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect,
-                    gArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
+                    gComboBoxEntryArrowWidget, "arrow",  GTK_ARROW_DOWN, TRUE,
                     real_arrow_rect.x, real_arrow_rect.y,
                     real_arrow_rect.width, real_arrow_rect.height);
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_container_paint(GdkDrawable* drawable, GdkRectangle* rect,
@@ -1825,17 +1821,19 @@ moz_gtk_toolbar_paint(GdkDrawable* drawa
 
     TSOffsetStyleGCs(style, rect->x, rect->y);
 
     gtk_style_apply_default_background(style, drawable, TRUE,
                                        GTK_STATE_NORMAL,
                                        cliprect, rect->x, rect->y,
                                        rect->width, rect->height);
 
-    gtk_paint_box (style, drawable, GTK_STATE_NORMAL, gToolbarShadowType,
+    gtk_widget_style_get(gToolbarWidget, "shadow-type", &shadow_type, NULL);
+
+    gtk_paint_box (style, drawable, GTK_STATE_NORMAL, shadow_type,
                    cliprect, gToolbarWidget, "toolbar",
                    rect->x, rect->y, rect->width, rect->height);
 
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect,
@@ -2204,23 +2202,26 @@ static gint
 moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect,
                        GdkRectangle* cliprect, GtkTextDirection direction)
 {
     GtkStyle* style;
     GtkShadowType shadow_type;
     ensure_menu_bar_widget();
     gtk_widget_set_direction(gMenuBarWidget, direction);
 
+    gtk_widget_style_get(gMenuBarWidget, "shadow-type", &shadow_type, NULL);
+
     style = gMenuBarWidget->style;
 
     TSOffsetStyleGCs(style, rect->x, rect->y);
     gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
                                        cliprect, rect->x, rect->y,
                                        rect->width, rect->height);
-    gtk_paint_box(style, drawable, GTK_STATE_NORMAL, gMenuBarShadowType,
+
+    gtk_paint_box(style, drawable, GTK_STATE_NORMAL, shadow_type,
                   cliprect, gMenuBarWidget, "menubar", rect->x, rect->y,
                   rect->width, rect->height);
     return MOZ_GTK_SUCCESS;
 }
 
 static gint
 moz_gtk_menu_popup_paint(GdkDrawable* drawable, GdkRectangle* rect,
                          GdkRectangle* cliprect, GtkTextDirection direction)
@@ -2308,22 +2309,19 @@ moz_gtk_menu_item_paint(GdkDrawable* dra
         } else {
             ensure_menu_item_widget();
             item_widget = gMenuItemWidget;
         }
         gtk_widget_set_direction(item_widget, direction);
         
         style = item_widget->style;
         TSOffsetStyleGCs(style, rect->x, rect->y);
-        if (have_menu_shadow_type) {
-            gtk_widget_style_get(item_widget, "selected_shadow_type",
-                                 &shadow_type, NULL);
-        } else {
-            shadow_type = GTK_SHADOW_OUT;
-        }
+
+        gtk_widget_style_get(item_widget, "selected-shadow-type",
+                             &shadow_type, NULL);
 
         gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, shadow_type,
                       cliprect, item_widget, "menuitem", rect->x, rect->y,
                       rect->width, rect->height);
     }
 
     return MOZ_GTK_SUCCESS;
 }
@@ -2494,21 +2492,21 @@ moz_gtk_get_widget_border(GtkThemeWidget
             return MOZ_GTK_SUCCESS;
         }
     case MOZ_GTK_TREE_HEADER_SORTARROW:
         ensure_tree_header_cell_widget();
         w = gTreeHeaderSortArrowWidget;
         break;
     case MOZ_GTK_DROPDOWN_ENTRY:
         ensure_combo_box_entry_widgets();
-        w = gDropdownEntryWidget;
+        w = gComboBoxEntryTextareaWidget;
         break;
     case MOZ_GTK_DROPDOWN_ARROW:
         ensure_combo_box_entry_widgets();
-        w = gDropdownButtonWidget;
+        w = gComboBoxEntryButtonWidget;
         break;
     case MOZ_GTK_DROPDOWN:
         {
             /* We need to account for the arrow on the dropdown, so text doesn't
                come too close to the arrow, or in some cases spill into the arrow. */
             gboolean interior_focus;
             GtkRequisition indicator_size;
             GtkBorder indicator_spacing;
@@ -2664,27 +2662,27 @@ moz_gtk_get_widget_border(GtkThemeWidget
 
     *right = *left = XTHICKNESS(w->style);
     *bottom = *top = YTHICKNESS(w->style);
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
-moz_gtk_get_dropdown_arrow_size(gint* width, gint* height)
+moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height)
 {
     /*
      * We get the requisition of the drop down button, which includes
      * all padding, border and focus line widths the button uses,
      * as well as the minimum arrow size and its padding
      * */
     GtkRequisition requisition;
     ensure_combo_box_entry_widgets();
 
-    gtk_widget_size_request(gDropdownButtonWidget, &requisition);
+    gtk_widget_size_request(gComboBoxEntryButtonWidget, &requisition);
     *width = requisition.width;
     *height = requisition.height;
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
 moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height)
@@ -2697,16 +2695,29 @@ moz_gtk_get_tab_scroll_arrow_size(gint* 
                          NULL);
 
     *height = *width = arrow_size;
 
     return MOZ_GTK_SUCCESS;
 }
 
 gint
+moz_gtk_get_downarrow_size(gint* width, gint* height)
+{
+    GtkRequisition requisition;
+    ensure_button_arrow_widget();
+
+    gtk_widget_size_request(gButtonArrowWidget, &requisition);
+    *width = requisition.width;
+    *height = requisition.height;
+
+    return MOZ_GTK_SUCCESS;
+}
+
+gint
 moz_gtk_get_toolbar_separator_width(gint* size)
 {
     gboolean wide_separators;
     gint separator_width;
     GtkStyle* style;
 
     ensure_toolbar_widget();
 
@@ -2910,23 +2921,23 @@ moz_gtk_widget_paint(GtkThemeWidgetType 
         return moz_gtk_entry_paint(drawable, rect, cliprect, state,
                                    gEntryWidget, direction);
         break;
     case MOZ_GTK_DROPDOWN:
         return moz_gtk_option_menu_paint(drawable, rect, cliprect, state,
                                          direction);
         break;
     case MOZ_GTK_DROPDOWN_ARROW:
-        return moz_gtk_dropdown_arrow_paint(drawable, rect, cliprect, state,
-                                            flags, direction);
+        return moz_gtk_combo_box_entry_button_paint(drawable, rect, cliprect,
+                                                    state, flags, direction);
         break;
     case MOZ_GTK_DROPDOWN_ENTRY:
         ensure_combo_box_entry_widgets();
         return moz_gtk_entry_paint(drawable, rect, cliprect, state,
-                                   gDropdownEntryWidget, direction);
+                                   gComboBoxEntryTextareaWidget, direction);
         break;
     case MOZ_GTK_CHECKBUTTON_CONTAINER:
     case MOZ_GTK_RADIOBUTTON_CONTAINER:
         return moz_gtk_container_paint(drawable, rect, cliprect, state,
                                        (widget == MOZ_GTK_RADIOBUTTON_CONTAINER),
                                        direction);
         break;
     case MOZ_GTK_CHECKBUTTON_LABEL:
@@ -3029,29 +3040,30 @@ moz_gtk_shutdown()
         gtk_widget_destroy(gTooltipWidget);
     /* This will destroy all of our widgets */
     if (gProtoWindow)
         gtk_widget_destroy(gProtoWindow);
 
     gProtoWindow = NULL;
     gButtonWidget = NULL;
     gToggleButtonWidget = NULL;
+    gButtonArrowWidget = NULL;
     gCheckboxWidget = NULL;
     gRadiobuttonWidget = NULL;
     gHorizScrollbarWidget = NULL;
     gVertScrollbarWidget = NULL;
     gSpinWidget = NULL;
     gHScaleWidget = NULL;
     gVScaleWidget = NULL;
     gEntryWidget = NULL;
-    gArrowWidget = NULL;
     gOptionMenuWidget = NULL;
-    gDropdownButtonWidget = NULL;
-    gDropdownEntryWidget = NULL;
     gComboBoxEntryWidget = NULL;
+    gComboBoxEntryButtonWidget = NULL;
+    gComboBoxEntryArrowWidget = NULL;
+    gComboBoxEntryTextareaWidget = NULL;
     gHandleBoxWidget = NULL;
     gToolbarWidget = NULL;
     gStatusbarWidget = NULL;
     gFrameWidget = NULL;
     gProgressWidget = NULL;
     gTabWidget = NULL;
     gTooltipWidget = NULL;
     gMenuBarWidget = NULL;
--- a/widget/src/gtk2/gtkdrawing.h
+++ b/widget/src/gtk2/gtkdrawing.h
@@ -336,28 +336,37 @@ moz_gtk_get_scrollbar_metrics(MozGtkScro
 
 /**
  * Get the desired size of a dropdown arrow button
  * width:   [OUT] the desired width
  * height:  [OUT] the desired height
  *
  * returns:    MOZ_GTK_SUCCESS if there was no error, an error code otherwise
  */
-gint moz_gtk_get_dropdown_arrow_size(gint* width, gint* height);
+gint moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height);
 
 /**
  * Get the desired size of a scroll arrow widget
  * width:   [OUT] the desired width
  * height:  [OUT] the desired height
  *
  * returns:    MOZ_GTK_SUCCESS if there was no error, an error code otherwise
  */
 gint moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height);
 
 /**
+ * Get the desired size of a toolbar button dropdown arrow
+ * width:   [OUT] the desired width
+ * height:  [OUT] the desired height
+ *
+ * returns:    MOZ_GTK_SUCCESS if there was no error, an error code otherwise
+ */
+gint moz_gtk_get_downarrow_size(gint* width, gint* height);
+
+/**
  * Get the desired size of a toolbar separator
  * size:    [OUT] the desired width
  *
  * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
  */
 gint moz_gtk_get_toolbar_separator_width(gint* size);
 
 /**
--- a/widget/src/gtk2/nsNativeThemeGTK.cpp
+++ b/widget/src/gtk2/nsNativeThemeGTK.cpp
@@ -1077,17 +1077,18 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
     case NS_THEME_TAB_SCROLLARROW_FORWARD:
       {
         moz_gtk_get_tab_scroll_arrow_size(&aResult->width, &aResult->height);
         *aIsOverridable = PR_FALSE;
       }
       break;
   case NS_THEME_DROPDOWN_BUTTON:
     {
-      moz_gtk_get_dropdown_arrow_size(&aResult->width, &aResult->height);
+      moz_gtk_get_combo_box_entry_button_size(&aResult->width,
+                                              &aResult->height);
       *aIsOverridable = PR_FALSE;
     }
     break;
   case NS_THEME_MENUSEPARATOR:
     {
       gint separator_height;
 
       moz_gtk_get_menu_separator_height(&separator_height);
@@ -1110,17 +1111,22 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
       }
 
       // Include space for the indicator and the padding around it.
       aResult->width = indicator_size;
       aResult->height = indicator_size;
       *aIsOverridable = PR_FALSE;
     }
     break;
-
+  case NS_THEME_TOOLBAR_BUTTON_DROPDOWN:
+    {
+        moz_gtk_get_downarrow_size(&aResult->width, &aResult->height);
+        *aIsOverridable = PR_FALSE;
+    }
+    break;
   case NS_THEME_CHECKBOX_CONTAINER:
   case NS_THEME_RADIO_CONTAINER:
   case NS_THEME_CHECKBOX_LABEL:
   case NS_THEME_RADIO_LABEL:
   case NS_THEME_BUTTON:
   case NS_THEME_TOOLBAR_BUTTON:
   case NS_THEME_TREEVIEW_HEADER_CELL:
     {
--- a/widget/src/windows/nsNativeDragTarget.h
+++ b/widget/src/windows/nsNativeDragTarget.h
@@ -37,19 +37,22 @@
 #ifndef _nsNativeDragTarget_h_
 #define _nsNativeDragTarget_h_
 
 #include "nsGUIEvent.h"
 #include "nsCOMPtr.h"
 #include "nsIDragSession.h"
 #include <ole2.h>
 #include <shlobj.h>
-#ifndef WINCE
+
+#ifndef WINCE 
 #ifndef IDropTargetHelper
+#ifndef __MINGW32__   // MingW does not provide shobjidl.h.
 #include <shobjidl.h> // Vista drag image interfaces
+#endif  // MingW
 #endif
 #endif  // WINCE
 
 class nsIDragService;
 class nsIWidget;
 
 struct IDataObject;
 
--- a/widget/src/windows/nsNativeThemeWin.cpp
+++ b/widget/src/windows/nsNativeThemeWin.cpp
@@ -1035,18 +1035,21 @@ nsNativeThemeWin::GetThemePartAndState(n
       /* On vista, in HTML, we use CBP_DROPBORDER instead of DROPFRAME for HTML content;
        * this gives us the thin outline in HTML content, instead of the gradient-filled
        * background */
       if (isHTML)
         aPart = CBP_DROPBORDER;
       else
         aPart = CBP_DROPFRAME;
 
-      PRBool isOpen = CheckBooleanAttr(aFrame, nsWidgetAtoms::open);
-      if (isOpen) {
+      if (IsDisabled(aFrame)) {
+        aState = TS_DISABLED;
+      } else if (IsReadOnly(aFrame)) {
+        aState = TS_NORMAL;
+      } else if (CheckBooleanAttr(aFrame, nsWidgetAtoms::open)) {
         aState = TS_ACTIVE;
       } else {
         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
         if (isHTML && eventState & NS_EVENT_STATE_FOCUS)
           aState = TS_ACTIVE;
         else if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
           aState = TS_ACTIVE;
         else if (eventState & NS_EVENT_STATE_HOVER)
--- a/xpcom/base/nscore.h
+++ b/xpcom/base/nscore.h
@@ -240,16 +240,36 @@
 #define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \
   typeof(&class::func) name
 #else
 #define NS_STDCALL_FUNCPROTO(ret, name, class, func, args) \
   ret (NS_STDCALL class::*name) args
 #endif
 
 /**
+ * Deprecated declarations.
+ */
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# define NS_DEPRECATED __attribute__((deprecated))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
+# define NS_DEPRECATED __declspec(deprecated)
+#else
+# define NS_DEPRECATED
+#endif
+
+/**
+ * Attributes defined to help Dehydra GCC analysis.	
+ */
+#ifdef DEHYDRA_GCC
+# define NS_SCRIPTABLE __attribute__((user("script")))
+#else
+# define NS_SCRIPTABLE
+#endif
+
+/**
  * Generic API modifiers which return the standard XPCOM nsresult type
  */
 #define NS_IMETHOD          NS_IMETHOD_(nsresult)
 #define NS_IMETHODIMP       NS_IMETHODIMP_(nsresult)
 #define NS_METHOD           NS_METHOD_(nsresult)
 #define NS_CALLBACK(_name)  NS_CALLBACK_(nsresult, _name)
 
 /**
--- a/xpcom/io/nsFastLoadFile.cpp
+++ b/xpcom/io/nsFastLoadFile.cpp
@@ -1395,18 +1395,18 @@ nsFastLoadFileWriter::StartMuxedDocument
                                                 PL_DHASH_LOOKUP));
         NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(mCurrentDocumentMapEntry),
                      "mCurrentDocumentMapEntry lost during table growth?!");
 
         // Refresh saveGeneration for use below when initializing uriMapEntry.
         saveGeneration = mDocumentMap.generation;
     }
 
-    NS_ASSERTION(docMapEntry->mString == nsnull,
-                 "redundant multiplexed document?");
+    NS_WARN_IF_FALSE(docMapEntry->mString == nsnull,
+                     "redundant multiplexed document?");
     if (docMapEntry->mString)
         return NS_ERROR_UNEXPECTED;
 
     void* spec = nsMemory::Clone(aURISpec, strlen(aURISpec) + 1);
     if (!spec)
         return NS_ERROR_OUT_OF_MEMORY;
     docMapEntry->mString = reinterpret_cast<const char*>(spec);
     docMapEntry->mURI = aURI;
--- a/xpcom/reflect/xptcall/src/md/unix/Makefile.in
+++ b/xpcom/reflect/xptcall/src/md/unix/Makefile.in
@@ -71,17 +71,17 @@ ifeq (Darwin,$(OS_ARCH))
 DEFINES		+= -DKEEP_STACK_16_BYTE_ALIGNED
 endif
 endif
 endif
 #
 # New code for Linux, et. al., with gcc
 # Migrate other platforms here after testing
 #
-ifneq (,$(filter Linux,$(OS_ARCH)))
+ifneq (,$(filter Linux GNU_%,$(OS_ARCH)))
 # Linux/x86-64
 ifeq (x86_64,$(OS_TEST))
 CPPSRCS		:= xptcinvoke_x86_64_linux.cpp xptcstubs_x86_64_linux.cpp
 else
 ifeq (86,$(findstring 86,$(OS_TEST)))
 CPPSRCS		:= xptcinvoke_gcc_x86_unix.cpp xptcstubs_gcc_x86_unix.cpp
 endif
 endif
--- a/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h
+++ b/xpcom/reflect/xptcall/src/md/unix/xptc_platforms_unixish_x86.h
@@ -62,17 +62,17 @@
 * #    error "need TYPE1 or TYPE2 for NTO"
 * #  endif
 * #elif defined(__BEOS__) 
 *
 *  and so on....
 *
 */
 
-#if defined(LINUX)
+#if defined(LINUX) || (defined(__GLIBC__) && defined(__FreeBSD_kernel__))
 
 #if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 7)
 /* Old gcc 2.7.x.x.  What does gcc 2.8.x do?? */
 #define CFRONT_STYLE_THIS_ADJUST
 #else
 /* egcs and later */
 #define THUNK_BASED_THIS_ADJUST
 #endif
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -147,8 +147,18 @@ check::
 	@echo "Running TestVersionComparator tests"
 	@$(PERL) -w $(srcdir)/TestVersionComparatorRunner.pl "$(RUN_TEST_PROGRAM) $(FINAL_TARGET)/TestVersionComparator$(BIN_SUFFIX)"
 	@echo "Running nsTextFormatter tests"
 	@$(RUN_TEST_PROGRAM) $(FINAL_TARGET)/TestTextFormatter$(BIN_SUFFIX)
 	@$(EXIT_ON_ERROR) \
 	for f in $(CPP_UNIT_TESTS); do \
 	  XPCOM_DEBUG_BREAK=stack-and-abort $(RUN_TEST_PROGRAM) $(DIST)/bin/$$f; \
 	done
+	@echo "Running XPIDL tests"
+	$(XPIDL_COMPILE) -m header $(srcdir)/TestScriptable.idl
+	@if grep Notscriptable TestScriptable.h | grep -q NS_SCRIPTABLE ; then \
+		echo "Nonscriptable object marked scriptable by xpidl"; \
+		exit 1; \
+	fi
+	@if test $$( grep 'NS_IMETHOD[^I].*Scriptable' TestScriptable.h | grep -v -c NS_SCRIPTABLE ) != 0 ; then \
+		echo "Scriptable object marked nonscriptable by xpidl"; \
+		exit 1; \
+	fi
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/TestScriptable.idl
@@ -0,0 +1,21 @@
+
+[scriptable, uuid(76d74662-0eae-404c-9d1f-697c0e321c0a)]
+interface testScriptableInterface {
+  readonly attribute long scriptable_attr1;
+  attribute long scriptable_attr2;
+  [noscript] readonly attribute long notscriptable_attr1;
+  [noscript] attribute long notscriptable_attr2;
+
+  void scriptable_method1();
+  [noscript] void notscriptable_method1();
+  [notxpcom] void notscriptable_method2();
+  [noscript, notxpcom] void notscriptable_method3();
+};
+
+[uuid(76d74662-0eae-404c-9d1f-697c0e321c0a)]
+interface testNotscriptableInterface {
+  readonly attribute long notscriptable_attr1;
+  attribute long notscriptable_attr2;
+
+  void notscriptable_method1();
+};
--- a/xpcom/typelib/xpidl/xpidl.h
+++ b/xpcom/typelib/xpidl/xpidl.h
@@ -270,9 +270,12 @@ verify_interface_declaration(IDL_tree me
  * it's of the form native <idl-name>(<c++-name>)
  */
 gboolean
 check_native(TreeState *state);
 
 void
 printlist(FILE *outfile, GSList *slist);
 
+gboolean
+is_method_scriptable(IDL_tree method_tree, IDL_tree ident);
+
 #endif /* __xpidl_h */
--- a/xpcom/typelib/xpidl/xpidl_header.c
+++ b/xpcom/typelib/xpidl/xpidl_header.c
@@ -141,17 +141,17 @@ static gboolean
 interface(TreeState *state)
 {
     IDL_tree iface = state->tree, iter, orig;
     char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
     char *classNameUpper = NULL;
     char *classNameImpl = NULL;
     char *cp;
     gboolean ok = TRUE;
-    gboolean keepvtable;
+    gboolean keepvtable, scriptable, deprecated;
     const char *iid;
     const char *name_space;
     struct nsID id;
     char iid_parsed[UUID_LENGTH];
     GSList *doc_comments = IDL_IDENT(IDL_INTERFACE(iface).ident).comments;
 
     if (!verify_interface_declaration(iface))
         return FALSE;
@@ -228,21 +228,30 @@ interface(TreeState *state)
     for (iter = IDL_INTERFACE(state->tree).body;
          iter != NULL;
          iter = IDL_LIST(iter).next)
     {
         IDL_tree data = IDL_LIST(iter).data;
         if (IDL_NODE_TYPE(data) == IDLN_CODEFRAG)
             keepvtable = TRUE;
     }
-    
+   
+    scriptable = deprecated = FALSE;
+    if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable"))
+        scriptable = TRUE;
+    if (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "deprecated"))
+        deprecated = TRUE;
+
     /* The interface declaration itself. */
     fprintf(state->file,
-            "class %s%s",
-            (keepvtable ? "" : "NS_NO_VTABLE "), className);
+            "class %s%s%s%s",
+            (keepvtable ? "" : "NS_NO_VTABLE "),
+            (scriptable ? "NS_SCRIPTABLE " : ""),
+            (deprecated ? "NS_DEPRECATED " : ""),
+            className);
     
     if ((iter = IDL_INTERFACE(iface).inheritance_spec)) {
         fputs(" : ", state->file);
         if (IDL_LIST(iter).next != NULL) {
             IDL_tree_error(iter,
                            "multiple inheritance is not supported by xpidl");
             FAIL;
         }
@@ -741,18 +750,24 @@ write_type(IDL_tree type_tree, gboolean 
  *  AS_CALL writes 'foo(bar, sil)'
  */
 static gboolean
 write_attr_accessor(IDL_tree attr_tree, FILE * outfile,
                     gboolean getter, int mode, const char *className)
 {
     char *attrname = ATTR_IDENT(attr_tree).str;
     const char *binaryname;
+    IDL_tree ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data;
 
     if (mode == AS_DECL) {
+        if (IDL_tree_property_get(ident, "deprecated"))
+            fputs("NS_DEPRECATED ", outfile);
+        if (is_method_scriptable(attr_tree, ident))
+            fputs("NS_SCRIPTABLE ", outfile);
+
         fputs("NS_IMETHOD ", outfile);
     } else if (mode == AS_IMPL) {
         fprintf(outfile, "NS_IMETHODIMP %s::", className);
     }
     fprintf(outfile, "%cet",
             getter ? 'G' : 'S');
     binaryname = IDL_tree_property_get(ATTR_DECLS(attr_tree), "binaryname");
     if (binaryname) {
@@ -1018,16 +1033,21 @@ write_method_signature(IDL_tree method_t
     gboolean no_generated_args = TRUE;
     gboolean op_notxpcom =
         (IDL_tree_property_get(op->ident, "notxpcom") != NULL);
     const char *name;
     const char *binaryname;
     IDL_tree iter;
 
     if (mode == AS_DECL) {
+        if (IDL_tree_property_get(op->ident, "deprecated"))
+            fputs("NS_DEPRECATED ", outfile);
+        if (is_method_scriptable(method_tree, op->ident))
+            fputs("NS_SCRIPTABLE ", outfile);
+
         if (op_notxpcom) {
             fputs("NS_IMETHOD_(", outfile);
             if (!write_type(op->op_type_spec, FALSE, outfile))
                 return FALSE;
             fputc(')', outfile);
         } else {
             fputs("NS_IMETHOD", outfile);
         }
--- a/xpcom/typelib/xpidl/xpidl_java.c
+++ b/xpcom/typelib/xpidl/xpidl_java.c
@@ -139,16 +139,65 @@ static char* nonIDLIfaces[] = {
 #define PRIVDATA(state)     (((struct java_priv_data *)state->priv))
 #define KEYWORDS(state)     (((struct java_priv_data *)state->priv)->keywords)
 
 static void
 write_indent(FILE *outfile) {
     fputs("  ", outfile);
 }
 
+static GSList*
+add_deprecated(GSList *comments)
+{
+    GSList *last;
+    char *buffer;
+    char *replaced;
+    const char deprecated[] = "* @deprecated */";
+
+    /* Handle the easy case: no documentation. */
+    if (comments == NULL) {
+        buffer = malloc(sizeof(deprecated)+2);
+        buffer[0] = '/';
+        buffer[1] = '*';
+        strcpy(buffer+2, deprecated);
+
+        return g_slist_append(comments, buffer);
+    }
+
+    /* xpidl is so nice in that they give us the data as a single node.
+     * We are going to have to (very hackishly) strip out the the end of the
+     * documentation comment, add the tag, and then pop it back together.
+     */
+
+    /* Step 1: Move the comment into a larger buffer, so that we can have
+     * more space to work with.
+     */
+    last = g_slist_last(comments);
+    buffer = last->data;
+    replaced = (char *)malloc(strlen(buffer) + sizeof(deprecated));
+    strcpy(replaced, buffer);
+    last->data = replaced;
+    free(buffer);
+    
+    /* Now replaced has the comment, with a large enough buffer to put in the
+     * @deprecated tag. We search for the last / in hopes that the previous
+     * character is the * we're looking for...
+     */
+    buffer = strrchr(replaced, '/');
+    if (buffer == NULL || buffer == replaced || buffer[-1] == '*') {
+        /* We can't find a '/', so there's no comment, or this is not the end
+         * of a comment, so we'll ignore adding the deprecated tag.
+         */
+        return comments;
+    }
+    /* buffer now points to '*' '/'. Overwrite both. */
+    strcpy(buffer-1, deprecated);
+    return comments;
+}
+
 static gboolean
 write_classname_iid_define(FILE *file, const char *className)
 {
     const char *iidName;
     if (className[0] == 'n' && className[1] == 's') {
         /* backcompat naming styles */
         fputs("NS_", file);
         iidName = className + 2;
@@ -326,16 +375,23 @@ interface_declaration(TreeState *state)
         }
     } else {
         IDL_tree_error(state->tree, "interface %s lacks a uuid attribute\n", 
                        interface_name);
         return FALSE;
     }
 
     /*
+     * Add deprecated tags if the interface is deprecated
+     */
+    if (IDL_tree_property_get(IDL_INTERFACE(interface).ident, "deprecated")) {
+        doc_comments = add_deprecated(doc_comments);
+    }
+
+    /*
      * Write any interface comments
      */
     if (doc_comments != NULL)
         printlist(state->file, doc_comments);
 
     /*
      * Write "public interface <foo>"
      */
@@ -771,16 +827,23 @@ method_declaration(TreeState *state)
     {
         IDL_tree iface = IDL_NODE_UP(IDL_NODE_UP(state->tree));
         char *className = IDL_IDENT(IDL_INTERFACE(iface).ident).str;
         if (strcmp(className, "nsIXPCSecurityManager") == 0)
             return TRUE;
     }
 #endif
 
+    /*
+     * Add deprecated tags if the interface is deprecated
+     */
+    if (IDL_tree_property_get(method->ident, "deprecated")) {
+        doc_comments = add_deprecated(doc_comments);
+    }
+
     if (doc_comments != NULL) {
         write_indent(state->file);
         printlist(state->file, doc_comments);
     }
 
     /*
      * Write return type
      * Unlike C++ headers, Java interfaces return the declared 
@@ -1008,16 +1071,24 @@ attribute_declaration(TreeState *state)
     if (IDL_tree_property_get(ATTR_PROPS(state->tree), "notxpcom") ||
         IDL_tree_property_get(ATTR_PROPS(state->tree), "noscript"))
         return TRUE;
 #endif
 
     doc_comments =
         IDL_IDENT(IDL_LIST(IDL_ATTR_DCL
                            (state->tree).simple_declarations).data).comments;
+
+    /*
+     * Add deprecated tags if the interface is deprecated
+     */
+    if (IDL_tree_property_get(ATTR_PROPS(state->tree), "deprecated")) {
+        doc_comments = add_deprecated(doc_comments);
+    }
+
     if (doc_comments != NULL) {
         write_indent(state->file);
         printlist(state->file, doc_comments);
     }
 
     /*
      * Write the proper Java return value for the get operation
      */
--- a/xpcom/typelib/xpidl/xpidl_util.c
+++ b/xpcom/typelib/xpidl/xpidl_util.c
@@ -272,67 +272,97 @@ matches_nsIFoo(const char* attribute_nam
         return FALSE;
     if (matches_IFoo(attribute_name + 2))
         return TRUE;
     if (IsNot_AlphaLower(attribute_name[2]))
         return FALSE;
     return matches_IFoo(attribute_name + 3);
 }
 
+/**
+ * Returns TRUE if the method is probably scriptable, FALSE otherwise.
+ * The first parameter may also be an attr_tree parameter, since these two are
+ * the same with respect to discovering the interface node.
+ */
+gboolean
+is_method_scriptable(IDL_tree method_tree, IDL_tree ident)
+{
+    IDL_tree iface;
+    gboolean scriptable_interface;
+    
+    /*
+     * Look up the tree to find the interface. If we can't find the interface,
+     * then the caller is being called on an incorrect tree. If we find it, we
+     * see if it's [scriptable] and duly note it.
+     */
+    if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
+        IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree))) 
+        == IDLN_INTERFACE)
+    {
+        scriptable_interface =
+            (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
+             != NULL);
+    } else {
+        IDL_tree_error(method_tree,
+                       "is_method_scriptable called on a non-interface?");
+        return FALSE;
+    }
+
+    /* If the interface isn't scriptable, the method sure can't be... */
+    if (!scriptable_interface)
+      return FALSE;
+
+    /* [notxpcom] implies [noscript] */
+    if (IDL_tree_property_get(ident, "notxpcom") != NULL)
+      return FALSE;
+
+    /* [noscript] methods obviously aren't scriptable */
+    if (IDL_tree_property_get(ident, "noscript") != NULL)
+      return FALSE;
+
+    /* The interface is scriptable, so therefore the method is, if the
+     * interfaces are accessible. That's good enough for this method.
+     */
+    return TRUE;
+}
+
 gboolean
 verify_attribute_declaration(IDL_tree attr_tree)
 {
     IDL_tree iface;
     IDL_tree ident;
     IDL_tree attr_type;
-    gboolean scriptable_interface;
 
     /* We don't support attributes named IID, conflicts with static GetIID 
      * member. The conflict is due to certain compilers (VC++) choosing a
      * different vtable order, placing GetIID at the beginning regardless
      * of it's placement
      */
     if (strcmp(
         IDL_IDENT(
             IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data).str, 
         "IID") == 0) {
         IDL_tree_error(attr_tree,
                        "Attributes named IID not supported, causes vtable "
                        "ordering problems");
         return FALSE;
     }
-    /* 
-     * Verify that we've been called on an interface, and decide if the
-     * interface was marked [scriptable].
-     */
-    if (IDL_NODE_UP(attr_tree) && IDL_NODE_UP(IDL_NODE_UP(attr_tree)) &&
-        IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(attr_tree))) 
-        == IDLN_INTERFACE)
-    {
-        scriptable_interface =
-            (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
-             != NULL);
-    } else {
-        IDL_tree_error(attr_tree,
-                    "verify_attribute_declaration called on a non-interface?");
-        return FALSE;
-    }
 
     /*
      * Grab the first of the list of idents and hope that it'll
      * say scriptable or no.
      */
     ident = IDL_LIST(IDL_ATTR_DCL(attr_tree).simple_declarations).data;
 
     /*
      * If the interface isn't scriptable, or the attribute is marked noscript,
-     * there's no need to check.
+     * there's no need to check. This also verifies that we've been called on
+     * an interface.
      */
-    if (!scriptable_interface ||
-        IDL_tree_property_get(ident, "noscript") != NULL)
+    if (!is_method_scriptable(attr_tree, ident))
         return TRUE;
 
     /*
      * If it should be scriptable, check that the type is non-native. nsid,
      * domstring, utf8string, cstring, astring are exempted.
      */
     attr_type = IDL_ATTR_DCL(attr_tree).param_type_spec;
 
@@ -528,28 +558,26 @@ check_param_attribute(IDL_tree method_tr
                 return FALSE;
             }
         }
     }
 
     return TRUE;
 }
 
-
 /*
  * Common method verification code, called by *op_dcl in the various backends.
  */
 gboolean
 verify_method_declaration(IDL_tree method_tree)
 {
     struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree);
     IDL_tree iface;
     IDL_tree iter;
     gboolean notxpcom;
-    gboolean scriptable_interface;
     gboolean scriptable_method;
     gboolean seen_retval = FALSE;
     gboolean hasoptional = PR_FALSE;
     const char *method_name = IDL_IDENT(IDL_OP_DCL(method_tree).ident).str;
 
     /* We don't support attributes named IID, conflicts with static GetIID 
      * member. The conflict is due to certain compilers (VC++) choosing a
      * different vtable order, placing GetIID at the beginning regardless
@@ -563,46 +591,22 @@ verify_method_declaration(IDL_tree metho
     }
     if (op->f_varargs) {
         /* We don't currently support varargs. */
         IDL_tree_error(method_tree, "varargs are not currently supported");
         return FALSE;
     }
 
     /* 
-     * Verify that we've been called on an interface, and decide if the
-     * interface was marked [scriptable].
+     * Decide if we are a scriptable method, or if we were are notxpcom.
+     * In doing so, we also verify that we've been called on an interface.
      */
-    if (IDL_NODE_UP(method_tree) && IDL_NODE_UP(IDL_NODE_UP(method_tree)) &&
-        IDL_NODE_TYPE(iface = IDL_NODE_UP(IDL_NODE_UP(method_tree))) 
-        == IDLN_INTERFACE)
-    {
-        scriptable_interface =
-            (IDL_tree_property_get(IDL_INTERFACE(iface).ident, "scriptable")
-             != NULL);
-    } else {
-        IDL_tree_error(method_tree,
-                       "verify_method_declaration called on a non-interface?");
-        return FALSE;
-    }
-
-    /*
-     * Require that any method in an interface marked as [scriptable], that
-     * *isn't* scriptable because it refers to some native type, be marked
-     * [noscript] or [notxpcom].
-     *
-     * Also check that iid_is points to nsid, and length_is, size_is points
-     * to unsigned long.
-     */
+    scriptable_method = is_method_scriptable(method_tree, op->ident);
     notxpcom = IDL_tree_property_get(op->ident, "notxpcom") != NULL;
 
-    scriptable_method = scriptable_interface &&
-        !notxpcom &&
-        IDL_tree_property_get(op->ident, "noscript") == NULL;
-
     /* Loop through the parameters and check. */
     for (iter = op->parameter_dcls; iter; iter = IDL_LIST(iter).next) {
         IDL_tree param = IDL_LIST(iter).data;
         IDL_tree param_type =
             IDL_PARAM_DCL(param).param_type_spec;
         IDL_tree simple_decl =
             IDL_PARAM_DCL(param).simple_declarator;
         const char *param_name = IDL_IDENT(simple_decl).str;