merge with mozilla-central
authorOleg Romashin <romaxa@gmail.com>
Sat, 16 Aug 2008 03:39:26 -0400
changeset 16962 cae882483daebb4c62786d0316973cd9ab8f045c
parent 16961 9999736a2cf4412ce2aff9e05a677a7c23e2f6ab (current diff)
parent 16729 f593ae83554f9ac69edcc1de1b8316874502e76a (diff)
child 16963 9095dca03bd2959caa952a212c54453cc9198789
push idunknown
push userunknown
push dateunknown
milestone1.9.1a2pre
merge with mozilla-central
config/autoconf.mk.in
configure.in
content/canvas/test/test_2d.drawImage.self.html
content/canvas/test/test_2d.fillStyle.parse.flavor.html
content/canvas/test/test_2d.gradient.radial.invalid.html
content/canvas/test/test_2d.imageData.get.nonpositive.html
content/canvas/test/test_2d.imageData.get.properties.html
content/canvas/test/test_2d.imageData.get.smallest.html
content/canvas/test/test_2d.imageData.get.sourcepos.html
content/canvas/test/test_2d.imageData.get.sourcesize.html
content/canvas/test/test_2d.imageData.get.values.html
content/canvas/test/test_2d.imageData.put.type.correct.html
content/canvas/test/test_2d.imageData.put.type.extra.html
content/canvas/test/test_2d.imageData.put.type.invalidsize.html
content/canvas/test/test_2d.imageData.put.type.invalidvalues.html
content/canvas/test/test_2d.imageData.put.type.missing.html
content/canvas/test/test_2d.imageData.put.type.onepixel.html
content/canvas/test/test_2d.line.cap.zerobezier.round.html
content/canvas/test/test_2d.line.cap.zeroline.round.html
content/canvas/test/test_2d.line.cap.zeroline.square.html
content/canvas/test/test_2d.line.invalid.lineWidth.html
content/canvas/test/test_2d.line.invalid.miterLimit.html
content/canvas/test/test_2d.line.join.zeroline.corner.html
content/canvas/test/test_2d.line.join.zeroline.join.html
content/canvas/test/test_2d.line.lineCap.butt.html
content/canvas/test/test_2d.line.lineCap.round.html
content/canvas/test/test_2d.line.lineCap.square.html
content/canvas/test/test_2d.line.lineJoin.bevel.html
content/canvas/test/test_2d.line.lineJoin.miter.html
content/canvas/test/test_2d.line.lineJoin.round.html
content/canvas/test/test_2d.line.lineWidth.basic.html
content/canvas/test/test_2d.line.lineWidth.transformed.html
content/canvas/test/test_2d.path.arc.zero.3.html
content/canvas/test/test_2d.path.arc.zero.4.html
content/canvas/test/test_2d.path.arc.zero.5.html
content/canvas/test/test_2d.path.arc.zero.6.html
content/canvas/test/test_2d.path.arc.zero.html
content/canvas/test/test_2d.path.transformation.multiple.1.html
content/canvas/test/test_2d.path.transformation.multiple.2.html
content/canvas/test/test_2d.path.transformation.multiple.3.html
content/canvas/test/test_2d.pattern.paint.coord3.html
content/canvas/test/test_2d.pattern.repeat.missing.html
content/canvas/test/test_2d.transformation.rotate.infinity.html
content/canvas/test/test_2d.transformation.rotate.nan.html
content/canvas/test/test_2d.transformation.rotate.neginfinity.html
content/canvas/test/test_2d.type.name.html
dom/public/idl/geolocation/nsIDOMGeolocation.idl
dom/public/idl/geolocation/nsIDOMGeolocationCallback.idl
dom/public/idl/geolocation/nsIDOMGeolocator.idl
dom/public/idl/geolocation/nsIDOMNavigatorGeolocator.idl
dom/tests/mochitest/geolocation/geolocator.html
extensions/inspector/Makefile.in
extensions/inspector/base/Makefile.in
extensions/inspector/base/js/Makefile.in
extensions/inspector/base/js/inspector-cmdline.js
extensions/inspector/build/Makefile.in
extensions/inspector/build/install.js
extensions/inspector/install.rdf
extensions/inspector/jar.mn
extensions/inspector/makefiles.sh
extensions/inspector/resources/Makefile.in
extensions/inspector/resources/content/Flasher.js
extensions/inspector/resources/content/ViewerRegistry.js
extensions/inspector/resources/content/browserOverlay.xul
extensions/inspector/resources/content/commandOverlay.xul
extensions/inspector/resources/content/editingOverlay.xul
extensions/inspector/resources/content/extensions/multipanel.css
extensions/inspector/resources/content/extensions/multipanel.xml
extensions/inspector/resources/content/extensions/titledSplitter.css
extensions/inspector/resources/content/extensions/titledSplitter.xml
extensions/inspector/resources/content/extensions/treeEditable.css
extensions/inspector/resources/content/extensions/treeEditable.xml
extensions/inspector/resources/content/extensions/wsm-colorpicker.js
extensions/inspector/resources/content/hooks.js
extensions/inspector/resources/content/inspector.css
extensions/inspector/resources/content/inspector.js
extensions/inspector/resources/content/inspector.xml
extensions/inspector/resources/content/inspector.xul
extensions/inspector/resources/content/inspectorOverlay.xul
extensions/inspector/resources/content/jsutil/events/ObserverManager.js
extensions/inspector/resources/content/jsutil/rdf/RDFArray.js
extensions/inspector/resources/content/jsutil/rdf/RDFU.js
extensions/inspector/resources/content/jsutil/system/DiskSearch.js
extensions/inspector/resources/content/jsutil/system/FilePickerUtils.js
extensions/inspector/resources/content/jsutil/system/PrefUtils.js
extensions/inspector/resources/content/jsutil/system/file.js
extensions/inspector/resources/content/jsutil/xpcom/XPCU.js
extensions/inspector/resources/content/jsutil/xul/DNDUtils.js
extensions/inspector/resources/content/jsutil/xul/FrameExchange.js
extensions/inspector/resources/content/jsutil/xul/inBaseTreeView.js
extensions/inspector/resources/content/jsutil/xul/inFormManager.js
extensions/inspector/resources/content/jsutil/xul/inTreeBuilder.js
extensions/inspector/resources/content/keysetOverlay.xul
extensions/inspector/resources/content/object.js
extensions/inspector/resources/content/object.xul
extensions/inspector/resources/content/popupOverlay.xul
extensions/inspector/resources/content/prefs/inspector.js
extensions/inspector/resources/content/prefs/pref-inspector.js
extensions/inspector/resources/content/prefs/pref-inspector.xul
extensions/inspector/resources/content/prefs/pref-sidebar.js
extensions/inspector/resources/content/prefs/prefsOverlay.xul
extensions/inspector/resources/content/res/search-registry.rdf
extensions/inspector/resources/content/res/viewer-registry.rdf
extensions/inspector/resources/content/res/winInspectorMain.ico
extensions/inspector/resources/content/res/winInspectorMain.xpm
extensions/inspector/resources/content/res/winInspectorMain16.xpm
extensions/inspector/resources/content/res/winInspectorMainOS2.ico
extensions/inspector/resources/content/sidebar.js
extensions/inspector/resources/content/sidebar.xul
extensions/inspector/resources/content/statusbarOverlay.xul
extensions/inspector/resources/content/tasksOverlay-ff.xul
extensions/inspector/resources/content/tasksOverlay-sb.xul
extensions/inspector/resources/content/tasksOverlay-tb.xul
extensions/inspector/resources/content/tasksOverlay.xul
extensions/inspector/resources/content/tests/allskin.xul
extensions/inspector/resources/content/toolboxOverlay.xul
extensions/inspector/resources/content/util.dtd
extensions/inspector/resources/content/utilWindow.xul
extensions/inspector/resources/content/utils.js
extensions/inspector/resources/content/venkmanOverlay.xul
extensions/inspector/resources/content/viewers/accessibleEvent/accessibleEvent.js
extensions/inspector/resources/content/viewers/accessibleEvent/accessibleEvent.xul
extensions/inspector/resources/content/viewers/accessibleEvents/accessibleEvents.js
extensions/inspector/resources/content/viewers/accessibleEvents/accessibleEvents.xul
extensions/inspector/resources/content/viewers/accessibleObject/accessibleObject.js
extensions/inspector/resources/content/viewers/accessibleObject/accessibleObject.xul
extensions/inspector/resources/content/viewers/accessibleProps/accessibleProps.js
extensions/inspector/resources/content/viewers/accessibleProps/accessibleProps.xul
extensions/inspector/resources/content/viewers/accessibleRelations/accessibleRelations.js
extensions/inspector/resources/content/viewers/accessibleRelations/accessibleRelations.xul
extensions/inspector/resources/content/viewers/accessibleTree/accessibleTree.js
extensions/inspector/resources/content/viewers/accessibleTree/accessibleTree.xul
extensions/inspector/resources/content/viewers/accessibleTree/evalJSDialog.js
extensions/inspector/resources/content/viewers/accessibleTree/evalJSDialog.xul
extensions/inspector/resources/content/viewers/boxModel/boxModel.js
extensions/inspector/resources/content/viewers/boxModel/boxModel.xul
extensions/inspector/resources/content/viewers/computedStyle/computedStyle.js
extensions/inspector/resources/content/viewers/computedStyle/computedStyle.xul
extensions/inspector/resources/content/viewers/dom/FindDialog.js
extensions/inspector/resources/content/viewers/dom/columnsDialog.js
extensions/inspector/resources/content/viewers/dom/columnsDialog.xul
extensions/inspector/resources/content/viewers/dom/commandOverlay.xul
extensions/inspector/resources/content/viewers/dom/dom.js
extensions/inspector/resources/content/viewers/dom/dom.xul
extensions/inspector/resources/content/viewers/dom/findDialog.xul
extensions/inspector/resources/content/viewers/dom/insertDialog.js
extensions/inspector/resources/content/viewers/dom/insertDialog.xul
extensions/inspector/resources/content/viewers/dom/keysetOverlay.xul
extensions/inspector/resources/content/viewers/dom/popupOverlay.xul
extensions/inspector/resources/content/viewers/dom/pseudoClassDialog.js
extensions/inspector/resources/content/viewers/dom/pseudoClassDialog.xul
extensions/inspector/resources/content/viewers/domNode/domNode.js
extensions/inspector/resources/content/viewers/domNode/domNode.xul
extensions/inspector/resources/content/viewers/domNode/domNodeDialog.js
extensions/inspector/resources/content/viewers/domNode/domNodeDialog.xul
extensions/inspector/resources/content/viewers/jsObject/evalExprDialog.js
extensions/inspector/resources/content/viewers/jsObject/evalExprDialog.xul
extensions/inspector/resources/content/viewers/jsObject/jsObject.js
extensions/inspector/resources/content/viewers/jsObject/jsObject.xul
extensions/inspector/resources/content/viewers/jsObject/jsObjectView.js
extensions/inspector/resources/content/viewers/jsObject/jsObjectViewer.js
extensions/inspector/resources/content/viewers/jsObject/jsObjectViewer.xul
extensions/inspector/resources/content/viewers/styleRules/commandOverlay.xul
extensions/inspector/resources/content/viewers/styleRules/keysetOverlay.xul
extensions/inspector/resources/content/viewers/styleRules/popupOverlay.xul
extensions/inspector/resources/content/viewers/styleRules/styleRules.js
extensions/inspector/resources/content/viewers/styleRules/styleRules.xul
extensions/inspector/resources/content/viewers/stylesheets/stylesheets.js
extensions/inspector/resources/content/viewers/stylesheets/stylesheets.xul
extensions/inspector/resources/content/viewers/xblBindings/xblBindings.js
extensions/inspector/resources/content/viewers/xblBindings/xblBindings.xul
extensions/inspector/resources/locale/Makefile.in
extensions/inspector/resources/locale/ca/editing.dtd
extensions/inspector/resources/locale/ca/inspector.dtd
extensions/inspector/resources/locale/ca/inspector.properties
extensions/inspector/resources/locale/ca/prefs.dtd
extensions/inspector/resources/locale/ca/search/findFiles.dtd
extensions/inspector/resources/locale/ca/search/junkImgs.dtd
extensions/inspector/resources/locale/ca/tasksOverlay.dtd
extensions/inspector/resources/locale/ca/viewers/boxModel.dtd
extensions/inspector/resources/locale/ca/viewers/computedStyle.dtd
extensions/inspector/resources/locale/ca/viewers/dom.dtd
extensions/inspector/resources/locale/ca/viewers/domNode.dtd
extensions/inspector/resources/locale/ca/viewers/jsObject.dtd
extensions/inspector/resources/locale/ca/viewers/styleRules.dtd
extensions/inspector/resources/locale/ca/viewers/stylesheets.dtd
extensions/inspector/resources/locale/ca/viewers/xblBindings.dtd
extensions/inspector/resources/locale/contents.rdf
extensions/inspector/resources/locale/cs/editing.dtd
extensions/inspector/resources/locale/cs/inspector.dtd
extensions/inspector/resources/locale/cs/inspector.properties
extensions/inspector/resources/locale/cs/prefs.dtd
extensions/inspector/resources/locale/cs/tasksOverlay.dtd
extensions/inspector/resources/locale/cs/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/cs/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/cs/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/cs/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/cs/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/cs/viewers/boxModel.dtd
extensions/inspector/resources/locale/cs/viewers/computedStyle.dtd
extensions/inspector/resources/locale/cs/viewers/dom.dtd
extensions/inspector/resources/locale/cs/viewers/domNode.dtd
extensions/inspector/resources/locale/cs/viewers/jsObject.dtd
extensions/inspector/resources/locale/cs/viewers/styleRules.dtd
extensions/inspector/resources/locale/cs/viewers/stylesheets.dtd
extensions/inspector/resources/locale/cs/viewers/xblBindings.dtd
extensions/inspector/resources/locale/da/editing.dtd
extensions/inspector/resources/locale/da/inspector.dtd
extensions/inspector/resources/locale/da/inspector.properties
extensions/inspector/resources/locale/da/prefs.dtd
extensions/inspector/resources/locale/da/search/findFiles.dtd
extensions/inspector/resources/locale/da/search/junkImgs.dtd
extensions/inspector/resources/locale/da/tasksOverlay.dtd
extensions/inspector/resources/locale/da/viewers/boxModel.dtd
extensions/inspector/resources/locale/da/viewers/computedStyle.dtd
extensions/inspector/resources/locale/da/viewers/dom.dtd
extensions/inspector/resources/locale/da/viewers/domNode.dtd
extensions/inspector/resources/locale/da/viewers/jsObject.dtd
extensions/inspector/resources/locale/da/viewers/styleRules.dtd
extensions/inspector/resources/locale/da/viewers/stylesheets.dtd
extensions/inspector/resources/locale/da/viewers/xblBindings.dtd
extensions/inspector/resources/locale/de/editing.dtd
extensions/inspector/resources/locale/de/inspector.dtd
extensions/inspector/resources/locale/de/inspector.properties
extensions/inspector/resources/locale/de/prefs.dtd
extensions/inspector/resources/locale/de/tasksOverlay.dtd
extensions/inspector/resources/locale/de/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/de/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/de/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/de/viewers/accessibleProps.properties
extensions/inspector/resources/locale/de/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/de/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/de/viewers/accessibleTreeEvalJSDialog.dtd
extensions/inspector/resources/locale/de/viewers/boxModel.dtd
extensions/inspector/resources/locale/de/viewers/computedStyle.dtd
extensions/inspector/resources/locale/de/viewers/dom.dtd
extensions/inspector/resources/locale/de/viewers/domNode.dtd
extensions/inspector/resources/locale/de/viewers/jsObject.dtd
extensions/inspector/resources/locale/de/viewers/styleRules.dtd
extensions/inspector/resources/locale/de/viewers/stylesheets.dtd
extensions/inspector/resources/locale/de/viewers/xblBindings.dtd
extensions/inspector/resources/locale/el/editing.dtd
extensions/inspector/resources/locale/el/inspector.dtd
extensions/inspector/resources/locale/el/inspector.properties
extensions/inspector/resources/locale/el/prefs.dtd
extensions/inspector/resources/locale/el/search/findFiles.dtd
extensions/inspector/resources/locale/el/search/junkImgs.dtd
extensions/inspector/resources/locale/el/tasksOverlay.dtd
extensions/inspector/resources/locale/el/viewers/boxModel.dtd
extensions/inspector/resources/locale/el/viewers/computedStyle.dtd
extensions/inspector/resources/locale/el/viewers/dom.dtd
extensions/inspector/resources/locale/el/viewers/domNode.dtd
extensions/inspector/resources/locale/el/viewers/jsObject.dtd
extensions/inspector/resources/locale/el/viewers/styleRules.dtd
extensions/inspector/resources/locale/el/viewers/stylesheets.dtd
extensions/inspector/resources/locale/el/viewers/xblBindings.dtd
extensions/inspector/resources/locale/en-US/editing.dtd
extensions/inspector/resources/locale/en-US/inspector.dtd
extensions/inspector/resources/locale/en-US/inspector.properties
extensions/inspector/resources/locale/en-US/prefs.dtd
extensions/inspector/resources/locale/en-US/tasksOverlay.dtd
extensions/inspector/resources/locale/en-US/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/en-US/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/en-US/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/en-US/viewers/accessibleProps.properties
extensions/inspector/resources/locale/en-US/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/en-US/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/en-US/viewers/accessibleTreeEvalJSDialog.dtd
extensions/inspector/resources/locale/en-US/viewers/boxModel.dtd
extensions/inspector/resources/locale/en-US/viewers/computedStyle.dtd
extensions/inspector/resources/locale/en-US/viewers/dom.dtd
extensions/inspector/resources/locale/en-US/viewers/domNode.dtd
extensions/inspector/resources/locale/en-US/viewers/jsObject.dtd
extensions/inspector/resources/locale/en-US/viewers/styleRules.dtd
extensions/inspector/resources/locale/en-US/viewers/stylesheets.dtd
extensions/inspector/resources/locale/en-US/viewers/xblBindings.dtd
extensions/inspector/resources/locale/fr/editing.dtd
extensions/inspector/resources/locale/fr/inspector.dtd
extensions/inspector/resources/locale/fr/inspector.properties
extensions/inspector/resources/locale/fr/prefs.dtd
extensions/inspector/resources/locale/fr/tasksOverlay.dtd
extensions/inspector/resources/locale/fr/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/fr/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/fr/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/fr/viewers/accessibleProps.properties
extensions/inspector/resources/locale/fr/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/fr/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/fr/viewers/accessibleTreeEvalJSDialog.dtd
extensions/inspector/resources/locale/fr/viewers/boxModel.dtd
extensions/inspector/resources/locale/fr/viewers/computedStyle.dtd
extensions/inspector/resources/locale/fr/viewers/dom.dtd
extensions/inspector/resources/locale/fr/viewers/domNode.dtd
extensions/inspector/resources/locale/fr/viewers/jsObject.dtd
extensions/inspector/resources/locale/fr/viewers/styleRules.dtd
extensions/inspector/resources/locale/fr/viewers/stylesheets.dtd
extensions/inspector/resources/locale/fr/viewers/xblBindings.dtd
extensions/inspector/resources/locale/ga-IE/editing.dtd
extensions/inspector/resources/locale/ga-IE/inspector.dtd
extensions/inspector/resources/locale/ga-IE/inspector.properties
extensions/inspector/resources/locale/ga-IE/prefs.dtd
extensions/inspector/resources/locale/ga-IE/search/findFiles.dtd
extensions/inspector/resources/locale/ga-IE/search/junkImgs.dtd
extensions/inspector/resources/locale/ga-IE/tasksOverlay.dtd
extensions/inspector/resources/locale/ga-IE/viewers/boxModel.dtd
extensions/inspector/resources/locale/ga-IE/viewers/computedStyle.dtd
extensions/inspector/resources/locale/ga-IE/viewers/dom.dtd
extensions/inspector/resources/locale/ga-IE/viewers/domNode.dtd
extensions/inspector/resources/locale/ga-IE/viewers/jsObject.dtd
extensions/inspector/resources/locale/ga-IE/viewers/styleRules.dtd
extensions/inspector/resources/locale/ga-IE/viewers/stylesheets.dtd
extensions/inspector/resources/locale/ga-IE/viewers/xblBindings.dtd
extensions/inspector/resources/locale/hu/editing.dtd
extensions/inspector/resources/locale/hu/inspector.dtd
extensions/inspector/resources/locale/hu/inspector.properties
extensions/inspector/resources/locale/hu/prefs.dtd
extensions/inspector/resources/locale/hu/search/findFiles.dtd
extensions/inspector/resources/locale/hu/search/junkImgs.dtd
extensions/inspector/resources/locale/hu/tasksOverlay.dtd
extensions/inspector/resources/locale/hu/viewers/boxModel.dtd
extensions/inspector/resources/locale/hu/viewers/computedStyle.dtd
extensions/inspector/resources/locale/hu/viewers/dom.dtd
extensions/inspector/resources/locale/hu/viewers/domNode.dtd
extensions/inspector/resources/locale/hu/viewers/jsObject.dtd
extensions/inspector/resources/locale/hu/viewers/styleRules.dtd
extensions/inspector/resources/locale/hu/viewers/stylesheets.dtd
extensions/inspector/resources/locale/hu/viewers/xblBindings.dtd
extensions/inspector/resources/locale/jar.mn
extensions/inspector/resources/locale/nb-NO/editing.dtd
extensions/inspector/resources/locale/nb-NO/inspector.dtd
extensions/inspector/resources/locale/nb-NO/inspector.properties
extensions/inspector/resources/locale/nb-NO/prefs.dtd
extensions/inspector/resources/locale/nb-NO/tasksOverlay.dtd
extensions/inspector/resources/locale/nb-NO/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/nb-NO/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/nb-NO/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/nb-NO/viewers/boxModel.dtd
extensions/inspector/resources/locale/nb-NO/viewers/computedStyle.dtd
extensions/inspector/resources/locale/nb-NO/viewers/dom.dtd
extensions/inspector/resources/locale/nb-NO/viewers/domNode.dtd
extensions/inspector/resources/locale/nb-NO/viewers/jsObject.dtd
extensions/inspector/resources/locale/nb-NO/viewers/styleRules.dtd
extensions/inspector/resources/locale/nb-NO/viewers/stylesheets.dtd
extensions/inspector/resources/locale/nb-NO/viewers/xblBindings.dtd
extensions/inspector/resources/locale/pl/editing.dtd
extensions/inspector/resources/locale/pl/inspector.dtd
extensions/inspector/resources/locale/pl/inspector.properties
extensions/inspector/resources/locale/pl/prefs.dtd
extensions/inspector/resources/locale/pl/tasksOverlay.dtd
extensions/inspector/resources/locale/pl/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/pl/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/pl/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/pl/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/pl/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/pl/viewers/boxModel.dtd
extensions/inspector/resources/locale/pl/viewers/computedStyle.dtd
extensions/inspector/resources/locale/pl/viewers/dom.dtd
extensions/inspector/resources/locale/pl/viewers/domNode.dtd
extensions/inspector/resources/locale/pl/viewers/jsObject.dtd
extensions/inspector/resources/locale/pl/viewers/styleRules.dtd
extensions/inspector/resources/locale/pl/viewers/stylesheets.dtd
extensions/inspector/resources/locale/pl/viewers/xblBindings.dtd
extensions/inspector/resources/locale/pt-BR/editing.dtd
extensions/inspector/resources/locale/pt-BR/inspector.dtd
extensions/inspector/resources/locale/pt-BR/inspector.properties
extensions/inspector/resources/locale/pt-BR/prefs.dtd
extensions/inspector/resources/locale/pt-BR/search/findFiles.dtd
extensions/inspector/resources/locale/pt-BR/search/junkImgs.dtd
extensions/inspector/resources/locale/pt-BR/tasksOverlay.dtd
extensions/inspector/resources/locale/pt-BR/viewers/boxModel.dtd
extensions/inspector/resources/locale/pt-BR/viewers/computedStyle.dtd
extensions/inspector/resources/locale/pt-BR/viewers/dom.dtd
extensions/inspector/resources/locale/pt-BR/viewers/domNode.dtd
extensions/inspector/resources/locale/pt-BR/viewers/jsObject.dtd
extensions/inspector/resources/locale/pt-BR/viewers/styleRules.dtd
extensions/inspector/resources/locale/pt-BR/viewers/stylesheets.dtd
extensions/inspector/resources/locale/pt-BR/viewers/xblBindings.dtd
extensions/inspector/resources/locale/ru/editing.dtd
extensions/inspector/resources/locale/ru/inspector.dtd
extensions/inspector/resources/locale/ru/inspector.properties
extensions/inspector/resources/locale/ru/prefs.dtd
extensions/inspector/resources/locale/ru/tasksOverlay.dtd
extensions/inspector/resources/locale/ru/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/ru/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/ru/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/ru/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/ru/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/ru/viewers/boxModel.dtd
extensions/inspector/resources/locale/ru/viewers/computedStyle.dtd
extensions/inspector/resources/locale/ru/viewers/dom.dtd
extensions/inspector/resources/locale/ru/viewers/domNode.dtd
extensions/inspector/resources/locale/ru/viewers/jsObject.dtd
extensions/inspector/resources/locale/ru/viewers/styleRules.dtd
extensions/inspector/resources/locale/ru/viewers/stylesheets.dtd
extensions/inspector/resources/locale/ru/viewers/xblBindings.dtd
extensions/inspector/resources/locale/sk/editing.dtd
extensions/inspector/resources/locale/sk/inspector.dtd
extensions/inspector/resources/locale/sk/inspector.properties
extensions/inspector/resources/locale/sk/prefs.dtd
extensions/inspector/resources/locale/sk/tasksOverlay.dtd
extensions/inspector/resources/locale/sk/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/sk/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/sk/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/sk/viewers/accessibleProps.properties
extensions/inspector/resources/locale/sk/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/sk/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/sk/viewers/accessibleTreeEvalJSDialog.dtd
extensions/inspector/resources/locale/sk/viewers/boxModel.dtd
extensions/inspector/resources/locale/sk/viewers/computedStyle.dtd
extensions/inspector/resources/locale/sk/viewers/dom.dtd
extensions/inspector/resources/locale/sk/viewers/domNode.dtd
extensions/inspector/resources/locale/sk/viewers/jsObject.dtd
extensions/inspector/resources/locale/sk/viewers/styleRules.dtd
extensions/inspector/resources/locale/sk/viewers/stylesheets.dtd
extensions/inspector/resources/locale/sk/viewers/xblBindings.dtd
extensions/inspector/resources/locale/sv-SE/editing.dtd
extensions/inspector/resources/locale/sv-SE/inspector.dtd
extensions/inspector/resources/locale/sv-SE/inspector.properties
extensions/inspector/resources/locale/sv-SE/prefs.dtd
extensions/inspector/resources/locale/sv-SE/tasksOverlay.dtd
extensions/inspector/resources/locale/sv-SE/viewers/accessibleEvent.dtd
extensions/inspector/resources/locale/sv-SE/viewers/accessibleEvents.dtd
extensions/inspector/resources/locale/sv-SE/viewers/accessibleProps.dtd
extensions/inspector/resources/locale/sv-SE/viewers/accessibleRelations.dtd
extensions/inspector/resources/locale/sv-SE/viewers/accessibleTree.dtd
extensions/inspector/resources/locale/sv-SE/viewers/boxModel.dtd
extensions/inspector/resources/locale/sv-SE/viewers/computedStyle.dtd
extensions/inspector/resources/locale/sv-SE/viewers/dom.dtd
extensions/inspector/resources/locale/sv-SE/viewers/domNode.dtd
extensions/inspector/resources/locale/sv-SE/viewers/jsObject.dtd
extensions/inspector/resources/locale/sv-SE/viewers/styleRules.dtd
extensions/inspector/resources/locale/sv-SE/viewers/stylesheets.dtd
extensions/inspector/resources/locale/sv-SE/viewers/xblBindings.dtd
extensions/inspector/resources/locale/zh-CN/editing.dtd
extensions/inspector/resources/locale/zh-CN/inspector.dtd
extensions/inspector/resources/locale/zh-CN/inspector.properties
extensions/inspector/resources/locale/zh-CN/prefs.dtd
extensions/inspector/resources/locale/zh-CN/search/findFiles.dtd
extensions/inspector/resources/locale/zh-CN/search/junkImgs.dtd
extensions/inspector/resources/locale/zh-CN/tasksOverlay.dtd
extensions/inspector/resources/locale/zh-CN/viewers/boxModel.dtd
extensions/inspector/resources/locale/zh-CN/viewers/computedStyle.dtd
extensions/inspector/resources/locale/zh-CN/viewers/dom.dtd
extensions/inspector/resources/locale/zh-CN/viewers/domNode.dtd
extensions/inspector/resources/locale/zh-CN/viewers/jsObject.dtd
extensions/inspector/resources/locale/zh-CN/viewers/styleRules.dtd
extensions/inspector/resources/locale/zh-CN/viewers/stylesheets.dtd
extensions/inspector/resources/locale/zh-CN/viewers/xblBindings.dtd
extensions/inspector/resources/locale/zh-TW/editing.dtd
extensions/inspector/resources/locale/zh-TW/inspector.dtd
extensions/inspector/resources/locale/zh-TW/inspector.properties
extensions/inspector/resources/locale/zh-TW/prefs.dtd
extensions/inspector/resources/locale/zh-TW/search/findFiles.dtd
extensions/inspector/resources/locale/zh-TW/search/junkImgs.dtd
extensions/inspector/resources/locale/zh-TW/tasksOverlay.dtd
extensions/inspector/resources/locale/zh-TW/viewers/boxModel.dtd
extensions/inspector/resources/locale/zh-TW/viewers/computedStyle.dtd
extensions/inspector/resources/locale/zh-TW/viewers/dom.dtd
extensions/inspector/resources/locale/zh-TW/viewers/domNode.dtd
extensions/inspector/resources/locale/zh-TW/viewers/jsObject.dtd
extensions/inspector/resources/locale/zh-TW/viewers/styleRules.dtd
extensions/inspector/resources/locale/zh-TW/viewers/stylesheets.dtd
extensions/inspector/resources/locale/zh-TW/viewers/xblBindings.dtd
extensions/inspector/resources/skin/classic/ImageSearchItem.gif
extensions/inspector/resources/skin/classic/btnFind-dis.gif
extensions/inspector/resources/skin/classic/btnFind.gif
extensions/inspector/resources/skin/classic/btnSelecting-act.gif
extensions/inspector/resources/skin/classic/btnSelecting-dis.gif
extensions/inspector/resources/skin/classic/btnSelecting.gif
extensions/inspector/resources/skin/classic/iconImportant.gif
extensions/inspector/resources/skin/classic/iconViewerList-dis.gif
extensions/inspector/resources/skin/classic/iconViewerList.gif
extensions/inspector/resources/skin/classic/iconViewerMenu-dis.gif
extensions/inspector/resources/skin/classic/iconViewerMenu.gif
extensions/inspector/resources/skin/classic/inspector.css
extensions/inspector/resources/skin/classic/inspectorWindow.css
extensions/inspector/resources/skin/classic/multipanel.css
extensions/inspector/resources/skin/classic/panelset.css
extensions/inspector/resources/skin/classic/sidebar.css
extensions/inspector/resources/skin/classic/titledSplitter.css
extensions/inspector/resources/skin/classic/titledsplitter-close.gif
extensions/inspector/resources/skin/classic/treeEditable.css
extensions/inspector/resources/skin/classic/viewers/boxModel/boxModel.css
extensions/inspector/resources/skin/classic/viewers/dom/columnsDialog.css
extensions/inspector/resources/skin/classic/viewers/dom/dom.css
extensions/inspector/resources/skin/classic/viewers/dom/findDialog.css
extensions/inspector/resources/skin/classic/viewers/domNode/domNode.css
extensions/inspector/resources/skin/classic/viewers/styleRules/styleRules.css
extensions/inspector/resources/skin/classic/viewers/xblBindings/xblBindings.css
extensions/inspector/resources/skin/modern/ImageSearchItem.gif
extensions/inspector/resources/skin/modern/btnFind-dis.gif
extensions/inspector/resources/skin/modern/btnFind.gif
extensions/inspector/resources/skin/modern/btnSelecting-act.gif
extensions/inspector/resources/skin/modern/btnSelecting-dis.gif
extensions/inspector/resources/skin/modern/btnSelecting.gif
extensions/inspector/resources/skin/modern/iconImportant.gif
extensions/inspector/resources/skin/modern/iconViewerList-dis.gif
extensions/inspector/resources/skin/modern/iconViewerList.gif
extensions/inspector/resources/skin/modern/iconViewerMenu-dis.gif
extensions/inspector/resources/skin/modern/iconViewerMenu.gif
extensions/inspector/resources/skin/modern/inspector.css
extensions/inspector/resources/skin/modern/inspectorWindow.css
extensions/inspector/resources/skin/modern/multipanel.css
extensions/inspector/resources/skin/modern/panelset.css
extensions/inspector/resources/skin/modern/sidebar.css
extensions/inspector/resources/skin/modern/titledSplitter.css
extensions/inspector/resources/skin/modern/titledsplitter-close.gif
extensions/inspector/resources/skin/modern/treeEditable.css
extensions/inspector/resources/skin/modern/viewers/boxModel/boxModel.css
extensions/inspector/resources/skin/modern/viewers/dom/columnsDialog.css
extensions/inspector/resources/skin/modern/viewers/dom/dom.css
extensions/inspector/resources/skin/modern/viewers/dom/findDialog.css
extensions/inspector/resources/skin/modern/viewers/domNode/domNode.css
extensions/inspector/resources/skin/modern/viewers/styleRules/styleRules.css
extensions/inspector/resources/skin/modern/viewers/xblBindings/xblBindings.css
gfx/thebes/src/gfxFont.cpp
gfx/thebes/src/gfxPlatform.cpp
intl/ctl/Makefile.in
intl/ctl/public/Makefile.in
intl/ctl/public/nsCtlCIID.h
intl/ctl/public/nsILE.h
intl/ctl/readme.txt
intl/ctl/src/Makefile.in
intl/ctl/src/ctl.pkg
intl/ctl/src/hindiShaper/Makefile.in
intl/ctl/src/hindiShaper/dvng-x.c
intl/ctl/src/nsCtlLEModule.cpp
intl/ctl/src/nsULE.cpp
intl/ctl/src/nsULE.h
intl/ctl/src/nsUnicodeToSunIndic.cpp
intl/ctl/src/nsUnicodeToSunIndic.h
intl/ctl/src/nsUnicodeToTIS620.cpp
intl/ctl/src/nsUnicodeToTIS620.h
intl/ctl/src/nsUnicodeToThaiTTF.cpp
intl/ctl/src/nsUnicodeToThaiTTF.h
intl/ctl/src/pangoLite/Makefile.in
intl/ctl/src/pangoLite/glyphstring.c
intl/ctl/src/pangoLite/modules.c
intl/ctl/src/pangoLite/modules.h
intl/ctl/src/pangoLite/pango-coverage.c
intl/ctl/src/pangoLite/pango-coverage.h
intl/ctl/src/pangoLite/pango-engine.h
intl/ctl/src/pangoLite/pango-glyph.h
intl/ctl/src/pangoLite/pango-modules.h
intl/ctl/src/pangoLite/pango-types.h
intl/ctl/src/pangoLite/pango-utils.c
intl/ctl/src/pangoLite/pango-utils.h
intl/ctl/src/pangoLite/pango.h
intl/ctl/src/pangoLite/pango.modules
intl/ctl/src/pangoLite/querymodules.c
intl/ctl/src/pangoLite/shape.c
intl/ctl/src/thaiShaper/Makefile.in
intl/ctl/src/thaiShaper/thai-x.c
js/src/js.cpp
layout/generic/Makefile.in
security/nss/lib/ckfw/nsprstub.c
toolkit/components/filepicker/Makefile.in
widget/src/windows/IENUMFE.CPP
widget/src/windows/IENUMFE.H
xpfe/components/filepicker/Makefile.in
xpfe/components/filepicker/public/Makefile.in
xpfe/components/filepicker/public/nsIFileView.idl
xpfe/components/filepicker/src/Makefile.in
xpfe/components/filepicker/src/filepicker.pkg
xpfe/components/filepicker/src/nsFilePicker.js.in
xpfe/components/filepicker/src/nsFileView.cpp
xpfe/components/filepicker/src/nsWildCard.cpp
xpfe/components/filepicker/src/nsWildCard.h
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1592,45 +1592,47 @@ NS_IMETHODIMP nsDocAccessible::FlushPend
           continue;
         }
         gLastFocusedFrameType = newFrameType;
       }
     }
 
     if (eventType == nsIAccessibleEvent::EVENT_DOM_CREATE || 
         eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
+
       nsCOMPtr<nsIAccessible> containerAccessible;
+      if (accessible)
+        accessible->GetParent(getter_AddRefs(containerAccessible));
+
+      if (!containerAccessible) {
+        GetAccessibleInParentChain(domNode, PR_TRUE,
+                                   getter_AddRefs(containerAccessible));
+        if (!containerAccessible)
+          containerAccessible = this;
+      }
+
       if (eventType == nsIAccessibleEvent::EVENT_ASYNCH_SHOW) {
-        if (accessible) {
-          // For asynch show, delayed invalidatation of parent's children
-          accessible->GetParent(getter_AddRefs(containerAccessible));
-          nsCOMPtr<nsPIAccessible> privateContainerAccessible =
-            do_QueryInterface(containerAccessible);
-          if (privateContainerAccessible)
-            privateContainerAccessible->InvalidateChildren();
-        }
+        // For asynch show, delayed invalidatation of parent's children
+        nsCOMPtr<nsPIAccessible> privateContainerAccessible =
+          do_QueryInterface(containerAccessible);
+        if (privateContainerAccessible)
+          privateContainerAccessible->InvalidateChildren();
+
         // Some show events in the subtree may have been removed to 
         // avoid firing redundant events. But, we still need to make sure any
         // accessibles parenting those shown nodes lose their child references.
         InvalidateChildrenInSubtree(domNode);
       }
 
       // Also fire text changes if the node being created could affect the text in an nsIAccessibleText parent.
       // When a node is being made visible or is inserted, the text in an ancestor hyper text will gain characters
       // At this point we now have the frame and accessible for this node if there is one. That is why we
       // wait to fire this here, instead of in InvalidateCacheSubtree(), where we wouldn't be able to calculate
       // the offset, length and text for the text change.
       if (domNode && domNode != mDOMNode) {
-        if (!containerAccessible) {
-          GetAccessibleInParentChain(domNode, PR_TRUE,
-                                     getter_AddRefs(containerAccessible));
-          if (!containerAccessible)
-            containerAccessible = this;
-        }
-
         nsCOMPtr<nsIAccessibleTextChangeEvent> textChangeEvent =
           CreateTextChangeEventForNode(containerAccessible, domNode, accessible, PR_TRUE, PR_TRUE);
         if (textChangeEvent) {
           nsAccEvent::PrepareForEvent(textChangeEvent, isFromUserInput);
           // XXX Queue them up and merge the text change events
           // XXX We need a way to ignore SplitNode and JoinNode() when they
           // do not affect the text within the hypertext
           FireAccessibleEvent(textChangeEvent);
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -332,17 +332,16 @@ pref("browser.tabs.closeButtons", 1);
 // When tabs opened by links in other tabs via a combination of 
 // browser.link.open_newwindow being set to 3 and target="_blank" etc are
 // closed:
 // true   return to the tab that opened this tab (its owner)
 // false  return to the adjacent tab (old default)
 pref("browser.tabs.selectOwnerOnClose", true);
 
 pref("browser.ctrlTab.mostRecentlyUsed", true);
-pref("browser.ctrlTab.previewsCount", 3);
 pref("browser.ctrlTab.smoothScroll", true);
 
 // Default bookmark sorting
 pref("browser.bookmarks.sort.direction", "descending");
 pref("browser.bookmarks.sort.resource", "rdf:http://home.netscape.com/NC-rdf#Name");
 
 // By default, do not export HTML at shutdown.
 // If true, at shutdown the bookmarks in your menu and toolbar will
--- a/browser/base/content/browser-tabPreviews.js
+++ b/browser/base/content/browser-tabPreviews.js
@@ -99,17 +99,18 @@ var tabPreviews = {
     }
   }
 };
 
 /**
  * Ctrl-Tab panel
  */
 var ctrlTab = {
-  tabs: [],
+  tabs: null,
+  visibleCount: 3,
   _uniqid: 0,
   get panel () {
     delete this.panel;
     return this.panel = document.getElementById("ctrlTab-panel");
   },
   get label () {
     delete this.label;
     return this.label = document.getElementById("ctrlTab-label");
@@ -133,58 +134,66 @@ var ctrlTab = {
   get rtl () {
     delete this.rtl;
     return this.rtl = getComputedStyle(this.panel, "").direction == "rtl";
   },
   get iconSize () {
     delete this.iconSize;
     return this.iconSize = Math.round(tabPreviews.height / 4);
   },
+  get closeCharCode () {
+    delete this.closeCharCode;
+    return this.closeCharCode = document.getElementById("key_close")
+                                        .getAttribute("key")
+                                        .toLowerCase().charCodeAt(0);
+  },
   get smoothScroll () {
     delete this.smoothScroll;
     return this.smoothScroll = gPrefService.getBoolPref("browser.ctrlTab.smoothScroll");
   },
-  get previewsCount () {
-    delete this.previewsCount;
-    return this.previewsCount = Math.max(gPrefService.getIntPref("browser.ctrlTab.previewsCount"), 3);
-  },
-  get visibleCount () {
-    return Math.min(this.previewsCount, this.tabs.length);
-  },
   get offscreenStart () {
     return Array.indexOf(this.container.childNodes, this.selected) - 1;
   },
   get offscreenEnd () {
     return this.container.childNodes.length - this.visibleCount - this.offscreenStart;
   },
   get offsetX () {
     return - tabPreviews.width * (this.rtl ? this.offscreenEnd : this.offscreenStart);
   },
+  get isOpen () {
+    return this.panel.state == "open" || this.panel.state == "showing";
+  },
   init: function () {
+    if (this.tabs)
+      return;
+
     var tabContainer = gBrowser.tabContainer;
 
+    this.tabs = [];
     Array.forEach(tabContainer.childNodes, function (tab) {
       this.attachTab(tab, tab == gBrowser.selectedTab);
     }, this);
 
     tabContainer.addEventListener("TabOpen", this, false);
     tabContainer.addEventListener("TabSelect", this, false);
     tabContainer.addEventListener("TabClose", this, false);
 
     gBrowser.mTabBox.handleCtrlTab = false;
-    window.addEventListener("keydown", this, true);
+    document.addEventListener("keypress", this, false);
   },
   uninit: function () {
+    this.tabs = null;
+
     var tabContainer = gBrowser.tabContainer;
     tabContainer.removeEventListener("TabOpen", this, false);
     tabContainer.removeEventListener("TabSelect", this, false);
     tabContainer.removeEventListener("TabClose", this, false);
 
     this.panel.removeEventListener("popuphiding", this, false);
-    window.removeEventListener("keydown", this, true);
+    document.removeEventListener("keypress", this, false);
   },
   addBox: function (aAtStart) {
     const SVGNS = "http://www.w3.org/2000/svg";
 
     var thumbnail = document.createElementNS(SVGNS, "image");
     thumbnail.setAttribute("class", "ctrlTab-thumbnail");
     thumbnail.setAttribute("height", tabPreviews.height);
     thumbnail.setAttribute("width", tabPreviews.width);
@@ -284,23 +293,22 @@ var ctrlTab = {
             }
           }
         }
         break;
     }
   },
   scroll: function () {
     if (!this.smoothScroll) {
-      this._move = true;
-      this.stopScroll();
+      this.advanceSelected();
+      this.arrangeBoxes();
       return;
     }
 
     this.stopScroll();
-    this._move = true;
     let (next = this.invertDirection ? this.selected.previousSibling : this.selected.nextSibling) {
       this.setStatusbarValue(next);
       this.label.value = next._tab.label;
       this.label.crop = next._tab.crop;
     }
 
     const FRAME_LENGTH = 40;
     var x = this.offsetX;
@@ -321,43 +329,36 @@ var ctrlTab = {
 
     this._scrollTimer = setInterval(processFrame, FRAME_LENGTH, this);
     processFrame(this, 0);
   },
   stopScroll: function () {
     if (this._scrollTimer) {
       clearInterval(this._scrollTimer);
       this._scrollTimer = 0;
-    }
-    if (this._move)
-      this.updateSelected();
-  },
-  updateSelected: function (aClosing) {
-    var index = 1;
-    if (this._move) {
-      this._move = false;
-      index += this.invertDirection ? -1 : 1;
+      this.advanceSelected();
+      this.arrangeBoxes();
     }
-    if (this.selected) {
-      index += this.offscreenStart + this.tabs.length;
-      index %= this.tabs.length;
-      if (index < 2)
-        index += this.tabs.length;
-      if (index > this.container.childNodes.length - this.visibleCount + 1)
-        index -= this.tabs.length;
-    }
+  },
+  advanceSelected: function () {
+    // regardless of visibleCount, the new highlighted tab will be
+    // the first or third-visible tab, depending on whether Shift is pressed
+    var index = ((this.invertDirection ? 0 : 2) + this.offscreenStart + this.tabs.length)
+                % this.tabs.length;
+    if (index < 2)
+      index += this.tabs.length;
+    if (index > this.container.childNodes.length - this.visibleCount + 1)
+      index -= this.tabs.length;
     this.selected = this.container.childNodes[index];
-
-    if (aClosing)
-      return;
-
+  },
+  arrangeBoxes: function () {
     this.addOffscreenBox(this.invertDirection);
     this.addOffscreenBox(!this.invertDirection);
 
-    // having lots of off-screen boxes reduce the scrolling speed, remove some
+    // having lots of off-screen boxes reduces the scrolling speed, remove some
     for (let i = this.offscreenStart; i > 1; i--)
       this.removeBox(this.container.firstChild);
     for (let i = this.offscreenEnd; i > 1; i--)
       this.removeBox(this.container.lastChild);
 
     this.container.setAttribute("transform", "translate("+ this.offsetX +", 0)");
 
     for (let i = 0, l = this.container.childNodes.length; i < l; i++)
@@ -415,104 +416,142 @@ var ctrlTab = {
       this.tabs.push(aTab);
   },
   detachTab: function (aTab) {
     var i = this.tabs.indexOf(aTab);
     if (i >= 0)
       this.tabs.splice(i, 1);
   },
   open: function () {
-    window.addEventListener("keyup", this, true);
-    window.addEventListener("keypress", this, true);
+    this._deferOnTabSelect = [];
+
+    document.addEventListener("keyup", this, false);
+    document.addEventListener("keydown", this, false);
     this.panel.addEventListener("popuphiding", this, false);
     this.panel.hidden = false;
     this.panel.width = tabPreviews.width * this.visibleCount;
     this.panel.openPopupAtScreen(screen.availLeft + (screen.availWidth - this.panel.width) / 2,
                                  screen.availTop + (screen.availHeight - this.svgRoot.getAttribute("height")) / 2,
                                  false);
 
+    // display $visibleCount tabs, starting with the first or
+    // the second to the last tab, depending on whether Shift is pressed
     for (let index = this.invertDirection ? this.tabs.length - 2 : 0,
              i = this.visibleCount; i > 0; i--)
       this.addPreview(this.addBox(), this.tabs[index++ % this.tabs.length]);
-    this.updateSelected();
+
+    // regardless of visibleCount, highlight the second-visible tab
+    this.selected = this.container.childNodes[1];
+    this.arrangeBoxes();
   },
-  onKeyDown: function (event) {
-    var isOpen = this.panel.state == "open" || this.panel.state == "showing";
+  onKeyPress: function (event) {
+    var isOpen = this.isOpen;
     var propagate = !isOpen;
     switch (event.keyCode) {
       case event.DOM_VK_TAB:
-        if (event.ctrlKey && !event.altKey && !event.metaKey && this.tabs.length > 1) {
+        if (event.ctrlKey && !event.altKey && !event.metaKey) {
           propagate = false;
           this.invertDirection = event.shiftKey;
           if (isOpen)
             this.scroll();
           else if (this.tabs.length == 2)
             gBrowser.selectedTab = this.tabs[1];
-          else
+          else if (this.tabs.length > 2)
             this.open();
         }
         break;
       case event.DOM_VK_ESCAPE:
         if (isOpen)
           this.panel.hidePopup();
         break;
+      default:
+        if (isOpen && event.charCode == this.closeCharCode) {
+          this.stopScroll();
+          gBrowser.removeTab(this.selected._tab);
+        }
     }
     if (!propagate) {
       event.stopPropagation();
       event.preventDefault();
     }
   },
   onKeyUp: function (event) {
     if (event.keyCode == event.DOM_VK_CONTROL) {
-      if (this._move)
-        this.updateSelected(true);
+      this.stopScroll();
       let selectedTab = this.selected._tab;
       this.panel.hidePopup();
       gBrowser.selectedTab = selectedTab;
     }
   },
   onPopupHiding: function () {
     this.stopScroll();
-    window.removeEventListener("keyup", this, true);
-    window.removeEventListener("keypress", this, true);
+    document.removeEventListener("keyup", this, false);
+    document.removeEventListener("keydown", this, false);
     while (this.container.childNodes.length)
       this.removeBox(this.container.lastChild);
     this.selected = null;
     this.invertDirection = false;
-    this._move = false;
     this._uniqid = 0;
     this.label.value = "";
     this.setStatusbarValue();
     this.container.removeAttribute("transform");
     this.svgRoot.forceRedraw();
+
+    this._deferOnTabSelect.forEach(this.onTabSelect, this);
+    this._deferOnTabSelect = null;
+  },
+  onTabSelect: function (aTab) {
+    if (aTab.parentNode) {
+      this.detachTab(aTab);
+      this.attachTab(aTab, true);
+    }
   },
   handleEvent: function (event) {
     switch (event.type) {
       case "DOMAttrModified":
         this.tabAttrModified(event.target, event.attrName);
         break;
       case "TabSelect":
-        this.detachTab(event.target);
-        this.attachTab(event.target, true);
+        if (this.isOpen)
+          // don't change the tab order while the panel is open
+          this._deferOnTabSelect.push(event.target);
+        else
+          this.onTabSelect(event.target);
         break;
       case "TabOpen":
         this.attachTab(event.target);
         break;
       case "TabClose":
+        if (this.isOpen) {
+          if (this.tabs.length == 2) {
+            // we have two tabs, one is being closed, so the panel isn't needed anymore
+            this.panel.hidePopup();
+          } else {
+            if (event.target == this.selected._tab)
+              this.advanceSelected();
+            this.detachTab(event.target);
+            Array.slice(this.container.childNodes).forEach(function (box) {
+              if (box._tab == event.target) {
+                this.removeBox(box);
+                this.arrangeBoxes();
+              }
+            }, this);
+          }
+        }
         this.detachTab(event.target);
         break;
+      case "keypress":
+        this.onKeyPress(event);
+        break;
       case "keydown":
-        this.onKeyDown(event);
-        break;
       case "keyup":
-      case "keypress":
         // the panel is open; don't propagate any key events
         event.stopPropagation();
         event.preventDefault();
-      case "keyup":
-        this.onKeyUp(event);
+        if (event.type == "keyup")
+          this.onKeyUp(event);
         break;
       case "popuphiding":
         this.onPopupHiding();
         break;
     }
   }
 };
--- a/browser/base/content/browser-textZoom.js
+++ b/browser/base/content/browser-textZoom.js
@@ -34,19 +34,16 @@
  * 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 *****
 #endif
  */
 
-// From nsMouseScrollEvent::kIsHorizontal
-const MOUSE_SCROLL_IS_HORIZONTAL = 1 << 2;
-
 // One of the possible values for the mousewheel.* preferences.
 // From nsEventStateManager.cpp.
 const MOUSE_SCROLL_ZOOM = 3;
 
 /**
  * Controls the "full zoom" setting and its site-specific preferences.
  */
 var FullZoom = {
@@ -143,17 +140,17 @@ var FullZoom = {
         break;
     }
   },
 
   _handleMouseScrolled: function FullZoom__handleMouseScrolled(event) {
     // Construct the "mousewheel action" pref key corresponding to this event.
     // Based on nsEventStateManager::GetBasePrefKeyForMouseWheel.
     var pref = "mousewheel";
-    if (event.scrollFlags & MOUSE_SCROLL_IS_HORIZONTAL)
+    if (event.axis == event.HORIZONTAL_AXIS)
       pref += ".horizscroll";
 
     if (event.shiftKey)
       pref += ".withshiftkey";
     else if (event.ctrlKey)
       pref += ".withcontrolkey";
     else if (event.altKey)
       pref += ".withaltkey";
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5094,128 +5094,110 @@ function charsetLoadListener (event)
           gCharsetMenu = Components.classes['@mozilla.org/rdf/datasource;1?name=charset-menu'].getService().QueryInterface(Components.interfaces.nsICurrentCharsetListener);
         gCharsetMenu.SetCurrentCharset(charset);
         gPrevCharset = gLastBrowserCharset;
         gLastBrowserCharset = charset;
     }
 }
 
 /* Begin Page Style Functions */
-function getStyleSheetArray(frame)
-{
-  var styleSheets = frame.document.styleSheets;
-  var styleSheetsArray = new Array(styleSheets.length);
-  for (var i = 0; i < styleSheets.length; i++) {
-    styleSheetsArray[i] = styleSheets[i];
-  }
-  return styleSheetsArray;
-}
-
-function getAllStyleSheets(frameset)
-{
-  var styleSheetsArray = getStyleSheetArray(frameset);
-  for (var i = 0; i < frameset.frames.length; i++) {
-    var frameSheets = getAllStyleSheets(frameset.frames[i]);
+function getAllStyleSheets(frameset) {
+  var styleSheetsArray = Array.slice(frameset.document.styleSheets);
+  for (let i = 0; i < frameset.frames.length; i++) {
+    let frameSheets = getAllStyleSheets(frameset.frames[i]);
     styleSheetsArray = styleSheetsArray.concat(frameSheets);
   }
   return styleSheetsArray;
 }
 
-function stylesheetFillPopup(menuPopup)
-{
+function stylesheetFillPopup(menuPopup) {
   var noStyle = menuPopup.firstChild;
   var persistentOnly = noStyle.nextSibling;
   var sep = persistentOnly.nextSibling;
   while (sep.nextSibling)
     menuPopup.removeChild(sep.nextSibling);
 
   var styleSheets = getAllStyleSheets(window.content);
-  var currentStyleSheets = [];
+  var currentStyleSheets = {};
   var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled;
   var haveAltSheets = false;
   var altStyleSelected = false;
 
-  for (var i = 0; i < styleSheets.length; ++i) {
-    var currentStyleSheet = styleSheets[i];
+  for (let i = 0; i < styleSheets.length; ++i) {
+    let currentStyleSheet = styleSheets[i];
+
+    if (!currentStyleSheet.title)
+      continue;
 
     // Skip any stylesheets that don't match the screen media type.
-    var media = currentStyleSheet.media.mediaText.toLowerCase();
-    if (media && (media.indexOf("screen") == -1) && (media.indexOf("all") == -1))
+    let (media = currentStyleSheet.media.mediaText.toLowerCase()) {
+      if (media && (media.indexOf("screen") == -1) && (media.indexOf("all") == -1))
         continue;
-
-    if (currentStyleSheet.title) {
-      if (!currentStyleSheet.disabled)
-        altStyleSelected = true;
-
-      haveAltSheets = true;
-
-      var lastWithSameTitle = null;
-      if (currentStyleSheet.title in currentStyleSheets)
-        lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
-
-      if (!lastWithSameTitle) {
-        var menuItem = document.createElement("menuitem");
-        menuItem.setAttribute("type", "radio");
-        menuItem.setAttribute("label", currentStyleSheet.title);
-        menuItem.setAttribute("data", currentStyleSheet.title);
-        menuItem.setAttribute("checked", !currentStyleSheet.disabled && !styleDisabled);
-        menuPopup.appendChild(menuItem);
-        currentStyleSheets[currentStyleSheet.title] = menuItem;
-      } else {
-        if (currentStyleSheet.disabled)
-          lastWithSameTitle.removeAttribute("checked");
-      }
+    }
+
+    if (!currentStyleSheet.disabled)
+      altStyleSelected = true;
+
+    haveAltSheets = true;
+
+    let lastWithSameTitle = null;
+    if (currentStyleSheet.title in currentStyleSheets)
+      lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
+
+    if (!lastWithSameTitle) {
+      let menuItem = document.createElement("menuitem");
+      menuItem.setAttribute("type", "radio");
+      menuItem.setAttribute("label", currentStyleSheet.title);
+      menuItem.setAttribute("data", currentStyleSheet.title);
+      menuItem.setAttribute("checked", !currentStyleSheet.disabled && !styleDisabled);
+      menuPopup.appendChild(menuItem);
+      currentStyleSheets[currentStyleSheet.title] = menuItem;
+    } else if (currentStyleSheet.disabled) {
+      lastWithSameTitle.removeAttribute("checked");
     }
   }
 
   noStyle.setAttribute("checked", styleDisabled);
   persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled);
   persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false;
   sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets;
   return true;
 }
 
 function stylesheetInFrame(frame, title) {
-  var docStyleSheets = frame.document.styleSheets;
-
-  for (var i = 0; i < docStyleSheets.length; ++i) {
-    if (docStyleSheets[i].title == title)
-      return true;
-  }
-  return false;
+  return Array.some(frame.document.styleSheets,
+                    function (stylesheet) stylesheet.title == title);
 }
 
 function stylesheetSwitchFrame(frame, title) {
   var docStyleSheets = frame.document.styleSheets;
 
-  for (var i = 0; i < docStyleSheets.length; ++i) {
-    var docStyleSheet = docStyleSheets[i];
+  for (let i = 0; i < docStyleSheets.length; ++i) {
+    let docStyleSheet = docStyleSheets[i];
 
     if (title == "_nostyle")
       docStyleSheet.disabled = true;
     else if (docStyleSheet.title)
       docStyleSheet.disabled = (docStyleSheet.title != title);
     else if (docStyleSheet.disabled)
       docStyleSheet.disabled = false;
   }
 }
 
 function stylesheetSwitchAll(frameset, title) {
-  if (!title || title == "_nostyle" || stylesheetInFrame(frameset, title)) {
+  if (!title || title == "_nostyle" || stylesheetInFrame(frameset, title))
     stylesheetSwitchFrame(frameset, title);
-  }
-  for (var i = 0; i < frameset.frames.length; i++) {
+
+  for (let i = 0; i < frameset.frames.length; i++)
     stylesheetSwitchAll(frameset.frames[i], title);
-  }
 }
 
 function setStyleDisabled(disabled) {
   getMarkupDocumentViewer().authorStyleDisabled = disabled;
 }
-
 /* End of the Page Style functions */
 
 var BrowserOffline = {
   /////////////////////////////////////////////////////////////////////////////
   // BrowserOffline Public Methods
   init: function ()
   {
     if (!this._uiElement)
@@ -6732,11 +6714,18 @@ let DownloadMonitorPanel = {
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// nsISupports
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDownloadProgressListener]),
 };
 
+function getNotificationBox(aWindow) {
+  var foundBrowser = gBrowser.getBrowserForDocument(aWindow.document);
+  if (foundBrowser)
+    return gBrowser.getNotificationBox(foundBrowser)
+  return null;
+};
+
 /* DEPRECATED */
 function getBrowser() gBrowser;
 function getNavToolbox() gNavToolbox;
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -56,16 +56,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_bug409481.js \
                  browser_autodiscovery.js \
                  browser_bug420160.js \
                  autodiscovery.html \
                  moz.png \
                  browser_getshortcutoruri.js \
                  browser_page_style_menu.js \
                  page_style_sample.html \
+                 browser_ctrlTab.js \
     $(NULL)
 
 ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
 _BROWSER_FILES += browser_customize.js \
     $(NULL)
 endif
 
 # disable tests on linux for now..
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_ctrlTab.js
@@ -0,0 +1,132 @@
+function test() {
+  gBrowser.addTab();
+  gBrowser.addTab();
+  gBrowser.addTab();
+
+  assertTabs(4);
+
+  ctrlTabTest([2]      , 1, 0);
+  ctrlTabTest([2, 3, 1], 2, 2);
+  ctrlTabTest([]       , 4, 2);
+
+  {
+    let selectedIndex = gBrowser.tabContainer.selectedIndex;
+    pressCtrlTab();
+    pressCtrlTab(true);
+    releaseCtrl();
+    is(gBrowser.tabContainer.selectedIndex, selectedIndex,
+       "Ctrl+Tab -> Ctrl+Shift+Tab keeps the selected tab");
+  }
+
+  { // test for bug 445369
+    let tabs = gBrowser.mTabs.length;
+    pressCtrlTab();
+    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    is(gBrowser.mTabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes one tab");
+    releaseCtrl();
+  }
+  assertTabs(3);
+
+  ctrlTabTest([2, 1, 0], 7, 1);
+
+  { // test for bug 445369
+    selectTabs([1, 2, 0]);
+
+    let selectedTab = gBrowser.selectedTab;
+    let tabToRemove = gBrowser.mTabs[1];
+
+    pressCtrlTab();
+    pressCtrlTab();
+    EventUtils.synthesizeKey("w", { ctrlKey: true });
+    ok(!tabToRemove.parentNode,
+       "Ctrl+Tab*2 -> Ctrl+W removes the second most recently selected tab");
+
+    pressCtrlTab(true);
+    pressCtrlTab(true);
+    releaseCtrl();
+    ok(gBrowser.selectedTab == selectedTab,
+       "Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab");
+  }
+  assertTabs(2);
+
+  ctrlTabTest([1]      , 1, 0);
+
+  gBrowser.removeTab(gBrowser.tabContainer.lastChild);
+
+  assertTabs(1);
+
+  { // test for bug 445768
+    let focusedWindow = document.commandDispatcher.focusedWindow;
+    let eventConsumed = true;
+    let detectKeyEvent = function (event) {
+      eventConsumed = event.getPreventDefault();
+    };
+    document.addEventListener("keypress", detectKeyEvent, false);
+    pressCtrlTab();
+    document.removeEventListener("keypress", detectKeyEvent, false);
+    ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
+    is(focusedWindow.location, document.commandDispatcher.focusedWindow.location,
+       "Ctrl+Tab doesn't change focus if one tab is open");
+  }
+
+  /* private utility functions */
+
+  function pressCtrlTab(aShiftKey)
+    EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
+
+  function releaseCtrl()
+    EventUtils.synthesizeKey("VK_CONTROL", { type: "keyup" });
+
+  function assertTabs(aTabs) {
+    var tabs = gBrowser.mTabs.length;
+    if (tabs != aTabs) {
+      while (gBrowser.mTabs.length > 1)
+        gBrowser.removeCurrentTab();
+      throw "expected " + aTabs + " open tabs, got " + tabs;
+    }
+  }
+
+  function selectTabs(tabs) {
+    tabs.forEach(function (index) {
+      gBrowser.selectedTab = gBrowser.mTabs[index];
+    });
+  }
+
+  function ctrlTabTest(tabsToSelect, tabTimes, expectedIndex) {
+    selectTabs(tabsToSelect);
+
+    var indexStart = gBrowser.tabContainer.selectedIndex;
+    var tabCount = gBrowser.mTabs.length;
+    var normalized = tabTimes % tabCount;
+    var where = normalized == 1 ? "back to the previously selected tab" :
+                normalized + " tabs back in most-recently-selected order";
+
+    for (let i = 0; i < tabTimes; i++) {
+      pressCtrlTab();
+
+      if (tabCount > 2)
+       is(gBrowser.tabContainer.selectedIndex, indexStart,
+         "Selected tab doesn't change while tabbing");
+    }
+
+    if (tabCount > 2) {
+      ok(ctrlTab.panel.state == "showing" || ctrlTab.panel.state == "open",
+         "With " + tabCount + " tabs open, Ctrl+Tab opens the preview panel");
+
+      is(ctrlTab.label.value, gBrowser.mTabs[expectedIndex].label,
+         "Preview panel displays label of expected tab");
+
+      releaseCtrl();
+
+      ok(ctrlTab.panel.state == "hiding" || ctrlTab.panel.state == "closed",
+         "Releasing Ctrl closes the preview panel");
+    } else {
+      ok(ctrlTab.panel.state == "hiding" || ctrlTab.panel.state == "closed",
+         "With " + tabCount + " tabs open, Ctrl+Tab doesn't open the preview panel");
+    }
+
+    is(gBrowser.tabContainer.selectedIndex, expectedIndex,
+       "With "+ tabCount +" tabs open and tab " + indexStart
+       + " selected, Ctrl+Tab*" + tabTimes + " goes " + where);
+  }
+}
--- a/browser/base/content/test/browser_page_style_menu.js
+++ b/browser/base/content/test/browser_page_style_menu.js
@@ -1,12 +1,10 @@
 function test() {
   waitForExplicitFinish();
-  finish();
-  return;
 
   var tab = gBrowser.addTab();
   gBrowser.selectedTab = tab;
   tab.linkedBrowser.addEventListener("load", checkPageStyleMenu, true);
   content.location =
     "chrome://mochikit/content/browser/browser/base/content/test/page_style_sample.html";
 }
 
@@ -26,17 +24,17 @@ function checkPageStyleMenu() {
   Array.forEach(content.document.getElementsByTagName("link"), function (link) {
     var title = link.getAttribute("title");
     var rel = link.getAttribute("rel");
     var media = link.getAttribute("media");
     var idstring = "link " + (title ? title : "without title and") +
                    " with rel=\"" + rel + "\"" +
                    (media ? " and media=\"" + media + "\"" : "");
 
-    var item = items.filter(function (item) item.label == title);
+    var item = items.filter(function (item) item.getAttribute("label") == title);
     var found = item.length == 1;
     var checked = found && (item[0].getAttribute("checked") == "true");
 
     switch (link.getAttribute("data-state")) {
       case "0":
         ok(!found, idstring + " does not show up in page style menu");
         break;
       case "0-todo":
--- a/browser/components/search/content/engineManager.js
+++ b/browser/components/search/content/engineManager.js
@@ -163,39 +163,30 @@ var gEngineManagerDialog = {
     var title = strings.getString("editTitle");
     var msg = strings.getFormattedString("editMsg", [selectedEngine.name]);
 
     while (prompt.prompt(window, title, msg, alias, null, { })) {
       var bduplicate = false;
       var eduplicate = false;
 
       if (alias.value != "") {
-        var searchService = Cc["@mozilla.org/browser/search-service;1"].
-                            getService(Ci.nsIBrowserSearchService);
-        var engine = searchService.getEngineByAlias(alias.value);
+        try {
+          let bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
+                       getService(Ci.nsINavBookmarksService);
+          if (bmserv.getURIForKeyword(alias.value))
+            bduplicate = true;
+        } catch(ex) {}
 
-        if (engine) {
-          if (engine.name != selectedEngine.name)
+        // Check for duplicates in changes we haven't committed yet
+        let engines = gEngineView._engineStore.engines;
+        for each (let engine in engines) {
+          if (engine.alias == alias.value && 
+              engine.name != selectedEngine.name) {
             eduplicate = true;
-        } else {
-          try {
-            var bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-                         getService(Ci.nsINavBookmarksService);
-            if (bmserv.getURIForKeyword(alias.value))
-              bduplicate = true;
-          } catch(ex) {}
-
-          // Check for duplicates in changes we haven't committed yet
-          var engines = gEngineView._engineStore.engines;
-          for each (var engine in engines) {
-            if (engine.alias == alias.value && 
-                engine.name != selectedEngine.name) {
-              eduplicate = true;
-              break;
-            }
+            break;
           }
         }
       }
 
       // Notify the user if they have chosen an existing engine/bookmark keyword
       if (eduplicate || bduplicate) {
         var dtitle = strings.getString("duplicateTitle");
         var bmsg = strings.getString("duplicateBookmarkMsg");
--- a/browser/components/search/content/engineManager.xul
+++ b/browser/components/search/content/engineManager.xul
@@ -120,12 +120,12 @@
   <hbox>
     <checkbox id="enableSuggest"
               label="&enableSuggest.label;"
               accesskey="&enableSuggest.accesskey;"/>
     <spacer flex="1"/>
   </hbox>
   <hbox>
     <label id="addEngines" class="text-link" value="&addEngine.label;"
-           onclick="gEngineManagerDialog.loadAddEngines();"/>
+           onclick="if (event.button == 0) { gEngineManagerDialog.loadAddEngines(); }"/>
     <spacer flex="1"/>
   </hbox>
 </dialog>
--- a/browser/components/sessionstore/nsISessionStore.idl
+++ b/browser/components/sessionstore/nsISessionStore.idl
@@ -38,137 +38,153 @@
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 interface nsIDOMNode;
 
 /**
  * nsISessionStore keeps track of the current browsing state - i.e.
  * tab history, cookies, scroll state, form data, POSTDATA and window features
- * - and allows to restore everything into one window.
+ * - and allows to restore everything into one browser window.
+ *
+ * The nsISessionStore API operates mostly on browser windows and the tabbrowser
+ * tabs contained in them:
+ *
+ * * "Browser windows" are those DOM windows having loaded
+ * chrome://browser/content/browser.xul . From overlays you can just pass the
+ * global |window| object to the API, though (or |top| from a sidebar).
+ * From elsewhere you can get browser windows through the nsIWindowMediator
+ * by looking for "navigator:browser" windows.
+ *
+ * * "Tabbrowser tabs" are all the child nodes of a browser window's
+ * |getBrowser().tabContainer| such as e.g. |getBrowser().selectedTab|.
+ *
+ * Note: This API will break in all sorts of way if the preference
+ *       browser.sessionstore.enabled is set to false (once bug ...
+ *       is fixed, the service won't be available at all).
  */
 
 [scriptable, uuid(58d17e12-a80f-11dc-8314-0800200c9a66)]
 interface nsISessionStore : nsISupports
 {
   /**
    * Initialize the service
    */
   void init(in nsIDOMWindow aWindow);
 
   /**
    * Get the current browsing state.
-   * @return a JSON string representing the session state.
+   * @returns a JSON string representing the session state.
    */
   AString getBrowserState();
 
   /**
    * Set the browsing state.
    * This will immediately restore the state of the whole application to the state
    * passed in, *replacing* the current session.
    *
    * @param aState is a JSON string representing the session state.
    */
   void setBrowserState(in AString aState);
 
   /**
-   * @param aWindow is the window whose state is to be returned.
+   * @param aWindow is the browser window whose state is to be returned.
    * 
-   * @return a JSON string representing a session state with only one window.
+   * @returns a JSON string representing a session state with only one window.
    */
   AString getWindowState(in nsIDOMWindow aWindow);
 
   /**
-   * @param aWindow    is the window whose state is to be set.
+   * @param aWindow    is the browser window whose state is to be set.
    * @param aState     is a JSON string representing a session state.
    * @param aOverwrite boolean overwrite existing tabs
    */
   void setWindowState(in nsIDOMWindow aWindow, in AString aState, in boolean aOverwrite);
 
   /**
-   * @param aTab is the tab whose state is to be returned.
+   * @param aTab is the tabbrowser tab whose state is to be returned.
    * 
-   * @return a JSON string representing the state of the tab
+   * @returns a JSON string representing the state of the tab
    *         (note: doesn't contain cookies - if you need them, use getWindowState instead).
    */
   AString getTabState(in nsIDOMNode aTab);
 
   /**
-   * @param aTab   is the tab whose state is to be set.
+   * @param aTab   is the tabbrowser tab whose state is to be set.
    * @param aState is a JSON string representing a session state.
    */
   void setTabState(in nsIDOMNode aTab, in AString aState);
 
   /**
    * Duplicates a given tab as thoroughly as possible.
    *
-   * @param aWindow is the window into which the tab will be duplicated.
-   * @param aTab    is the tab to duplicate (can be from a different window).
-   * @return a reference to the newly created tab.
+   * @param aWindow is the browser window into which the tab will be duplicated.
+   * @param aTab    is the tabbrowser tab to duplicate (can be from a different window).
+   * @returns a reference to the newly created tab.
    */
   nsIDOMNode duplicateTab(in nsIDOMWindow aWindow, in nsIDOMNode aTab);
 
   /**
-   * Get the number of restore-able tabs for a window
+   * Get the number of restore-able tabs for a browser window
    */
   unsigned long getClosedTabCount(in nsIDOMWindow aWindow);
 
   /**
    * Get closed tab data
-   * @return a JSON string representing the list of closed tabs.
+   *
+   * @param aWindow is the browser window for which to get closed tab data
+   * @returns a JSON string representing the list of closed tabs.
    */
   AString getClosedTabData(in nsIDOMWindow aWindow);
 
   /**
-   * @param aWindow
-   *          The window to reopen a closed tab in.
-   * @param aIndex
-   *          Indicates the window to be restored (FIFO ordered).
+   * @param aWindow is the browser window to reopen a closed tab in.
+   * @param aIndex  is the index of the tab to be restored (FIFO ordered).
    */
   void undoCloseTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
 
   /**
    * @param aWindow is the window to get the value for.
    * @param aKey    is the value's name.
    * 
-   * @return A string value or "" if none is set.
+   * @returns A string value or an empty string if none is set.
    */
   AString getWindowValue(in nsIDOMWindow aWindow, in AString aKey);
 
   /**
-   * @param aWindow      is the window to set the value for.
+   * @param aWindow      is the browser window to set the value for.
    * @param aKey         is the value's name.
    * @param aStringValue is the value itself (use toSource/eval before setting JS objects).
    */
   void setWindowValue(in nsIDOMWindow aWindow, in AString aKey, in AString aStringValue);
   
   /**
-   * @param aWindow is the window to get the value for.
+   * @param aWindow is the browser window to get the value for.
    * @param aKey    is the value's name.
    */
   void deleteWindowValue(in nsIDOMWindow aWindow, in AString aKey);
 
   /**
-   * @param aTab is the tab to get the value for.
+   * @param aTab is the tabbrowser tab to get the value for.
    * @param aKey is the value's name.
    * 
-   * @return A string value or "" if none is set.
+   * @returns A string value or an empty string if none is set.
    */
   AString getTabValue(in nsIDOMNode aTab, in AString aKey);
 
   /**
-   * @param aTab         is the tab to set the value for.
+   * @param aTab         is the tabbrowser tab to set the value for.
    * @param aKey         is the value's name.
    * @param aStringValue is the value itself (use toSource/eval before setting JS objects).
    */
   void setTabValue(in nsIDOMNode aTab, in AString aKey, in AString aStringValue);
 
   /**
-   * @param aTab is the tab to get the value for.
+   * @param aTab is the tabbrowser tab to get the value for.
    * @param aKey is the value's name.
    */
   void deleteTabValue(in nsIDOMNode aTab, in AString aKey);
 
   /**
-   * @param aName is the name of the attribute to save/restore for all xul:tabs.
+   * @param aName is the name of the attribute to save/restore for all tabbrowser tabs.
    */
   void persistTabAttribute(in AString aName);
 };
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -596,16 +596,17 @@ components/nsKillAll.js
 components/passwordmgr.xpt
 components/progressDlg.xpt
 components/safebrowsing.xpt
 components/search.xpt
 components/websrvcs.xpt
 components/widget_mac.xpt
 components/xml-rpc.xpt
 components/xpcom_obsolete.xpt
+updater.app/Contents/MacOS/updater.ini
 init.d/README
 redo-prebinding.sh
 res/viewer.properties
 res/bloatcycle.html
 #endif
 #ifdef XP_UNIX
 #ifndef XP_MACOSX
 readme.txt
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -304,20 +304,16 @@ endif
 	@$(MAKE) repackage-zip-$*
 
 ifdef MOZ_UPDATER
 libs:: $(addprefix $(LOCALE_SRCDIR)/,updater/updater.ini)
 ifeq ($(OS_ARCH),WINNT)
 	cat $< $(srcdir)/../installer/windows/nsis/updater_append.ini | \
 	  iconv -f UTF-8 -t $(WIN_INSTALLER_CHARSET) > $(FINAL_TARGET)/updater.ini
 else
-ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
-	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/updater.app/Contents/MacOS
-else
 	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
 endif
 endif
-endif
 
 ifdef MOZ_CRASHREPORTER
 libs:: $(addprefix $(LOCALE_SRCDIR)/,crashreporter/crashreporter-override.ini)
 	$(SYSINSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)
 endif
--- a/browser/locales/en-US/chrome/browser-region/region.properties
+++ b/browser/locales/en-US/chrome/browser-region/region.properties
@@ -17,18 +17,20 @@ browser.contentHandlers.types.2.uri=http
 # Keyword URL (for location bar searches)
 keyword.URL=http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=
 
 # increment this number when anything gets changed in the list below.  This will
 # cause Firefox to re-read these prefs and inject any new handlers into the 
 # profile database.  Note that "new" is defined as "has a different URL"; this
 # means that it's not possible to update the name of existing handler, so 
 # don't make any spelling errors here.
-gecko.handlerService.defaultHandlersVersion=1
+gecko.handlerService.defaultHandlersVersion=2
 
 # The default set of protocol handlers for webcal:
 gecko.handlerService.schemes.webcal.0.name=30 Boxes
 gecko.handlerService.schemes.webcal.0.uriTemplate=http://30boxes.com/external/widget?refer=ff&url=%s
 
 # The default set of protocol handlers for mailto:
 gecko.handlerService.schemes.mailto.0.name=Yahoo! Mail
 gecko.handlerService.schemes.mailto.0.uriTemplate=http://compose.mail.yahoo.com/?To=%s 
+gecko.handlerService.schemes.mailto.1.name=Gmail
+gecko.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?extsrc=mailto&url=%s
 
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -126,17 +126,16 @@ MOZ_MAIL_NEWS	= @MOZ_MAIL_NEWS@
 MOZ_CALENDAR	= @MOZ_CALENDAR@
 MOZ_PLAINTEXT_EDITOR_ONLY = @MOZ_PLAINTEXT_EDITOR_ONLY@
 MOZ_COMPOSER = @MOZ_COMPOSER@
 BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@
 MOZ_ENABLE_LIBXUL = @MOZ_ENABLE_LIBXUL@
 ENABLE_TESTS	= @ENABLE_TESTS@
 IBMBIDI = @IBMBIDI@
 MOZ_UNIVERSALCHARDET = @MOZ_UNIVERSALCHARDET@
-SUNCTL = @SUNCTL@
 ACCESSIBILITY = @ACCESSIBILITY@
 MOZ_VIEW_SOURCE = @MOZ_VIEW_SOURCE@
 MOZ_XPINSTALL = @MOZ_XPINSTALL@
 MOZ_JSLOADER  = @MOZ_JSLOADER@
 MOZ_USE_NATIVE_UCONV = @MOZ_USE_NATIVE_UCONV@
 MOZ_LDAP_XPCOM = @MOZ_LDAP_XPCOM@
 MOZ_LDAP_XPCOM_EXPERIMENTAL = @MOZ_LDAP_XPCOM_EXPERIMENTAL@
 MOZ_BRANDING_DIRECTORY = @MOZ_BRANDING_DIRECTORY@
--- a/config/system-headers
+++ b/config/system-headers
@@ -85,16 +85,69 @@ cairo-pdf.h
 cairo-ps.h
 cairo-quartz.h
 cairo-win32.h
 cairo-xlib.h
 cairo-xlib-xrender.h
 cairo-directfb.h
 cairo-qpainter.h
 #endif
+dfiff.h
+fusion/reactor.h
+fusion/property.h
+fusion/conf.h
+fusion/build.h
+fusion/hash.h
+fusion/shm/shm.h
+fusion/shm/shm_internal.h
+fusion/shm/pool.h
+fusion/ref.h
+fusion/fusion_internal.h
+fusion/lock.h
+fusion/types.h
+fusion/vector.h
+fusion/call.h
+fusion/shmalloc.h
+fusion/protocol.h
+fusion/fusion.h
+fusion/arena.h
+fusion/object.h
+directfbgl.h
+directfb_version.h
+directfb.h
+directfb_util.h
+directfb_keynames.h
+dgiff.h
+direct/util.h
+direct/memcpy.h
+direct/interface.h
+direct/conf.h
+direct/tree.h
+direct/signals.h
+direct/build.h
+direct/interface_implementation.h
+direct/utf8.h
+direct/serial.h
+direct/hash.h
+direct/direct.h
+direct/clock.h
+direct/types.h
+direct/mem.h
+direct/thread.h
+direct/debug.h
+direct/stream.h
+direct/messages.h
+direct/trace.h
+direct/modules.h
+direct/log.h
+direct/system.h
+direct/list.h
+dfb_types.h
+directfb_strings.h
+directfb_keyboard.h
 callconv.h
 Carbon/Carbon.h
 CarbonEvents.h
 Carbon.h
 cassert
 c_asm.h
 cctype
 cderr.h
@@ -225,16 +278,17 @@ gdk/gdkevents.h
 gdk/gdk.h
 gdk/gdkkeysyms.h
 gdk/gdkpango.h
 gdk/gdkprivate.h
 gdk/gdkscreen.h
 gdk/gdkregion.h
 gdk/gdkwindow.h
 gdk/gdkx.h
+gdk/gdkdirectfb.h
 gdk-pixbuf/gdk-pixbuf.h
 Gestalt.h
 getopt.h
 glibconfig.h
 glib.h
 glib-object.h
 gmodule.h
 gnome.h
--- a/configure.in
+++ b/configure.in
@@ -203,17 +203,17 @@ fi
 COMPILE_ENVIRONMENT=1
 MOZ_ARG_ENABLE_BOOL(compile-environment,
 [  --disable-compile-environment
                            Disable compiler/library checks.],
     COMPILE_ENVIRONMENT=1,
     COMPILE_ENVIRONMENT= )
 
 MOZ_ARG_WITH_STRING(l10n-base,
-[  --with-l10nbase=DIR     path to l10n repositories],
+[  --with-l10n-base=DIR     path to l10n repositories],
     L10NBASEDIR=$withval)
 if test ! -z "$L10NBASEDIR"; then
     if test "$L10NBASEDIR" = "yes" -o "$L10NBASEDIR" = "no"; then
         AC_MSG_ERROR([--with-l10n-base must specify a path])
     elif test -d "$L10NBASEDIR"; then
         L10NBASEDIR=`cd "$L10NBASEDIR" && pwd`
     else
         AC_MSG_ERROR([Invalid value --with-l10n-base, $L10NBASEDIR doesn't exist])
@@ -1308,17 +1308,16 @@ if test "$GNU_CC"; then
     _MOZ_EXCEPTIONS_FLAGS_OFF='-fno-handle-exceptions'
 
     # Turn on GNU specific features
     # -Wall - turn on all warnings
     # -pedantic - make compiler warn about non-ANSI stuff, and
     #             be a little bit stricter
     # Warnings slamm took out for now (these were giving more noise than help):
     # -Wbad-function-cast - warns when casting a function to a new return type
-    # -Wconversion - complained when char's or short's were used a function args
     # -Wshadow - removed because it generates more noise than help --pete
     _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -W -Wno-unused -Wpointer-arith"
     if test -z "$INTEL_CC"; then
        # Don't use -Wcast-align with ICC
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, since it's noisy there
            hppa | ia64 | sparc)
            ;;
@@ -1355,17 +1354,17 @@ else
     DSO_PIC_CFLAGS='-KPIC'
     _DEFINES_CFLAGS='$(ACDEFINES) -D_MOZILLA_CONFIG_H_ -DMOZILLA_CLIENT'
 fi
 
 if test "$GNU_CXX"; then
     # FIXME: Let us build with strict aliasing. bug 414641.
     CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
     # Turn on GNU specific features
-    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wconversion -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
     if test -z "$INTEL_CC"; then
        # Don't use -Wcast-align with ICC
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, since it's noisy there
            hppa | ia64 | sparc)
            ;;
            *)
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
@@ -1577,31 +1576,16 @@ dnl Get version of various core apps fro
 FIREFOX_VERSION=`cat $topsrcdir/browser/config/version.txt`
 THUNDERBIRD_VERSION=`cat $topsrcdir/mail/config/version.txt`
 SUNBIRD_VERSION=`cat $topsrcdir/calendar/sunbird/config/version.txt`
 SEAMONKEY_VERSION=`cat $topsrcdir/suite/config/version.txt`
 
 AC_DEFINE_UNQUOTED(MOZILLA_VERSION,"$MOZILLA_VERSION")
 AC_DEFINE_UNQUOTED(MOZILLA_VERSION_U,$MOZILLA_VERSION)
 
-PKG_CHECK_MODULES(LIBHILONMIME,libhildonmime,
-                  NS_HILDON=1,
-                  NS_HILDON=)
-if test $NS_HILDON; then
-   AC_DEFINE(NS_HILDON)
-fi
-
-PKG_CHECK_MODULES(LIBOSSO,libosso,
-                  NS_OSSO=1,
-                  NS_OSSO=)
-
-if test $NS_OSSO; then
-   AC_DEFINE(NS_OSSO)     
-fi
-
 dnl ========================================================
 dnl System overrides of the defaults for target
 dnl ========================================================
 
 case "$target" in
 *-aix*)
     AC_DEFINE(AIX)
     if test ! "$GNU_CC"; then
@@ -4400,17 +4384,16 @@ MOZ_XTF=1
 MOZ_XUL=1
 MOZ_XUL_APP=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 NECKO_COOKIES=1
 NECKO_DISK_CACHE=1
 NECKO_PROTOCOLS_DEFAULT="about data file ftp gopher http res viewsource"
 NECKO_SMALL_BUFFERS=
-SUNCTL=
 JS_STATIC_BUILD=
 XPC_IDISPATCH_SUPPORT=
 
 
 case "$target_os" in
 darwin*)
     ACCESSIBILITY=
     ;;
@@ -5281,24 +5264,16 @@ if test -n "$MOZ_OJI"; then
     AC_DEFINE(OJI)
 fi
 
 dnl bi-directional support always on
 IBMBIDI=1
 AC_DEFINE(IBMBIDI)
 
 dnl ========================================================
-dnl complex text support off by default
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(ctl,
-[  --enable-ctl            Enable Thai Complex Script support],
-    SUNCTL=1,
-    SUNCTL= )
-
-dnl ========================================================
 dnl view source support on by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(view-source,
 [  --disable-view-source     Disable view source support],
     MOZ_VIEW_SOURCE=,
     MOZ_VIEW_SOURCE=1 )
 if test "$MOZ_VIEW_SOURCE"; then
     AC_DEFINE(MOZ_VIEW_SOURCE)
@@ -6126,16 +6101,17 @@ then
     SQLITE_CFLAGS=
     SQLITE_LIBS='$(call EXPAND_LIBNAME_PATH,sqlite3,$(DIST)/lib)'
 else
     PKG_CHECK_MODULES(SQLITE, sqlite3 >= $SQLITE_VERSION)
 fi
 
 AC_SUBST(MOZ_NATIVE_SQLITE)
 
+dnl ========================================================
 dnl = Enable help viewer (off by default)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(help-viewer,
 [  --enable-help-viewer        Enable help viewer],
     MOZ_HELP_VIEWER=1,
     MOZ_HELP_VIEWER= )
 if test -n "$MOZ_HELP_VIEWER"; then
      AC_DEFINE(MOZ_HELP_VIEWER)
@@ -6193,16 +6169,37 @@ MOZ_ARG_ENABLE_BOOL(js-ultrasparc,
 dnl only enable option for ultrasparcs
 if test `echo "$target_os" | grep -c \^solaris 2>/dev/null` = 0 -o \
     "$OS_TEST" != "sun4u"; then
     JS_ULTRASPARC_OPTS=
 fi
 AC_SUBST(JS_ULTRASPARC_OPTS)
 
 dnl ========================================================
+dnl = Hildon and OSSO checks
+dnl ========================================================
+PKG_CHECK_MODULES(LIBHILONMIME,libhildonmime,
+                  NS_HILDON=1,
+                  NS_HILDON=)
+if test $NS_HILDON; then
+   AC_DEFINE(NS_HILDON)
+fi
+
+PKG_CHECK_MODULES(LIBOSSO,libosso,
+                  NS_OSSO=1,
+                  NS_OSSO=)
+
+if test $NS_OSSO; then
+    if test -z "$MOZ_ENABLE_DBUS"; then
+        AC_MSG_ERROR([DBus is required when building for OSSO])
+    fi
+    AC_DEFINE(NS_OSSO)     
+fi
+
+dnl ========================================================
 dnl =
 dnl = Feature options that require extra sources to be pulled
 dnl =
 dnl ========================================================
 dnl MOZ_ARG_HEADER(Features that require extra sources)
 
 dnl ========================================================
 dnl =
@@ -7920,32 +7917,16 @@ if test "$MOZ_LDAP_XPCOM"; then
         fi
     elif test "$OS_ARCH" = "OS2"; then
             LDAP_LIBS='$(DIST)/lib/$(LIB_PREFIX)ldap60.${IMPORT_LIB_SUFFIX} $(DIST)/lib/$(LIB_PREFIX)prldap60.${IMPORT_LIB_SUFFIX} $(DIST)/lib/$(LIB_PREFIX)ldif60.${IMPORT_LIB_SUFFIX}'
     else
         LDAP_LIBS='-L${DIST}/bin -L${DIST}/lib -lldap60 -lprldap60 -lldif60'
     fi
 fi
 
-if test "$COMPILE_ENVIRONMENT"; then
-if test "$SUNCTL"; then
-    dnl older versions of glib do not seem to have gmodule which ctl needs
-    _SAVE_CFLAGS=$CFLAGS
-    CFLAGS="$CFLAGS $GLIB_CFLAGS"
-    AC_LANG_SAVE
-    AC_LANG_C
-    AC_TRY_COMPILE([#include <gmodule.h>],
-        [ int x = 1; x++; ],,
-        [AC_MSG_ERROR([Cannot build ctl without gmodule support in glib.])])
-    AC_LANG_RESTORE
-    CFLAGS=$_SAVE_CFLAGS
-    AC_DEFINE(SUNCTL)
-fi
-fi # COMPILE_ENVIRONMENT
-
 dnl ========================================================
 dnl =
 dnl = Maintainer debug option (no --enable equivalent)
 dnl =
 dnl ========================================================
 
 AC_SUBST(AR)
 AC_SUBST(AR_FLAGS)
@@ -8042,17 +8023,16 @@ AC_SUBST(HAVE_XIE)
 AC_SUBST(MOZ_XIE_LIBS)
 AC_SUBST(MOZ_ENABLE_POSTSCRIPT)
 
 AC_SUBST(XPCOM_USE_LEA)
 AC_SUBST(BUILD_STATIC_LIBS)
 AC_SUBST(MOZ_ENABLE_LIBXUL)
 AC_SUBST(ENABLE_TESTS)
 AC_SUBST(IBMBIDI)
-AC_SUBST(SUNCTL)
 AC_SUBST(MOZ_UNIVERSALCHARDET)
 AC_SUBST(ACCESSIBILITY)
 AC_SUBST(MOZ_XPINSTALL)
 AC_SUBST(MOZ_VIEW_SOURCE)
 AC_SUBST(MOZ_SPELLCHECK)
 AC_SUBST(MOZ_XPFE_COMPONENTS)
 AC_SUBST(MOZ_USER_DIR)
 AC_SUBST(MOZ_CRASHREPORTER)
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -30,26 +30,41 @@
  * 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 "nsISupports.idl"
+#include "nsIDOMEventTarget.idl"
 
 interface nsIChannel;
 interface nsIDOMDocument;
 interface nsIDOMEventListener;
 interface nsIPrincipal;
 interface nsIScriptContext;
 interface nsIVariant;
 interface nsPIDOMWindow;
 
+[scriptable, uuid(6ce0a193-b033-4c3d-b748-f851b09261f5)]
+interface nsIXMLHttpRequestEventTarget : nsIDOMEventTarget {
+  // event handler attributes
+  attribute nsIDOMEventListener onabort;
+  attribute nsIDOMEventListener onerror;
+  attribute nsIDOMEventListener onload;
+  attribute nsIDOMEventListener onloadstart;
+  attribute nsIDOMEventListener onprogress;
+};
+
+[scriptable, uuid(09ff3682-7759-4441-a765-f70e1a1fabcf)]
+interface nsIXMLHttpRequestUpload : nsIXMLHttpRequestEventTarget {
+  // for future use
+};
+
 /**
  * Mozilla's XMLHttpRequest is modelled after Microsoft's IXMLHttpRequest
  * object. The goal has been to make Mozilla's version match Microsoft's
  * version as closely as possible, but there are bound to be some differences.
  *
  * In general, Microsoft's documentation for IXMLHttpRequest can be used.
  * Mozilla's interface definitions provide some additional documentation. The
  * web page to look at is http://www.mozilla.org/xmlextras/
@@ -77,20 +92,16 @@ interface nsPIDOMWindow;
  *
  *   where mylistener is your event listener object that implements the
  *   interface nsIDOMEventListener.
  *
  *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
  *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
  *   those.
  *
- * Though actually, if you use addEventListener from C++ weird things will
- * happen too, since the result will depend on what JS happens to be on the
- * stack when you do it....
- *
  * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
  * you're aware of all the security implications.  And then think twice about
  * it.
  */
 [scriptable, uuid(acda85ab-d06c-4176-b834-6d129ca97ca3)]
 interface nsIXMLHttpRequest : nsISupports
 {
   /**
@@ -320,16 +331,24 @@ interface nsIXMLHttpRequest : nsISupport
    *                      null.
    * @param ownerWindow The associated window for the request. May be null.
    */
   [noscript] void init(in nsIPrincipal principal,
                        in nsIScriptContext scriptContext,
                        in nsPIDOMWindow ownerWindow);
 };
 
+[scriptable, uuid(6e127bd2-b4c1-4a82-be0d-012bd24efb37)]
+interface nsIXMLHttpRequestUploadGetter : nsISupports {
+  /**
+   * Upload process can be tracked by adding event listener to |upload|.
+   */
+  readonly attribute nsIXMLHttpRequestUpload upload;
+};
+
 [scriptable, uuid(261676b4-d508-43bf-b099-74635a0ee2e9)]
 interface nsIJSXMLHttpRequest : nsISupports {
   /**
    * Meant to be a script-only mechanism for setting a load event listener.
    * The attribute is expected to be JavaScript function object. When
    * the load event occurs, the function is invoked.
    * This attribute should not be used from native code!!
    *
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -120,16 +120,22 @@
 #include "nsIDOMUserDataHandler.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsIEditor.h"
 #include "nsIEditorDocShell.h"
 #include "nsEventDispatcher.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsIFocusController.h"
 #include "nsIControllers.h"
+#include "nsLayoutUtils.h"
+#include "nsIView.h"
+#include "nsIViewManager.h"
+#include "nsIScrollableFrame.h"
+#include "nsIScrollableView.h"
+#include "nsIScrollableViewProvider.h"
 #include "nsXBLInsertionPoint.h"
 #include "nsICSSStyleRule.h" /* For nsCSSSelectorList */
 #include "nsCSSRuleProcessor.h"
 
 #ifdef MOZ_XUL
 #include "nsIXULDocument.h"
 #endif /* MOZ_XUL */
 
@@ -793,16 +799,325 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNSEle
 
 NS_IMETHODIMP
 nsNSElementTearoff::GetElementsByClassName(const nsAString& aClasses,
                                            nsIDOMNodeList** aReturn)
 {
   return nsDocument::GetElementsByClassNameHelper(mContent, aClasses, aReturn);
 }
 
+nsIFrame*
+nsGenericElement::GetStyledFrame()
+{
+  nsIFrame *frame = GetPrimaryFrame(Flush_Layout);
+
+  return (frame && frame->GetType() == nsGkAtoms::tableOuterFrame) ?
+    frame->GetFirstChild(nsnull) : frame;
+}
+
+void
+nsGenericElement::GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent)
+{
+  *aOffsetParent = nsnull;
+  aRect = nsRect();
+
+  nsIFrame* frame = GetStyledFrame();
+  if (!frame) {
+    return;
+  }
+
+  nsPoint origin = frame->GetPosition();
+  aRect.x = nsPresContext::AppUnitsToIntCSSPixels(origin.x);
+  aRect.y = nsPresContext::AppUnitsToIntCSSPixels(origin.y);
+
+  // Get the union of all rectangles in this and continuation frames.
+  // It doesn't really matter what we use as aRelativeTo here, since
+  // we only care about the size. Using 'parent' might make things
+  // a bit faster by speeding up the internal GetOffsetTo operations.
+  nsRect rcFrame = nsLayoutUtils::GetAllInFlowRectsUnion(frame, nsnull);
+  aRect.width = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.width);
+  aRect.height = nsPresContext::AppUnitsToIntCSSPixels(rcFrame.height);
+}
+
+void
+nsNSElementTearoff::GetScrollInfo(nsIScrollableView **aScrollableView,
+                                  nsIFrame **aFrame)
+{
+  *aScrollableView = nsnull;
+
+  // it isn't clear what to return for SVG nodes, so just return nothing
+  if (mContent->IsNodeOfType(nsINode::eSVG)) {
+    if (aFrame)
+      *aFrame = nsnull;
+    return;
+  }
+
+  nsIFrame* frame =
+    (static_cast<nsGenericElement*>(mContent))->GetStyledFrame();
+
+  if (aFrame) {
+    *aFrame = frame;
+  }
+  if (!frame) {
+    return;
+  }
+
+  // Get the scrollable frame
+  nsIScrollableFrame *scrollFrame = nsnull;
+  CallQueryInterface(frame, &scrollFrame);
+
+  if (!scrollFrame) {
+    nsIScrollableViewProvider *scrollProvider = nsnull;
+    CallQueryInterface(frame, &scrollProvider);
+    // menu frames implement nsIScrollableViewProvider but we don't want
+    // to use it here.
+    if (scrollProvider && frame->GetType() != nsGkAtoms::menuFrame) {
+      *aScrollableView = scrollProvider->GetScrollableView();
+      if (*aScrollableView) {
+        return;
+      }
+    }
+
+    nsIDocument* doc = mContent->GetCurrentDoc();
+    PRBool quirksMode = doc &&
+                        doc->GetCompatibilityMode() == eCompatibility_NavQuirks;
+    if ((quirksMode && mContent->NodeInfo()->Equals(nsGkAtoms::body)) ||
+        (!quirksMode && mContent->NodeInfo()->Equals(nsGkAtoms::html))) {
+      // In quirks mode, the scroll info for the body element should map to the
+      // scroll info for the nearest scrollable frame above the body element
+      // (i.e. the root scrollable frame).  This is what IE6 does in quirks
+      // mode.  In strict mode the root scrollable frame corresponds to the
+      // html element in IE6, so we map the scroll info for the html element to
+      // the root scrollable frame.
+
+      do {
+        frame = frame->GetParent();
+
+        if (!frame) {
+          break;
+        }
+
+        CallQueryInterface(frame, &scrollFrame);
+      } while (!scrollFrame);
+    }
+
+    if (!scrollFrame) {
+      return;
+    }
+  }
+
+  // Get the scrollable view
+  *aScrollableView = scrollFrame->GetScrollableView();
+}
+
+nsresult
+nsNSElementTearoff::GetScrollTop(PRInt32* aScrollTop)
+{
+  NS_ENSURE_ARG_POINTER(aScrollTop);
+  *aScrollTop = 0;
+
+  nsIScrollableView *view;
+  nsresult rv = NS_OK;
+
+  GetScrollInfo(&view);
+
+  if (view) {
+    nscoord xPos, yPos;
+    rv = view->GetScrollPosition(xPos, yPos);
+
+    *aScrollTop = nsPresContext::AppUnitsToIntCSSPixels(yPos);
+  }
+
+  return rv;
+}
+
+nsresult
+nsNSElementTearoff::SetScrollTop(PRInt32 aScrollTop)
+{
+  nsIScrollableView *view;
+  nsresult rv = NS_OK;
+
+  GetScrollInfo(&view);
+
+  if (view) {
+    nscoord xPos, yPos;
+
+    rv = view->GetScrollPosition(xPos, yPos);
+
+    if (NS_SUCCEEDED(rv)) {
+      rv = view->ScrollTo(xPos, nsPresContext::CSSPixelsToAppUnits(aScrollTop),
+                          NS_VMREFRESH_IMMEDIATE);
+    }
+  }
+
+  return rv;
+}
+
+nsresult
+nsNSElementTearoff::GetScrollLeft(PRInt32* aScrollLeft)
+{
+  NS_ENSURE_ARG_POINTER(aScrollLeft);
+  *aScrollLeft = 0;
+
+  nsIScrollableView *view;
+  nsresult rv = NS_OK;
+
+  GetScrollInfo(&view);
+
+  if (view) {
+    nscoord xPos, yPos;
+    rv = view->GetScrollPosition(xPos, yPos);
+
+    *aScrollLeft = nsPresContext::AppUnitsToIntCSSPixels(xPos);
+  }
+
+  return rv;
+}
+
+nsresult
+nsNSElementTearoff::SetScrollLeft(PRInt32 aScrollLeft)
+{
+  nsIScrollableView *view;
+  nsresult rv = NS_OK;
+
+  GetScrollInfo(&view);
+
+  if (view) {
+    nscoord xPos, yPos;
+    rv = view->GetScrollPosition(xPos, yPos);
+
+    if (NS_SUCCEEDED(rv)) {
+      rv = view->ScrollTo(nsPresContext::CSSPixelsToAppUnits(aScrollLeft),
+                          yPos, NS_VMREFRESH_IMMEDIATE);
+    }
+  }
+
+  return rv;
+}
+
+nsresult
+nsNSElementTearoff::GetScrollHeight(PRInt32* aScrollHeight)
+{
+  NS_ENSURE_ARG_POINTER(aScrollHeight);
+  *aScrollHeight = 0;
+
+  if (mContent->IsNodeOfType(nsINode::eSVG))
+    return NS_OK;
+
+  nsIScrollableView *scrollView;
+  nsresult rv = NS_OK;
+
+  GetScrollInfo(&scrollView);
+
+  if (!scrollView) {
+    nsRect rcFrame;
+    nsCOMPtr<nsIContent> parent;
+    (static_cast<nsGenericElement *>(mContent))->GetOffsetRect(rcFrame, getter_AddRefs(parent));
+    *aScrollHeight = rcFrame.height;
+    return NS_OK;
+  }
+
+  // xMax and yMax is the total length of our container
+  nscoord xMax, yMax;
+  rv = scrollView->GetContainerSize(&xMax, &yMax);
+
+  *aScrollHeight = nsPresContext::AppUnitsToIntCSSPixels(yMax);
+
+  return rv;
+}
+
+nsresult
+nsNSElementTearoff::GetScrollWidth(PRInt32* aScrollWidth)
+{
+  NS_ENSURE_ARG_POINTER(aScrollWidth);
+  *aScrollWidth = 0;
+
+  if (mContent->IsNodeOfType(nsINode::eSVG))
+    return NS_OK;
+
+  nsIScrollableView *scrollView;
+  nsresult rv = NS_OK;
+
+  GetScrollInfo(&scrollView);
+
+  if (!scrollView) {
+    nsRect rcFrame;
+    nsCOMPtr<nsIContent> parent;
+    (static_cast<nsGenericElement *>(mContent))->GetOffsetRect(rcFrame, getter_AddRefs(parent));
+    *aScrollWidth = rcFrame.width;
+    return NS_OK;
+  }
+
+  nscoord xMax, yMax;
+  rv = scrollView->GetContainerSize(&xMax, &yMax);
+
+  *aScrollWidth = nsPresContext::AppUnitsToIntCSSPixels(xMax);
+
+  return rv;
+}
+
+nsRect
+nsNSElementTearoff::GetClientAreaRect()
+{
+  nsIScrollableView *scrollView;
+  nsIFrame *frame;
+
+  // it isn't clear what to return for SVG nodes, so just return 0
+  if (mContent->IsNodeOfType(nsINode::eSVG))
+    return nsRect(0, 0, 0, 0);
+
+  GetScrollInfo(&scrollView, &frame);
+
+  if (scrollView) {
+    return scrollView->View()->GetBounds();
+  }
+
+  if (frame &&
+      (frame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
+       frame->IsFrameOfType(nsIFrame::eReplaced))) {
+    // Special case code to make client area work even when there isn't
+    // a scroll view, see bug 180552, bug 227567.
+    return frame->GetPaddingRect() - frame->GetPositionIgnoringScrolling();
+  }
+
+  return nsRect(0, 0, 0, 0);
+}
+
+nsresult
+nsNSElementTearoff::GetClientTop(PRInt32* aLength)
+{
+  NS_ENSURE_ARG_POINTER(aLength);
+  *aLength = nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().y);
+  return NS_OK;
+}
+
+nsresult
+nsNSElementTearoff::GetClientLeft(PRInt32* aLength)
+{
+  NS_ENSURE_ARG_POINTER(aLength);
+  *aLength = nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().x);
+  return NS_OK;
+}
+
+nsresult
+nsNSElementTearoff::GetClientHeight(PRInt32* aLength)
+{
+  NS_ENSURE_ARG_POINTER(aLength);
+  *aLength = nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().height);
+  return NS_OK;
+}
+
+nsresult
+nsNSElementTearoff::GetClientWidth(PRInt32* aLength)
+{
+  NS_ENSURE_ARG_POINTER(aLength);
+  *aLength = nsPresContext::AppUnitsToIntCSSPixels(GetClientAreaRect().width);
+  return NS_OK;
+}
+
 static nsIFrame*
 GetContainingBlockForClientRect(nsIFrame* aFrame)
 {
   // get the nearest enclosing SVG foreign object frame or the root frame
   while (aFrame->GetParent() &&
          !aFrame->IsFrameOfType(nsIFrame::eSVGForeignObject)) {
     aFrame = aFrame->GetParent();
   }
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -73,16 +73,18 @@ class nsIDOMNamedNodeMap;
 class nsDOMCSSDeclaration;
 class nsIDOMCSSStyleDeclaration;
 class nsIURI;
 class nsVoidArray;
 class nsINodeInfo;
 class nsIControllers;
 class nsIDOMNSFeatureFactory;
 class nsIEventListenerManager;
+class nsIScrollableView;
+struct nsRect;
 
 typedef unsigned long PtrBits;
 
 /**
  * Class that implements the nsIDOMNodeList interface (a list of children of
  * the content), by holding a reference to the content and delegating GetLength
  * and Item to its existing child list.
  * @see nsIDOMNodeList
@@ -391,16 +393,18 @@ private:
  * nsIDOMNode and nsIDOMElement methods.
  */
 class nsGenericElement : public nsIContent
 {
 public:
   nsGenericElement(nsINodeInfo *aNodeInfo);
   virtual ~nsGenericElement();
 
+  friend class nsNSElementTearoff;
+
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   /**
    * Called during QueryInterface to give the binding manager a chance to
    * get an interface for this element.
    */
   nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
 
@@ -941,16 +945,27 @@ protected:
    */
   nsresult CopyInnerTo(nsGenericElement* aDest) const;
 
   /**
    * Internal hook for converting an attribute name-string to an atomized name
    */
   virtual const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
 
+  /**
+   * Retrieve the rectangle for the offsetX properties, which
+   * are coordinates relative to the returned aOffsetParent.
+   *
+   * @param aRect offset rectangle
+   * @param aOffsetParent offset parent
+   */
+  virtual void GetOffsetRect(nsRect& aRect, nsIContent** aOffsetParent);
+
+  nsIFrame* GetStyledFrame();
+
 public:
   // Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
   // otherwise nsXULElement::nsXULSlots doesn't compile.
   /**
    * There are a set of DOM- and scripting-specific instance variables
    * that may only be instantiated when a content object is accessed
    * through the DOM. Rather than burn actual slots in the content
    * objects for each of these instance variables, we put them off
@@ -1122,11 +1137,29 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS(nsNSElementTearoff)
 
   nsNSElementTearoff(nsGenericElement *aContent) : mContent(aContent)
   {
   }
   
 private:
   nsRefPtr<nsGenericElement> mContent;
+
+  /**
+   * Get this element's client area rect in app units.
+   * @return the frame's client area
+   */
+  nsRect GetClientAreaRect();
+
+private:
+
+  /**
+   * Get the element's styled frame (the primary frame or, for tables, the inner
+   * table frame) and closest scrollable view.
+   * @note This method flushes pending notifications (Flush_Layout).
+   * @param aScrollableView the scrollable view [OUT]
+   * @param aFrame (optional) the frame [OUT]
+   */
+  void GetScrollInfo(nsIScrollableView **aScrollableView,
+                     nsIFrame **aFrame = nsnull);
 };
 
 #endif /* nsGenericElement_h___ */
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -372,17 +372,16 @@ GK_ATOM(formatNumber, "format-number")
 GK_ATOM(frame, "frame")
 GK_ATOM(frameborder, "frameborder")
 GK_ATOM(frameset, "frameset")
 GK_ATOM(from, "from")
 GK_ATOM(functionAvailable, "function-available")
 GK_ATOM(generateId, "generate-id")
 GK_ATOM(getter, "getter")
 GK_ATOM(grid, "grid")
-GK_ATOM(gripper, "gripper")
 GK_ATOM(grippy, "grippy")
 GK_ATOM(group, "group")
 GK_ATOM(groupingSeparator, "grouping-separator")
 GK_ATOM(groupingSize, "grouping-size")
 GK_ATOM(grow, "grow")
 GK_ATOM(gutter, "gutter")
 GK_ATOM(h1, "h1")
 GK_ATOM(h2, "h2")
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1663,22 +1663,36 @@ nsresult
 nsObjectLoadingContent::TryInstantiate(const nsACString& aMIMEType,
                                        nsIURI* aURI)
 {
   nsIObjectFrame* frame = GetExistingFrame(eFlushContent);
   if (!frame) {
     LOG(("OBJLC [%p]: No frame yet\n", this));
     return NS_OK; // Not a failure to have no frame
   }
-  nsIFrame* iframe;
-  CallQueryInterface(frame, &iframe);
-  if (iframe->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
-    LOG(("OBJLC [%p]: Frame hasn't been reflown yet\n", this));
-    return NS_OK; // Not a failure to have no frame
+
+  nsCOMPtr<nsIPluginInstance> instance;
+  nsresult rv = frame->GetPluginInstance(*getter_AddRefs(instance));
+
+  if (!instance) {
+    // The frame has no plugin instance yet. If the frame hasn't been
+    // reflown yet, do nothing as once the reflow happens we'll end up
+    // instantiating the plugin with the correct size n' all (which
+    // isn't known until we've done the first reflow). But if the
+    // frame does have a plugin instance already, be sure to
+    // re-instantiate the plugin as its source or whatnot might have
+    // chanced since it was instantiated.
+    nsIFrame* iframe;
+    CallQueryInterface(frame, &iframe);
+    if (iframe->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
+      LOG(("OBJLC [%p]: Frame hasn't been reflown yet\n", this));
+      return NS_OK; // Not a failure to have no frame
+    }
   }
+
   return Instantiate(frame, aMIMEType, aURI);
 }
 
 nsresult
 nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
                                     const nsACString& aMIMEType,
                                     nsIURI* aURI)
 {
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -45,17 +45,16 @@
 #include "nsIURI.h"
 #include "nsILoadGroup.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsIUploadChannel.h"
 #include "nsIDOMSerializer.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
-#include "nsIEventListenerManager.h"
 #include "nsGUIEvent.h"
 #include "nsIPrivateDOMEvent.h"
 #include "prprf.h"
 #include "nsIDOMEventListener.h"
 #include "nsIJSContextStack.h"
 #include "nsJSEnvironment.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsWeakPtr.h"
@@ -89,16 +88,18 @@
 #include "nsIMultiPartChannel.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIStorageStream.h"
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 
 #define LOAD_STR "load"
 #define ERROR_STR "error"
+#define ABORT_STR "abort"
+#define LOADSTART_STR "loadstart"
 #define PROGRESS_STR "progress"
 #define UPLOADPROGRESS_STR "uploadprogress"
 #define READYSTATE_STR "readystatechange"
 
 // CIDs
 
 // State
 #define XML_HTTP_REQUEST_UNINITIALIZED  (1 << 0)  // 0
@@ -128,16 +129,39 @@
    XML_HTTP_REQUEST_INTERACTIVE |           \
    XML_HTTP_REQUEST_COMPLETED |             \
    XML_HTTP_REQUEST_SENT |                  \
    XML_HTTP_REQUEST_STOPPED)
 
 #define NS_BADCERTHANDLER_CONTRACTID \
   "@mozilla.org/content/xmlhttprequest-bad-cert-handler;1"
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventListenerWrapper)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
+NS_INTERFACE_MAP_END_AGGREGATED(mListener)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventListenerWrapper)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventListenerWrapper)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventListenerWrapper)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListener)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEventListenerWrapper)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListener)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMETHODIMP
+nsDOMEventListenerWrapper::HandleEvent(nsIDOMEvent* aEvent)
+{
+  return mListener->HandleEvent(aEvent);
+}
+
 // This helper function adds the given load flags to the request's existing
 // load flags.
 static void AddLoadFlags(nsIRequest *request, nsLoadFlags newFlags)
 {
   nsLoadFlags flags;
   request->GetLoadFlags(&flags);
   flags |= newFlags;
   request->SetLoadFlags(flags);
@@ -265,39 +289,344 @@ GetDocumentFromScriptContext(nsIScriptCo
     if (domdoc) {
       CallQueryInterface(domdoc, &doc);
     }
   }
   return doc;
 }
 
 /////////////////////////////////////////////
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXHREventTarget)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXHREventTarget)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnAbortListener)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadStartListener)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnProgressListener)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXHREventTarget)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnAbortListener)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadStartListener)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnProgressListener)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXHREventTarget)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequestEventTarget)
+  NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
+  NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXHREventTarget,
+                                          nsIXMLHttpRequestEventTarget)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXHREventTarget,
+                                           nsIXMLHttpRequestEventTarget)
+
+NS_IMETHODIMP
+nsXHREventTarget::AddEventListener(const nsAString& aType,
+                                   nsIDOMEventListener* aListener,
+                                   PRBool aUseCapture)
+{
+  nsCOMPtr<nsIScriptContext> context;
+  GetContextForEventHandlers(getter_AddRefs(context));
+  nsCOMPtr<nsIDocument> doc = GetDocumentFromScriptContext(context);
+  PRBool wantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
+  return AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::RemoveEventListener(const nsAString& aType,
+                                      nsIDOMEventListener* aListener,
+                                      PRBool aUseCapture)
+{
+  nsCOMPtr<nsIEventListenerManager> elm;
+  GetListenerManager(PR_FALSE, getter_AddRefs(elm));
+  if (elm) {
+    PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
+    elm->RemoveEventListenerByType(aListener, aType, flags, nsnull);
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::AddEventListener(const nsAString& aType,
+                                   nsIDOMEventListener *aListener,
+                                   PRBool aUseCapture,
+                                   PRBool aWantsUntrusted)
+{
+  nsCOMPtr<nsIEventListenerManager> elm;
+  GetListenerManager(PR_TRUE, getter_AddRefs(elm));
+  NS_ENSURE_STATE(elm);
+  PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
+  if (aWantsUntrusted) {
+    flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
+  }
+  return elm->AddEventListenerByType(aListener, aType, flags, nsnull);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::GetScriptTypeID(PRUint32 *aLang)
+{
+  *aLang = mLang;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::SetScriptTypeID(PRUint32 aLang)
+{
+  mLang = aLang;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::DispatchEvent(nsIDOMEvent* aEvent, PRBool* aRetVal)
+{
+  nsEventStatus status = nsEventStatus_eIgnore;
+  nsresult rv =
+    nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMEventTarget*>(this),
+                                        nsnull, aEvent, nsnull, &status);
+
+  *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
+  return rv;
+}
+
+nsresult
+nsXHREventTarget::RemoveAddEventListener(const nsAString& aType,
+                                         nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
+                                         nsIDOMEventListener* aNew)
+{
+  if (aCurrent) {
+    RemoveEventListener(aType, aCurrent, PR_FALSE);
+    aCurrent = nsnull;
+  }
+  if (aNew) {
+    aCurrent = new nsDOMEventListenerWrapper(aNew);
+    NS_ENSURE_TRUE(aCurrent, NS_ERROR_OUT_OF_MEMORY);
+    AddEventListener(aType, aCurrent, PR_FALSE);
+  }
+  return NS_OK;
+}
+
+nsresult
+nsXHREventTarget::GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
+                                        nsIDOMEventListener** aListener)
+{
+  NS_ENSURE_ARG_POINTER(aListener);
+  if (aWrapper) {
+    NS_ADDREF(*aListener = aWrapper->GetInner());
+  } else {
+    *aListener = nsnull;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::GetOnload(nsIDOMEventListener** aOnLoad)
+{
+  return GetInnerEventListener(mOnLoadListener, aOnLoad);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::SetOnload(nsIDOMEventListener* aOnLoad)
+{
+  return RemoveAddEventListener(NS_LITERAL_STRING(LOAD_STR),
+                                mOnLoadListener, aOnLoad);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::GetOnerror(nsIDOMEventListener** aOnerror)
+{
+  return GetInnerEventListener(mOnErrorListener, aOnerror);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::SetOnerror(nsIDOMEventListener* aOnerror)
+{
+  return RemoveAddEventListener(NS_LITERAL_STRING(ERROR_STR),
+                                mOnErrorListener, aOnerror);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::GetOnabort(nsIDOMEventListener** aOnabort)
+{
+  return GetInnerEventListener(mOnAbortListener, aOnabort);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::SetOnabort(nsIDOMEventListener* aOnabort)
+{
+  return RemoveAddEventListener(NS_LITERAL_STRING(ABORT_STR),
+                                mOnAbortListener, aOnabort);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::GetOnloadstart(nsIDOMEventListener** aOnloadstart)
+{
+  return GetInnerEventListener(mOnLoadStartListener, aOnloadstart);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::SetOnloadstart(nsIDOMEventListener* aOnloadstart)
+{
+  return RemoveAddEventListener(NS_LITERAL_STRING(LOADSTART_STR),
+                                mOnLoadStartListener, aOnloadstart);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::GetOnprogress(nsIDOMEventListener** aOnprogress)
+{
+  return GetInnerEventListener(mOnProgressListener, aOnprogress);
+}
+
+NS_IMETHODIMP
+nsXHREventTarget::SetOnprogress(nsIDOMEventListener* aOnprogress)
+{
+  return RemoveAddEventListener(NS_LITERAL_STRING(PROGRESS_STR),
+                                mOnProgressListener, aOnprogress);
+}
+
+nsresult
+nsXHREventTarget::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+{
+  aVisitor.mCanHandle = PR_TRUE;
+  aVisitor.mParentTarget = nsnull;
+  return NS_OK;
+}
+
+nsresult
+nsXHREventTarget::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
+{
+  return NS_OK;
+}
+
+nsresult
+nsXHREventTarget::DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
+                                   nsPresContext* aPresContext,
+                                   nsEventStatus* aEventStatus)
+{
+  return
+    nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMEventTarget*>(this),
+                                        aEvent, aDOMEvent, aPresContext,
+                                        aEventStatus);
+}
+
+nsresult
+nsXHREventTarget::GetListenerManager(PRBool aCreateIfNotFound,
+                                     nsIEventListenerManager** aResult)
+{
+  if (!mListenerManager) {
+    if (!aCreateIfNotFound) {
+      *aResult = nsnull;
+      return NS_OK;
+    }
+    nsresult rv = NS_NewEventListenerManager(getter_AddRefs(mListenerManager));
+    NS_ENSURE_SUCCESS(rv, rv);
+    mListenerManager->SetListenerTarget(static_cast<nsPIDOMEventTarget*>(this));
+  }
+
+  NS_ADDREF(*aResult = mListenerManager);
+  return NS_OK;
+}
+
+nsresult
+nsXHREventTarget::AddEventListenerByIID(nsIDOMEventListener *aListener,
+                                        const nsIID& aIID)
+{
+  nsCOMPtr<nsIEventListenerManager> elm;
+  GetListenerManager(PR_TRUE, getter_AddRefs(elm));
+  if (elm) {
+    elm->AddEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
+  }
+  return NS_OK;
+}
+
+nsresult
+nsXHREventTarget::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
+                                           const nsIID& aIID)
+{
+  nsCOMPtr<nsIEventListenerManager> elm;
+  GetListenerManager(PR_FALSE, getter_AddRefs(elm));
+  if (elm) {
+    return elm->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
+  }
+  return NS_OK;
+}
+
+nsresult
+nsXHREventTarget::GetSystemEventGroup(nsIDOMEventGroup** aGroup)
+{
+  nsCOMPtr<nsIEventListenerManager> elm;
+  nsresult rv = GetListenerManager(PR_TRUE, getter_AddRefs(elm));
+  if (elm) {
+    return elm->GetSystemEventGroupLM(aGroup);
+  }
+  return rv;
+}
+
+/////////////////////////////////////////////
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestUpload)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequestUpload)
+  NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestUpload)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLHttpRequestUpload)
+NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
+
+NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
+NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequestUpload, nsXHREventTarget)
+
+nsresult
+nsXMLHttpRequestUpload::GetContextForEventHandlers(nsIScriptContext** aContext)
+{
+  return mOwner->GetContextForEventHandlers(aContext);
+}
+
+/////////////////////////////////////////////
 //
 //
 /////////////////////////////////////////////
 
 nsXMLHttpRequest::nsXMLHttpRequest()
-  : mState(XML_HTTP_REQUEST_UNINITIALIZED)
+  : mState(XML_HTTP_REQUEST_UNINITIALIZED), mUploadTransferred(0),
+    mUploadTotal(0), mUploadComplete(PR_TRUE), mErrorLoad(PR_FALSE)
 {
   nsLayoutStatics::AddRef();
 }
 
 nsXMLHttpRequest::~nsXMLHttpRequest()
 {
+  if (mListenerManager) {
+    mListenerManager->Disconnect();
+  }
+
   if (mState & (XML_HTTP_REQUEST_STOPPED |
                 XML_HTTP_REQUEST_SENT |
                 XML_HTTP_REQUEST_INTERACTIVE)) {
     Abort();
   }
 
   NS_ABORT_IF_FALSE(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
-  // Needed to free the listener arrays.
-  ClearEventListeners();
   nsLayoutStatics::Release();
 }
 
 /**
  * This Init method is called from the factory constructor.
  */
 nsresult
 nsXMLHttpRequest::Init()
@@ -385,258 +714,111 @@ nsXMLHttpRequest::Initialize(nsISupports
   NS_ENSURE_STATE(sgo);
   mScriptContext = sgo->GetContext();
   NS_ENSURE_STATE(mScriptContext);
   return NS_OK; 
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequest)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLHttpRequest,
+                                                  nsXHREventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReadRequest)
 
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mLoadEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mErrorEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mProgressEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mUploadProgressEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mReadystatechangeEventListeners)
-
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnLoadListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnErrorListener)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnProgressListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressEventSink)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner)
+
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mUpload,
+                                                       nsIXMLHttpRequestUpload)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequest)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXMLHttpRequest,
+                                                nsXHREventTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
 
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mLoadEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mErrorEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mProgressEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mUploadProgressEventListeners)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mReadystatechangeEventListeners)
-
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptContext)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnLoadListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnProgressListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressEventSink)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner)
+
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUpload)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 // QueryInterface implementation for nsXMLHttpRequest
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequest)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequest)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest)
+  NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestUploadGetter)
   NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLHttpRequest)
-NS_INTERFACE_MAP_END
-
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest)
-
-
-/* void addEventListener (in string type, in nsIDOMEventListener
-   listener); */
-NS_IMETHODIMP
-nsXMLHttpRequest::AddEventListener(const nsAString& type,
-                                   nsIDOMEventListener *listener,
-                                   PRBool useCapture)
-{
-  NS_ENSURE_ARG(listener);
-
-  nsCOMArray<nsIDOMEventListener> *array;
-
-#define IMPL_ADD_LISTENER(_type, _member)    \
-  if (type.EqualsLiteral(_type)) {           \
-    array = &(_member);                      \
-  } else
-
-  IMPL_ADD_LISTENER(LOAD_STR, mLoadEventListeners)
-  IMPL_ADD_LISTENER(ERROR_STR, mErrorEventListeners)
-  IMPL_ADD_LISTENER(PROGRESS_STR, mProgressEventListeners)
-  IMPL_ADD_LISTENER(UPLOADPROGRESS_STR, mUploadProgressEventListeners)
-  IMPL_ADD_LISTENER(READYSTATE_STR, mReadystatechangeEventListeners)
-  {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  array->AppendObject(listener);
-
-#undef IMPL_ADD_LISTENER
-  
-  return NS_OK;
-}
-
-/* void removeEventListener (in string type, in nsIDOMEventListener
-   listener); */
-NS_IMETHODIMP
-nsXMLHttpRequest::RemoveEventListener(const nsAString & type,
-                                      nsIDOMEventListener *listener,
-                                      PRBool useCapture)
-{
-  NS_ENSURE_ARG(listener);
-
-  nsCOMArray<nsIDOMEventListener> *array;
-#define IMPL_REMOVE_LISTENER(_type, _member)  \
-  if (type.EqualsLiteral(_type)) {            \
-    array = &(_member);                       \
-  } else
-
-  IMPL_REMOVE_LISTENER(LOAD_STR, mLoadEventListeners)
-  IMPL_REMOVE_LISTENER(ERROR_STR, mErrorEventListeners)
-  IMPL_REMOVE_LISTENER(PROGRESS_STR, mProgressEventListeners)
-  IMPL_REMOVE_LISTENER(UPLOADPROGRESS_STR, mUploadProgressEventListeners)
-  IMPL_REMOVE_LISTENER(READYSTATE_STR, mReadystatechangeEventListeners)
-  {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  // Allow a caller to remove O(N^2) behavior by removing end-to-start.
-  for (PRUint32 i = array->Count() - 1; i != PRUint32(-1); --i) {
-    if (array->ObjectAt(i) == listener) {
-      array->RemoveObjectAt(i);
-      break;
-    }
-  }
-
-  return NS_OK;
-}
-
-/* boolean dispatchEvent (in nsIDOMEvent evt); */
-NS_IMETHODIMP
-nsXMLHttpRequest::DispatchEvent(nsIDOMEvent *evt, PRBool *_retval)
-{
-  // Ignored
-
-  return NS_OK;
-}
-
-/* attribute nsIDOMEventListener onreadystatechange; */
+NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
+
+NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequest, nsXHREventTarget)
+NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequest, nsXHREventTarget)
+
 NS_IMETHODIMP
 nsXMLHttpRequest::GetOnreadystatechange(nsIDOMEventListener * *aOnreadystatechange)
 {
-  NS_ENSURE_ARG_POINTER(aOnreadystatechange);
-
-  NS_IF_ADDREF(*aOnreadystatechange = mOnReadystatechangeListener);
-
-  return NS_OK;
+  return
+    nsXHREventTarget::GetInnerEventListener(mOnReadystatechangeListener,
+                                            aOnreadystatechange);
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnreadystatechange(nsIDOMEventListener * aOnreadystatechange)
 {
-  mOnReadystatechangeListener = aOnreadystatechange;
-  return NS_OK;
-}
-
-
-/* attribute nsIDOMEventListener onload; */
-NS_IMETHODIMP
-nsXMLHttpRequest::GetOnload(nsIDOMEventListener * *aOnLoad)
-{
-  NS_ENSURE_ARG_POINTER(aOnLoad);
-
-  NS_IF_ADDREF(*aOnLoad = mOnLoadListener);
-
-  return NS_OK;
+  return
+    nsXHREventTarget::RemoveAddEventListener(NS_LITERAL_STRING(READYSTATE_STR),
+                                             mOnReadystatechangeListener,
+                                             aOnreadystatechange);
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SetOnload(nsIDOMEventListener * aOnLoad)
-{
-  mOnLoadListener = aOnLoad;
-  return NS_OK;
-}
-
-/* attribute nsIDOMEventListener onerror; */
-NS_IMETHODIMP
-nsXMLHttpRequest::GetOnerror(nsIDOMEventListener * *aOnerror)
-{
-  NS_ENSURE_ARG_POINTER(aOnerror);
-
-  NS_IF_ADDREF(*aOnerror = mOnErrorListener);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXMLHttpRequest::SetOnerror(nsIDOMEventListener * aOnerror)
-{
-  mOnErrorListener = aOnerror;
-  return NS_OK;
-}
-
-/* attribute nsIDOMEventListener onprogress; */
-NS_IMETHODIMP
-nsXMLHttpRequest::GetOnprogress(nsIDOMEventListener * *aOnprogress)
-{
-  NS_ENSURE_ARG_POINTER(aOnprogress);  
-
-  NS_IF_ADDREF(*aOnprogress = mOnProgressListener);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXMLHttpRequest::SetOnprogress(nsIDOMEventListener * aOnprogress)
-{
-  mOnProgressListener = aOnprogress;
-  return NS_OK;
-}
-
-/* attribute nsIDOMEventListener onuploadprogress; */
-NS_IMETHODIMP
 nsXMLHttpRequest::GetOnuploadprogress(nsIDOMEventListener * *aOnuploadprogress)
 {
-  NS_ENSURE_ARG_POINTER(aOnuploadprogress);  
-
-  NS_IF_ADDREF(*aOnuploadprogress = mOnUploadProgressListener);
-
-  return NS_OK;
+  return
+    nsXHREventTarget::GetInnerEventListener(mOnUploadProgressListener,
+                                            aOnuploadprogress);
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnuploadprogress(nsIDOMEventListener * aOnuploadprogress)
 {
-  mOnUploadProgressListener = aOnuploadprogress;
-  return NS_OK;
+  return
+    nsXHREventTarget::RemoveAddEventListener(NS_LITERAL_STRING(UPLOADPROGRESS_STR),
+                                             mOnUploadProgressListener,
+                                             aOnuploadprogress);
 }
 
 /* readonly attribute nsIChannel channel; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
 {
   NS_ENSURE_ARG_POINTER(aChannel);
   NS_IF_ADDREF(*aChannel = mChannel);
@@ -857,17 +1039,27 @@ nsXMLHttpRequest::Abort()
   }
   mDocument = nsnull;
   mResponseBody.Truncate();
   mState |= XML_HTTP_REQUEST_ABORTED;
 
   if (!(mState & (XML_HTTP_REQUEST_UNINITIALIZED |
                   XML_HTTP_REQUEST_OPENED |
                   XML_HTTP_REQUEST_COMPLETED))) {
-    ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE, PR_TRUE);
+    ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE);
+  }
+
+  if (!(mState & XML_HTTP_REQUEST_SYNCLOOPING)) {
+    NS_NAMED_LITERAL_STRING(abortStr, ABORT_STR);
+    DispatchProgressEvent(this, abortStr, PR_FALSE, mResponseBody.Length(), 0);
+    if (mUpload && !mUploadComplete) {
+      mUploadComplete = PR_TRUE;
+      DispatchProgressEvent(mUpload, abortStr, PR_TRUE, mUploadTransferred,
+                            mUploadTotal);
+    }
   }
 
   // The ChangeState call above calls onreadystatechange handlers which
   // if they load a new url will cause nsXMLHttpRequest::OpenRequest to clear
   // the abort state bit. If this occurs we're not uninitialized (bug 361773).
   if (mState & XML_HTTP_REQUEST_ABORTED) {
     ChangeState(XML_HTTP_REQUEST_UNINITIALIZED, PR_FALSE);  // IE seems to do it
   }
@@ -954,121 +1146,83 @@ nsXMLHttpRequest::GetBaseURI()
   if (!doc) {
     return nsnull;
   }
 
   return doc->GetBaseURI();
 }
 
 nsresult
-nsXMLHttpRequest::CreateEvent(const nsAString& aType, nsIDOMEvent** aDOMEvent)
+nsXMLHttpRequest::CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent)
 {
   nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
                                                NS_LITERAL_STRING("Events"),
                                                aDOMEvent);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsCOMPtr<nsIPrivateDOMEvent> privevent(do_QueryInterface(*aDOMEvent));
   if (!privevent) {
     NS_IF_RELEASE(*aDOMEvent);
     return NS_ERROR_FAILURE;
   }
 
-  if (!aType.IsEmpty()) {
-    (*aDOMEvent)->InitEvent(aType, PR_FALSE, PR_FALSE);
-  }
-  
-  privevent->SetTarget(this);
-  privevent->SetCurrentTarget(this);
-  privevent->SetOriginalTarget(this);
-
-  // We assume anyone who managed to call CreateEvent is trusted
+  (*aDOMEvent)->InitEvent(NS_LITERAL_STRING(READYSTATE_STR),
+                          PR_FALSE, PR_FALSE);
+
+  // We assume anyone who managed to call CreateReadystatechangeEvent is trusted
   privevent->SetTrusted(PR_TRUE);
 
   return NS_OK;
 }
 
 void
-nsXMLHttpRequest::CopyEventListeners(nsCOMPtr<nsIDOMEventListener>& aListener,
-                                     const nsCOMArray<nsIDOMEventListener>& aListenerArray,
-                                     nsCOMArray<nsIDOMEventListener>& aCopy)
+nsXMLHttpRequest::DispatchProgressEvent(nsPIDOMEventTarget* aTarget,
+                                        const nsAString& aType,
+                                        PRBool aUseLSEventWrapper,
+                                        PRBool aLengthComputable,
+                                        PRUint64 aLoaded, PRUint64 aTotal,
+                                        PRUint64 aPosition, PRUint64 aTotalSize)
 {
-  NS_PRECONDITION(aCopy.Count() == 0, "aCopy should start off empty");
-  if (aListener)
-    aCopy.AppendObject(aListener);
-
-  aCopy.AppendObjects(aListenerArray);
-}
-
-void
-nsXMLHttpRequest::NotifyEventListeners(const nsCOMArray<nsIDOMEventListener>& aListeners,
-                                       nsIDOMEvent* aEvent)
-{
-  // XXXbz wouldn't it be easier to just have an actual nsEventListenerManager
-  // to work with or something?  I feel like we're duplicating code here...
-  if (!aEvent)
+  if (aType.IsEmpty()) {
     return;
-
-  nsCOMPtr<nsIJSContextStack> stack;
-  JSContext *cx = nsnull;
-
-  if (NS_FAILED(CheckInnerWindowCorrectness())) {
+  }
+
+  nsCOMPtr<nsIDOMEvent> event;
+  nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
+                                               NS_LITERAL_STRING("ProgressEvent"),
+                                               getter_AddRefs(event));
+  if (NS_FAILED(rv)) {
     return;
   }
 
-  if (mScriptContext) {
-    stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
-
-    if (stack) {
-      cx = (JSContext *)mScriptContext->GetNativeContext();
-
-      if (cx) {
-        stack->Push(cx);
-      }
-    }
+  nsCOMPtr<nsIPrivateDOMEvent> privevent(do_QueryInterface(event));
+  if (!privevent) {
+    return;
   }
-
-  PRInt32 count = aListeners.Count();
-  for (PRInt32 index = 0; index < count; ++index) {
-    nsIDOMEventListener* listener = aListeners[index];
-    
-    if (listener) {
-      listener->HandleEvent(aEvent);
-    }
-  }
-
-  if (cx) {
-    stack->Pop(&cx);
+  privevent->SetTrusted(PR_TRUE);
+
+  nsCOMPtr<nsIDOMProgressEvent> progress = do_QueryInterface(event);
+  if (!progress) {
+    return;
   }
-}
-
-void
-nsXMLHttpRequest::ClearEventListeners()
-{
-  // This isn't *really* needed anymore now that we use a cycle
-  // collector, but we may as well keep it for safety (against leaks)
-  // and compatibility, and also for the code to clear the first
-  // listener arrays (called from the destructor).
-  // XXXbz per spec we shouldn't be doing this, actually.  And we
-  // don't need to clear the arrays from the destructor now that we're
-  // using nsCOMArray.
-
-  mLoadEventListeners.Clear();
-  mErrorEventListeners.Clear();
-  mProgressEventListeners.Clear();
-  mUploadProgressEventListeners.Clear();
-  mReadystatechangeEventListeners.Clear();
-
-  mOnLoadListener = nsnull;
-  mOnErrorListener = nsnull;
-  mOnProgressListener = nsnull;
-  mOnUploadProgressListener = nsnull;
-  mOnReadystatechangeListener = nsnull;
+
+  progress->InitProgressEvent(aType, PR_FALSE, PR_FALSE, aLengthComputable,
+                              aLoaded, (aTotal == LL_MAXUINT) ? 0 : aTotal);
+
+  if (aUseLSEventWrapper) {
+    nsCOMPtr<nsIDOMProgressEvent> xhrprogressEvent =
+      new nsXMLHttpProgressEvent(progress, aPosition, aTotalSize);
+    if (!xhrprogressEvent) {
+      return;
+    }
+    event = xhrprogressEvent;
+  }
+  aTarget->DispatchDOMEvent(nsnull, event, nsnull, nsnull);
 }
 
 already_AddRefed<nsIHttpChannel>
 nsXMLHttpRequest::GetCurrentHttpChannel()
 {
   nsIHttpChannel *httpChannel = nsnull;
 
   if (mReadRequest) {
@@ -1206,20 +1360,19 @@ nsXMLHttpRequest::OpenRequest(const nsAC
   nsCOMPtr<nsILoadGroup> loadGroup;
   GetLoadGroup(getter_AddRefs(loadGroup));
 
   // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
   // in turn keeps STOP button from becoming active.  If the consumer passed in
   // a progress event handler we must load with nsIRequest::LOAD_NORMAL or
   // necko won't generate any progress notifications
   nsLoadFlags loadFlags;
-  if (mOnProgressListener ||
-      mOnUploadProgressListener ||
-      mProgressEventListeners.Count() != 0 ||
-      mUploadProgressEventListeners.Count() != 0) {
+  if (HasListenersFor(NS_LITERAL_STRING(PROGRESS_STR)) ||
+      HasListenersFor(NS_LITERAL_STRING(UPLOADPROGRESS_STR)) ||
+      (mUpload && mUpload->HasListenersFor(NS_LITERAL_STRING(PROGRESS_STR)))) {
     loadFlags = nsIRequest::LOAD_NORMAL;
   } else {
     loadFlags = nsIRequest::LOAD_BACKGROUND;
   }
   rv = NS_NewChannel(getter_AddRefs(mChannel), uri, nsnull, loadGroup, nsnull,
                      loadFlags);
   if (NS_FAILED(rv)) return rv;
 
@@ -1471,16 +1624,23 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
     rv = target->AddEventListenerByIID(static_cast<nsIDOMEventListener*>
                                                   (proxy),
                                        NS_GET_IID(nsIDOMLoadListener));
     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
   }
 
   nsresult status;
   request->GetStatus(&status);
+  mErrorLoad = mErrorLoad || NS_FAILED(status);
+
+  if (mUpload && !mUploadComplete && !mErrorLoad) {
+    mUploadComplete = PR_TRUE;
+    DispatchProgressEvent(mUpload, NS_LITERAL_STRING(LOAD_STR),
+                          PR_TRUE, mUploadTotal, mUploadTotal);
+  }
 
   PRBool parseBody = PR_TRUE;
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
   if (httpChannel) {
     nsCAutoString method;
     httpChannel->GetRequestMethod(method);
     parseBody = !method.EqualsLiteral("HEAD");
   }
@@ -1629,45 +1789,41 @@ nsXMLHttpRequest::RequestCompleted()
   // If we're uninitialized at this point, we encountered an error
   // earlier and listeners have already been notified. Also we do
   // not want to do this if we already completed.
   if (mState & (XML_HTTP_REQUEST_UNINITIALIZED |
                 XML_HTTP_REQUEST_COMPLETED)) {
     return NS_OK;
   }
 
-  // Grab hold of the event listeners we will need before we possibly clear
-  // them.
-  nsCOMArray<nsIDOMEventListener> loadEventListeners;
-  CopyEventListeners(mOnLoadListener, mLoadEventListeners, loadEventListeners);
-
-  // We need to create the event before nulling out mDocument
-  nsCOMPtr<nsIDOMEvent> domevent;
-  if (loadEventListeners.Count()) {
-    rv = CreateEvent(NS_LITERAL_STRING(LOAD_STR), getter_AddRefs(domevent));
-  }
-
   // We might have been sent non-XML data. If that was the case,
   // we should null out the document member. The idea in this
   // check here is that if there is no document element it is not
   // an XML document. We might need a fancier check...
   if (mDocument) {
     nsCOMPtr<nsIDOMElement> root;
     mDocument->GetDocumentElement(getter_AddRefs(root));
     if (!root) {
       mDocument = nsnull;
     }
   }
 
-  // Clear listeners here unless we're multipart
-  ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE,
-              !!(mState & XML_HTTP_REQUEST_GOT_FINAL_STOP));
-
-  if (NS_SUCCEEDED(rv) && domevent) {
-    NotifyEventListeners(loadEventListeners, domevent);
+  ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE);
+
+  PRUint32 responseLength = mResponseBody.Length();
+  NS_NAMED_LITERAL_STRING(errorStr, ERROR_STR);
+  NS_NAMED_LITERAL_STRING(loadStr, LOAD_STR);
+  DispatchProgressEvent(this,
+                        mErrorLoad ? errorStr : loadStr,
+                        !mErrorLoad,
+                        responseLength,
+                        mErrorLoad ? 0 : responseLength);
+  if (mErrorLoad && mUpload && !mUploadComplete) {
+    DispatchProgressEvent(mUpload, errorStr, PR_TRUE,
+                          mUploadTransferred, mUploadTotal);
   }
 
   if (!(mState & XML_HTTP_REQUEST_GOT_FINAL_STOP)) {
     // We're a multipart request, so we're not done. Reset to opened.
     ChangeState(XML_HTTP_REQUEST_OPENED);
   }
 
   nsJSContext::MaybeCC(PR_FALSE);
@@ -1744,16 +1900,21 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
     if (!IsSystemPrincipal(mPrincipal)) {
       nsCOMPtr<nsIURI> codebase;
       mPrincipal->GetURI(getter_AddRefs(codebase));
 
       httpChannel->SetReferrer(codebase);
     }
   }
 
+  mUploadTransferred = 0;
+  mUploadTotal = 0;
+  // By default we don't have any upload, so mark upload complete.
+  mUploadComplete = PR_TRUE;
+  mErrorLoad = PR_FALSE;
   if (aBody && httpChannel && !method.EqualsLiteral("GET")) {
     nsXPIDLString serial;
     nsCOMPtr<nsIInputStream> postDataStream;
     nsCAutoString charset(NS_LITERAL_CSTRING("UTF-8"));
 
     PRUint16 dataType;
     rv = aBody->GetDataType(&dataType);
     if (NS_FAILED(rv))
@@ -1885,16 +2046,18 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
                                      nsCaseInsensitiveCStringComparator())) {
           nsCAutoString newCharset("; charset=");
           newCharset.Append(charset);
           contentType.Replace(charsetStart, charsetEnd - charsetStart,
                               newCharset);
         }
       }
 
+      mUploadComplete = PR_FALSE;
+      postDataStream->Available(&mUploadTotal);
       rv = uploadChannel->SetUploadStream(postDataStream, contentType, -1);
       // Reset the method to its original value
       if (httpChannel) {
         httpChannel->SetRequestMethod(method);
       }
     }
   }
 
@@ -1963,16 +2126,23 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
   if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
     nsIThread *thread = NS_GetCurrentThread();
     while (mState & XML_HTTP_REQUEST_SYNCLOOPING) {
       if (!NS_ProcessNextEvent(thread)) {
         rv = NS_ERROR_UNEXPECTED;
         break;
       }
     }
+  } else {
+    DispatchProgressEvent(this, NS_LITERAL_STRING(LOADSTART_STR), PR_FALSE,
+                          0, 0);
+    if (mUpload && !mUploadComplete) {
+      DispatchProgressEvent(mUpload, NS_LITERAL_STRING(LOADSTART_STR), PR_TRUE,
+                            0, mUploadTotal);
+    }
   }
 
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
   return rv;
 }
@@ -2175,76 +2345,52 @@ nsXMLHttpRequest::Abort(nsIDOMEvent* aEv
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
   return NS_OK;
 }
 
 nsresult
 nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
 {
-  nsCOMArray<nsIDOMEventListener> errorEventListeners;
-  CopyEventListeners(mOnErrorListener, mErrorEventListeners,
-                     errorEventListeners);
-
-  // We need to create the event before nulling out mDocument
-  nsCOMPtr<nsIDOMEvent> event = aEvent;
-  if (!event && errorEventListeners.Count()) {
-    CreateEvent(NS_LITERAL_STRING(ERROR_STR), getter_AddRefs(event));
-  }
-
   mDocument = nsnull;
   ChangeState(XML_HTTP_REQUEST_COMPLETED);
 
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
-  ClearEventListeners();
-  
-  if (event) {
-    NotifyEventListeners(errorEventListeners, event);
+  DispatchProgressEvent(this, NS_LITERAL_STRING(ERROR_STR), PR_FALSE,
+                        mResponseBody.Length(), 0);
+  if (mUpload && !mUploadComplete) {
+    mUploadComplete = PR_TRUE;
+    DispatchProgressEvent(mUpload, NS_LITERAL_STRING(ERROR_STR), PR_TRUE,
+                          mUploadTransferred, mUploadTotal);
   }
 
   nsJSContext::MaybeCC(PR_FALSE);
   return NS_OK;
 }
 
 nsresult
-nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast,
-                              PRBool aClearEventListeners)
+nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast)
 {
   // If we are setting one of the mutually exclusive states,
   // unset those state bits first.
   if (aState & XML_HTTP_REQUEST_LOADSTATES) {
     mState &= ~XML_HTTP_REQUEST_LOADSTATES;
   }
   mState |= aState;
   nsresult rv = NS_OK;
 
-  // Grab private copies of the listeners we need
-  nsCOMArray<nsIDOMEventListener> readystatechangeEventListeners;
-
-  if (aBroadcast) {
-    CopyEventListeners(mOnReadystatechangeListener,
-                       mReadystatechangeEventListeners,
-                       readystatechangeEventListeners);
-  }
-
-  if (aClearEventListeners) {
-    ClearEventListeners();
-  }
-
   if ((mState & XML_HTTP_REQUEST_ASYNC) &&
       (aState & XML_HTTP_REQUEST_LOADSTATES) && // Broadcast load states only
-      aBroadcast &&
-      readystatechangeEventListeners.Count()) {
+      aBroadcast) {
     nsCOMPtr<nsIDOMEvent> event;
-    rv = CreateEvent(NS_LITERAL_STRING(READYSTATE_STR),
-                     getter_AddRefs(event));
+    rv = CreateReadystatechangeEvent(getter_AddRefs(event));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    NotifyEventListeners(readystatechangeEventListeners, event);
+    DispatchDOMEvent(nsnull, event, nsnull, nsnull);
   }
 
   return rv;
 }
 
 /////////////////////////////////////////////////////
 // nsIChannelEventSink methods:
 //
@@ -2263,63 +2409,72 @@ nsXMLHttpRequest::OnChannelRedirect(nsIC
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIURI> newURI;
     rv = aNewChannel->GetURI(getter_AddRefs(newURI));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = nsContentUtils::GetSecurityManager()->
       CheckSameOriginURI(oldURI, newURI, PR_TRUE);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      mErrorLoad = PR_TRUE;
+      return rv;
+    }
   }
 
   if (mChannelEventSink) {
     rv =
       mChannelEventSink->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      mErrorLoad = PR_TRUE;
+      return rv;
+    }
   }
 
   mChannel = aNewChannel;
 
   return NS_OK;
 }
 
 /////////////////////////////////////////////////////
 // nsIProgressEventSink methods:
 //
 
 NS_IMETHODIMP
 nsXMLHttpRequest::OnProgress(nsIRequest *aRequest, nsISupports *aContext, PRUint64 aProgress, PRUint64 aProgressMax)
 {
   // We're uploading if our state is XML_HTTP_REQUEST_OPENED or
   // XML_HTTP_REQUEST_SENT
-  PRBool downloading =
-    !((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState);
-  nsCOMArray<nsIDOMEventListener> progressListeners;
-  if (downloading) {
-    CopyEventListeners(mOnProgressListener,
-                       mProgressEventListeners, progressListeners);
-  } else {
-    CopyEventListeners(mOnUploadProgressListener,
-                       mUploadProgressEventListeners, progressListeners);
+  PRBool upload = !!((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState);
+  PRUint64 loaded = aProgress;
+  PRUint64 total = aProgressMax;
+  // When uploading, OnProgress reports also headers in aProgress and aProgressMax.
+  // So, try to remove the headers, if possible.
+  PRBool lengthComputable = (aProgressMax != LL_MAXUINT);
+  if (upload) {
+   if (lengthComputable) {
+      PRUint32 headerSize = aProgressMax - mUploadTotal;
+      loaded -= headerSize;
+      total -= headerSize;
+    }
+    mUploadTransferred = loaded;
   }
-  
-  if (progressListeners.Count()) {
-    nsCOMPtr<nsIDOMEvent> event;
-    nsresult rv = CreateEvent(NS_LITERAL_STRING(PROGRESS_STR),
-                              getter_AddRefs(event));
-    NS_ENSURE_SUCCESS(rv, rv);
-    
-    nsXMLHttpProgressEvent * progressEvent =
-      new nsXMLHttpProgressEvent(event, aProgress, aProgressMax); 
-    if (!progressEvent)
-      return NS_ERROR_OUT_OF_MEMORY;
-
-    event = progressEvent;
-    NotifyEventListeners(progressListeners, event);
+
+  if (!mErrorLoad) {
+    NS_NAMED_LITERAL_STRING(progress, PROGRESS_STR);
+    NS_NAMED_LITERAL_STRING(uploadprogress, UPLOADPROGRESS_STR);
+    DispatchProgressEvent(this, upload ? uploadprogress : progress, PR_TRUE,
+                          lengthComputable, loaded, lengthComputable ? total : 0,
+                          aProgress, aProgressMax);
+
+    if (upload && mUpload) {
+      NS_WARN_IF_FALSE(mUploadTotal == PRUint32(total), "Wrong upload total?");
+      DispatchProgressEvent(mUpload, progress,  PR_TRUE, lengthComputable, loaded,
+                            lengthComputable ? total : 0, aProgress, aProgressMax);
+    }
   }
 
   if (mProgressEventSink) {
     mProgressEventSink->OnProgress(aRequest, aContext, aProgress,
                                    aProgressMax);
   }
 
   return NS_OK;
@@ -2397,50 +2552,84 @@ nsXMLHttpRequest::GetInterface(const nsI
     return wwatch->GetPrompt(window, aIID,
                              reinterpret_cast<void**>(aResult));
 
   }
 
   return QueryInterface(aIID, aResult);
 }
 
+nsresult
+nsXMLHttpRequest::GetContextForEventHandlers(nsIScriptContext** aContext)
+{
+  NS_IF_ADDREF(*aContext = mScriptContext);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLHttpRequest::GetUpload(nsIXMLHttpRequestUpload** aUpload)
+{
+  *aUpload = nsnull;
+  if (!mUpload) {
+    mUpload = new nsXMLHttpRequestUpload(this);
+    NS_ENSURE_TRUE(mUpload, NS_ERROR_OUT_OF_MEMORY);
+  }
+  NS_ADDREF(*aUpload = mUpload);
+  return NS_OK;
+}
 
 NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
 
 NS_IMETHODIMP nsXMLHttpRequest::
 nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
 {
     mHeaders.Append(header);
     mHeaders.Append(": ");
     mHeaders.Append(value);
     mHeaders.Append('\n');
     return NS_OK;
 }
 
 // DOM event class to handle progress notifications
-nsXMLHttpProgressEvent::nsXMLHttpProgressEvent(nsIDOMEvent * aInner, PRUint64 aCurrentProgress, PRUint64 aMaxProgress)
+nsXMLHttpProgressEvent::nsXMLHttpProgressEvent(nsIDOMProgressEvent* aInner,
+                                               PRUint64 aCurrentProgress,
+                                               PRUint64 aMaxProgress)
 {
-  mInner = aInner; 
+  mInner = static_cast<nsDOMProgressEvent*>(aInner);
   mCurProgress = aCurrentProgress;
   mMaxProgress = aMaxProgress;
 }
 
 nsXMLHttpProgressEvent::~nsXMLHttpProgressEvent()
 {}
 
-// QueryInterface implementation for nsXMLHttpRequest
-NS_INTERFACE_MAP_BEGIN(nsXMLHttpProgressEvent)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLSProgressEvent)
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpProgressEvent)
+
+// QueryInterface implementation for nsXMLHttpProgressEvent
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpProgressEvent)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProgressEvent)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEvent, nsIDOMProgressEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNSEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIPrivateDOMEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMProgressEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMLSProgressEvent)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLHttpProgressEvent)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_ADDREF(nsXMLHttpProgressEvent)
-NS_IMPL_RELEASE(nsXMLHttpProgressEvent)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHttpProgressEvent)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpProgressEvent)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpProgressEvent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInner);
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpProgressEvent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mInner,
+                                                       nsIDOMProgressEvent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMETHODIMP nsXMLHttpProgressEvent::GetInput(nsIDOMLSInput * *aInput)
 {
   *aInput = nsnull;
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP nsXMLHttpProgressEvent::GetPosition(PRUint32 *aPosition)
@@ -2451,8 +2640,9 @@ NS_IMETHODIMP nsXMLHttpProgressEvent::Ge
 }
 
 NS_IMETHODIMP nsXMLHttpProgressEvent::GetTotalSize(PRUint32 *aTotalSize)
 {
   // XXX can we change the iface?
   LL_L2UI(*aTotalSize, mMaxProgress);
   return NS_OK;
 }
+
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -39,16 +39,17 @@
 #define nsXMLHttpRequest_h__
 
 #include "nsIXMLHttpRequest.h"
 #include "nsISupportsUtils.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIDOMLoadListener.h"
 #include "nsIDOMEventTarget.h"
+#include "nsIDOMNSEventTarget.h"
 #include "nsIDOMDocument.h"
 #include "nsIURI.h"
 #include "nsIHttpChannel.h"
 #include "nsIDocument.h"
 #include "nsIStreamListener.h"
 #include "nsWeakReference.h"
 #include "jsapi.h"
 #include "nsIScriptContext.h"
@@ -62,48 +63,139 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMLSProgressEvent.h"
 #include "nsClassHashtable.h"
 #include "nsHashKeys.h"
 #include "prclist.h"
 #include "prtime.h"
+#include "nsIEventListenerManager.h"
+#include "nsIDOMNSEvent.h"
+#include "nsIPrivateDOMEvent.h"
+#include "nsDOMProgressEvent.h"
 
 class nsILoadGroup;
 
-class nsXMLHttpRequest : public nsIXMLHttpRequest,
+class nsDOMEventListenerWrapper : public nsIDOMEventListener
+{
+public:
+  nsDOMEventListenerWrapper(nsIDOMEventListener* aListener)
+  : mListener(aListener) {}
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
+
+  NS_DECL_NSIDOMEVENTLISTENER
+
+  nsIDOMEventListener* GetInner() { return mListener; }
+protected:
+  nsCOMPtr<nsIDOMEventListener> mListener;
+};
+
+class nsXHREventTarget : public nsIXMLHttpRequestEventTarget,
+                         public nsPIDOMEventTarget,
+                         public nsIDOMNSEventTarget
+{
+public:
+  nsXHREventTarget() : mLang(nsIProgrammingLanguage::JAVASCRIPT) {}
+  virtual ~nsXHREventTarget() {}
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXHREventTarget,
+                                           nsIXMLHttpRequestEventTarget)
+  NS_DECL_NSIDOMNSEVENTTARGET
+  NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
+  NS_DECL_NSIDOMEVENTTARGET
+  // nsPIDOMEventTarget
+  virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
+  virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
+  virtual nsresult DispatchDOMEvent(nsEvent* aEvent, nsIDOMEvent* aDOMEvent,
+                                    nsPresContext* aPresContext,
+                                    nsEventStatus* aEventStatus);
+  virtual nsresult GetListenerManager(PRBool aCreateIfNotFound,
+                                      nsIEventListenerManager** aResult);
+  virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener,
+                                         const nsIID& aIID);
+  virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener,
+                                            const nsIID& aIID);
+  virtual nsresult GetSystemEventGroup(nsIDOMEventGroup** aGroup);
+  virtual nsresult GetContextForEventHandlers(nsIScriptContext** aContext) = 0;
+
+  PRBool HasListenersFor(const nsAString& aType)
+  {
+    return mListenerManager && mListenerManager->HasListenersFor(aType);
+  }
+  nsresult RemoveAddEventListener(const nsAString& aType,
+                                  nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
+                                  nsIDOMEventListener* aNew);
+
+  nsresult GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
+                                 nsIDOMEventListener** aListener);
+protected:
+  nsRefPtr<nsDOMEventListenerWrapper> mOnLoadListener;
+  nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
+  nsRefPtr<nsDOMEventListenerWrapper> mOnAbortListener;
+  nsRefPtr<nsDOMEventListenerWrapper> mOnLoadStartListener;
+  nsRefPtr<nsDOMEventListenerWrapper> mOnProgressListener;
+  nsCOMPtr<nsIEventListenerManager> mListenerManager;
+  PRUint32 mLang;
+};
+
+class nsXMLHttpRequestUpload : public nsXHREventTarget,
+                               public nsIXMLHttpRequestUpload
+{
+public:
+  nsXMLHttpRequestUpload(nsPIDOMEventTarget* aOwner) : mOwner(aOwner) {}
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequestUpload,
+                                           nsXHREventTarget)
+  NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
+  NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
+  NS_FORWARD_NSIDOMNSEVENTTARGET(nsXHREventTarget::)
+  NS_DECL_NSIXMLHTTPREQUESTUPLOAD
+  virtual nsresult GetContextForEventHandlers(nsIScriptContext** aContext);
+protected:
+  nsCOMPtr<nsPIDOMEventTarget> mOwner;
+};
+
+class nsXMLHttpRequest : public nsXHREventTarget,
+                         public nsIXMLHttpRequest,
                          public nsIJSXMLHttpRequest,
                          public nsIDOMLoadListener,
-                         public nsIDOMEventTarget,
                          public nsIStreamListener,
                          public nsIChannelEventSink,
                          public nsIProgressEventSink,
                          public nsIInterfaceRequestor,
                          public nsSupportsWeakReference,
-                         public nsIJSNativeInitializer
+                         public nsIJSNativeInitializer,
+                         public nsIXMLHttpRequestUploadGetter
 {
 public:
   nsXMLHttpRequest();
   virtual ~nsXMLHttpRequest();
 
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
 
   // nsIXMLHttpRequest
   NS_DECL_NSIXMLHTTPREQUEST
 
   // nsIJSXMLHttpRequest
-  NS_DECL_NSIJSXMLHTTPREQUEST
+  NS_IMETHOD GetOnuploadprogress(nsIDOMEventListener** aOnuploadprogress);
+  NS_IMETHOD SetOnuploadprogress(nsIDOMEventListener* aOnuploadprogress);
+  NS_IMETHOD GetOnreadystatechange(nsIDOMEventListener** aOnreadystatechange);
+  NS_IMETHOD SetOnreadystatechange(nsIDOMEventListener* aOnreadystatechange);
 
-  // nsIDOMEventTarget
-  NS_DECL_NSIDOMEVENTTARGET
+  NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
 
   // nsIDOMEventListener
   NS_DECL_NSIDOMEVENTLISTENER
 
+  // nsIXMLHttpRequestUploadGetter
+  NS_DECL_NSIXMLHTTPREQUESTUPLOADGETTER
+
   // nsIDOMLoadListener
   NS_IMETHOD Load(nsIDOMEvent* aEvent);
   NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
   NS_IMETHOD Unload(nsIDOMEvent* aEvent);
   NS_IMETHOD Abort(nsIDOMEvent* aEvent);
   NS_IMETHOD Error(nsIDOMEvent* aEvent);
 
   // nsIStreamListener
@@ -120,59 +212,75 @@ public:
 
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
                        PRUint32 argc, jsval* argv);
 
+  virtual nsresult GetContextForEventHandlers(nsIScriptContext** aContext);
+
+
+  // This creates a trusted readystatechange event, which is not cancelable and
+  // doesn't bubble.
+  static nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
+  // For backwards compatibility aPosition should contain the headers for upload
+  // and aTotalSize is LL_MAXUINT when unknown. Both those values are
+  // used by nsXMLHttpProgressEvent. Normal progress event should not use
+  // headers in aLoaded and aTotal is 0 when unknown.
+  static void DispatchProgressEvent(nsPIDOMEventTarget* aTarget,
+                                    const nsAString& aType,
+                                    // Whether to use nsXMLHttpProgressEvent,
+                                    // which implements LS Progress Event.
+                                    PRBool aUseLSEventWrapper,
+                                    PRBool aLengthComputable,
+                                    // For Progress Events
+                                    PRUint64 aLoaded, PRUint64 aTotal,
+                                    // For LS Progress Events
+                                    PRUint64 aPosition, PRUint64 aTotalSize);
+  static void DispatchProgressEvent(nsPIDOMEventTarget* aTarget,
+                                    const nsAString& aType,
+                                    PRBool aLengthComputable,
+                                    PRUint64 aLoaded, PRUint64 aTotal)
+  {
+    DispatchProgressEvent(aTarget, aType, PR_FALSE,
+                          aLengthComputable, aLoaded, aTotal,
+                          aLoaded, aLengthComputable ? aTotal : LL_MAXUINT);
+  }
+
   // This is called by the factory constructor.
   nsresult Init();
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXMLHttpRequest,
+                                           nsXHREventTarget)
 
 protected:
-
   nsresult DetectCharset(nsACString& aCharset);
   nsresult ConvertBodyToText(nsAString& aOutBuffer);
   static NS_METHOD StreamReaderFunc(nsIInputStream* in,
                 void* closure,
                 const char* fromRawSegment,
                 PRUint32 toOffset,
                 PRUint32 count,
                 PRUint32 *writeCount);
   // Change the state of the object with this. The broadcast argument
   // determines if the onreadystatechange listener should be called.
-  // If aClearEventListeners is true, ChangeState will take refs to
-  // any event listeners it needs and call ClearEventListeners before
-  // making any HandleEvent() calls that could change the listener
-  // values.
-  nsresult ChangeState(PRUint32 aState, PRBool aBroadcast = PR_TRUE,
-                       PRBool aClearEventListeners = PR_FALSE);
+  nsresult ChangeState(PRUint32 aState, PRBool aBroadcast = PR_TRUE);
   nsresult RequestCompleted();
   nsresult GetLoadGroup(nsILoadGroup **aLoadGroup);
   nsIURI *GetBaseURI();
 
-  // This creates a trusted event, which is not cancelable and doesn't
-  // bubble. Don't call this if we have no event listeners, since this may
-  // use our script context, which is not set in that case.
-  nsresult CreateEvent(const nsAString& aType, nsIDOMEvent** domevent);
+  nsresult RemoveAddEventListener(const nsAString& aType,
+                                  nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
+                                  nsIDOMEventListener* aNew);
 
-  // Make a copy of a pair of members to be passed to NotifyEventListeners.
-  void CopyEventListeners(nsCOMPtr<nsIDOMEventListener>& aListener,
-                          const nsCOMArray<nsIDOMEventListener>& aListenerArray,
-                          nsCOMArray<nsIDOMEventListener>& aCopy);
+  nsresult GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
+                                 nsIDOMEventListener** aListener);
 
-  // aListeners must be a "non-live" list (i.e., addEventListener and
-  // removeEventListener should not affect it).  It should be built from
-  // member variables by calling CopyEventListeners.
-  void NotifyEventListeners(const nsCOMArray<nsIDOMEventListener>& aListeners,
-                            nsIDOMEvent* aEvent);
-  void ClearEventListeners();
   already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
 
   /**
    * Check if mChannel is ok for a cross-site request by making sure no
    * inappropriate headers are set, and no username/password is set.
    *
    * Also updates the XML_HTTP_REQUEST_USE_XSITE_AC bit.
    */
@@ -192,31 +300,22 @@ protected:
 
   nsCOMPtr<nsISupports> mContext;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIChannel> mChannel;
   // mReadRequest is different from mChannel for multipart requests
   nsCOMPtr<nsIRequest> mReadRequest;
   nsCOMPtr<nsIDOMDocument> mDocument;
 
-  nsCOMArray<nsIDOMEventListener> mLoadEventListeners;
-  nsCOMArray<nsIDOMEventListener> mErrorEventListeners;
-  nsCOMArray<nsIDOMEventListener> mProgressEventListeners;
-  nsCOMArray<nsIDOMEventListener> mUploadProgressEventListeners;
-  nsCOMArray<nsIDOMEventListener> mReadystatechangeEventListeners;
-
   // These may be null (native callers or xpcshell).
   nsCOMPtr<nsIScriptContext> mScriptContext;
   nsCOMPtr<nsPIDOMWindow>    mOwner; // Inner window.
 
-  nsCOMPtr<nsIDOMEventListener> mOnLoadListener;
-  nsCOMPtr<nsIDOMEventListener> mOnErrorListener;
-  nsCOMPtr<nsIDOMEventListener> mOnProgressListener;
-  nsCOMPtr<nsIDOMEventListener> mOnUploadProgressListener;
-  nsCOMPtr<nsIDOMEventListener> mOnReadystatechangeListener;
+  nsRefPtr<nsDOMEventListenerWrapper> mOnUploadProgressListener;
+  nsRefPtr<nsDOMEventListenerWrapper> mOnReadystatechangeListener;
 
   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
 
   // used to implement getAllResponseHeaders()
   class nsHeaderVisitor : public nsIHttpHeaderVisitor {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHTTPHEADERVISITOR
@@ -244,30 +343,79 @@ protected:
   nsCOMPtr<nsIChannelEventSink> mChannelEventSink;
   nsCOMPtr<nsIProgressEventSink> mProgressEventSink;
 
   PRUint32 mState;
 
   // List of potentially dangerous headers explicitly set using
   // SetRequestHeader.
   nsTArray<nsCString> mExtraRequestHeaders;
+
+  nsRefPtr<nsXMLHttpRequestUpload> mUpload;
+  PRUint32 mUploadTransferred;
+  PRUint32 mUploadTotal;
+  PRPackedBool mUploadComplete;
+
+  PRPackedBool mErrorLoad;
 };
 
-
 // helper class to expose a progress DOM Event
 
-class nsXMLHttpProgressEvent : public nsIDOMLSProgressEvent
+class nsXMLHttpProgressEvent : public nsIDOMProgressEvent,
+                               public nsIDOMLSProgressEvent,
+                               public nsIDOMNSEvent,
+                               public nsIPrivateDOMEvent
 {
 public:
-  nsXMLHttpProgressEvent(nsIDOMEvent * aInner, PRUint64 aCurrentProgress, PRUint64 aMaxProgress);
+  nsXMLHttpProgressEvent(nsIDOMProgressEvent* aInner,
+                         PRUint64 aCurrentProgress,
+                         PRUint64 aMaxProgress);
   virtual ~nsXMLHttpProgressEvent();
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpProgressEvent, nsIDOMNSEvent)
+  NS_FORWARD_NSIDOMEVENT(mInner->)
+  NS_FORWARD_NSIDOMNSEVENT(mInner->)
+  NS_FORWARD_NSIDOMPROGRESSEVENT(mInner->)
   NS_DECL_NSIDOMLSPROGRESSEVENT
-  NS_FORWARD_NSIDOMEVENT(mInner->)
+  // nsPrivateDOMEvent
+  NS_IMETHOD DuplicatePrivateData()
+  {
+    return mInner->DuplicatePrivateData();
+  }
+  NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget)
+  {
+    return mInner->SetTarget(aTarget);
+  }
+  NS_IMETHOD SetCurrentTarget(nsIDOMEventTarget* aTarget)
+  {
+    return mInner->SetCurrentTarget(aTarget);
+  }
+  NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aTarget)
+  {
+    return mInner->SetOriginalTarget(aTarget);
+  }
+  NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchPrevented)
+  {
+    return mInner->IsDispatchStopped(aIsDispatchPrevented);
+  }
+  NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent)
+  {
+    return mInner->GetInternalNSEvent(aNSEvent);
+  }
+  NS_IMETHOD HasOriginalTarget(PRBool* aResult)
+  {
+    return mInner->HasOriginalTarget(aResult);
+  }
+  NS_IMETHOD SetTrusted(PRBool aTrusted)
+  {
+    return mInner->SetTrusted(aTrusted);
+  }
 
 protected:
-  nsCOMPtr<nsIDOMEvent> mInner;
+  // Use nsDOMProgressEvent so that we can forward
+  // most of the method calls easily.
+  nsRefPtr<nsDOMProgressEvent> mInner;
   PRUint64 mCurProgress;
   PRUint64 mMaxProgress;
 };
 
 #endif
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -112,16 +112,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug366946.html \
 		test_bug367164.html \
 		test_bug371576-1.html \
 		test_bug371576-2.html \
 		test_bug371576-3.html \
 		test_bug371576-4.html \
 		test_bug371576-5.html \
 		test_bug372086.html \
+		test_bug372964.html \
 		test_bug373181.xhtml \
 		test_bug375314.html \
 		test_bug378969.html \
 		test_bug382113.html \
 		test_bug383430.html \
 		test_bug390219.html \
 		test_bug390735.html \
 		test_bug392318.html \
@@ -178,16 +179,19 @@ include $(topsrcdir)/config/rules.mk
 		file_XHR_pass3.txt^headers^ \
 		file_XHR_fail1.txt \
 		file_XHR_fail1.txt^headers^ \
 		test_bug428847.html \
 		file_bug428847-1.xhtml \
 		file_bug428847-2.xhtml \
 		test_bug425201.html \
 		test_bug431833.html \
+		test_bug435425.html \
+		bug435425.sjs \
+		bug435425_redirect.sjs \
 		test_bug438519.html \
 		test_bug444722.html \
 		test_text_replaceWholeText.html \
 		test_text_wholeText.html \
 		wholeTexty-helper.xml \
 		test_bug444030.xhtml \
 		test_NodeIterator_basics_filters.xhtml \
 		test_NodeIterator_mutations_1.xhtml \
new file mode 100644
--- /dev/null
+++ b/content/base/test/bug435425.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response)
+{
+  response.setHeader("Content-Type", "text/plain", false);
+  response.write(request.queryString);
+}
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/bug435425_redirect.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response)
+{
+  response.setStatusLine(null, 302, "Moved");
+  response.setHeader("Location", "http://www.mozilla.org", false);
+}
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug372964.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=372964
+-->
+<head>
+  <title>Test for Bug 372964</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>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=372964">Mozilla Bug 372964</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 372964 **/
+
+var expectedEventType = "";
+var shouldBeTrusted = false;
+var eventHandlerCallCount = 0;
+
+function eventHandler(evt) {
+  ++eventHandlerCallCount;
+  is(evt.type, expectedEventType, "Wrong event type");
+  is(evt.isTrusted, shouldBeTrusted, "Wrong .isTrusted");
+}
+
+function test(trusted, type, removeAddedListener, removeSetListener, allowUntrusted) {
+  if (trusted) {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  }
+  var x1 = new XMLHttpRequest();
+
+  var handlerCount = 0;
+  if (trusted || allowUntrusted || allowUntrusted == undefined) {
+    ++handlerCount;
+  }
+
+  if (allowUntrusted == undefined) {
+    // Test .addEventListener with 3 parameters.
+    x1.addEventListener(type, eventHandler, false);
+  } else {
+    // Test .addEventListener with 4 parameters.
+    x1.addEventListener(type, eventHandler, false, allowUntrusted);
+  }
+
+  if (("on" + type) in x1) {
+    ++handlerCount;
+    x1["on" + type] = eventHandler;
+  }
+
+  if (removeAddedListener) {
+    x1.removeEventListener(type, eventHandler, false);
+    if (trusted || allowUntrusted || allowUntrusted == undefined) {
+      --handlerCount;
+    }
+  }
+
+  if (removeSetListener) {
+    if (("on" + type) in x1) {
+      --handlerCount;
+      x1["on" + type] = null;
+    }
+  }
+
+  var e1 = document.createEvent("Events");
+  e1.initEvent(type, true, true);
+  expectedEventType = type;
+  shouldBeTrusted = trusted;
+  var ecc = eventHandlerCallCount;
+  x1.dispatchEvent(e1);
+  is(eventHandlerCallCount, ecc + handlerCount,
+     "Wrong number event handler calls. (1)");
+
+  e1 = document.createEvent("Events");
+  e1.initEvent(type, true, true);
+  expectedEventType = type;
+  // Set trusted since open() may cause events to be sent.
+  shouldBeTrusted = true;
+  x1.open("GET", window.location);
+  x1.abort(); // This should not remove event listeners.
+  ecc = eventHandlerCallCount;
+  shouldBeTrusted = trusted;
+  x1.dispatchEvent(e1);
+  is(eventHandlerCallCount, ecc + handlerCount,
+     "Wrong number event handler calls. (2)");
+
+  e1 = document.createEvent("Events");
+  e1.initEvent(type, true, true);
+  expectedEventType = type;
+  // Set trusted since open()/send() may cause events to be sent.
+  shouldBeTrusted = true;
+  x1.open("GET", window.location);
+  x1.send("");
+  x1.abort(); // This should not remove event listeners!
+  ecc = eventHandlerCallCount;
+  shouldBeTrusted = trusted;
+  x1.dispatchEvent(e1);
+  is(eventHandlerCallCount, ecc + handlerCount,
+     "Wrong number event handler calls. (3)");
+}
+
+var events =
+  ["load", "error", "progress", "uploadprogress", "readystatechange", "foo"];
+
+do {
+  var e = events.shift();
+  test(false, e, false, false);
+  test(false, e, false, true);
+  test(false, e, true,  false);
+  test(false, e, true,  true);
+  test(true,  e, false, false);
+  test(true,  e, false, true);
+  test(true,  e, true,  false);
+  test(true,  e, true,  true);
+
+  test(false, e, false, false, false);
+  test(false, e, false, false, true);
+  test(false, e, false, true,  false);
+  test(false, e, false, true,  true);
+  test(false, e, true,  false, false);
+  test(false, e, true,  false, true);
+  test(false, e, true,  true,  false);
+  test(false, e, true,  true,  true);
+  test(true,  e, false, false, false);
+  test(true,  e, false, false, true);
+  test(true,  e, false, true,  false);
+  test(true,  e, false, true,  true);
+  test(true,  e, true,  false, false);
+  test(true,  e, true,  false, true);
+  test(true,  e, true,  true,  false);
+  test(true,  e, true,  true,  true);
+} while(events.length);
+
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug435425.html
@@ -0,0 +1,344 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=435425
+-->
+<head>
+  <title>Test for Bug 435425</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>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435425">Mozilla Bug 435425</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 435425 **/
+
+var xhr = null;
+var upload = null;
+var currentEvents = null;
+var expectedResponseText = null;
+
+function logEvent(evt) {
+  var i = 0;
+  while ((currentEvents.length != i) &&
+         currentEvents[i].optional &&
+         ((currentEvents[i].type != evt.type) ||
+          (!evt.target instanceof currentEvents[i].target))) {
+    ++i;
+  }
+  ok(i != currentEvents.length, "Extra or wrong event?");
+  is(evt.type, currentEvents[i].type, "Wrong event!")
+  ok(evt.target instanceof currentEvents[i].target, "Wrong event target [" + evt.type + "]!");
+  // If we handled non-optional event, remove all optional events before the 
+  // handled event and then the non-optional event from the list.
+  if (!currentEvents[i].optional) {
+    for (;i != -1; --i) {
+      currentEvents.shift();
+    }
+  }
+}
+
+function stop(evt) {
+  logEvent(evt);
+  nextTest();
+}
+
+function openXHR(xhr, method, url, privileged) {
+  try {
+    if (privileged) {
+      netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    }
+  } catch (ex) {
+    ok(false, ex);
+  }
+  xhr.open(method, url);
+}
+
+function start(obj) {
+  xhr = new XMLHttpRequest();
+  upload = xhr.upload;
+  currentEvents = obj.expectedEvents;
+  expectedResponseText = obj.withUpload;
+  xhr.onload =
+    function(evt) {
+      if (expectedResponseText) {
+        is(evt.target.responseText, expectedResponseText, "Wrong responseText");
+      }
+      stop(evt);
+    }
+  xhr.onerror =
+    function(evt) {
+      stop(evt);
+    }
+  xhr.onabort =
+    function(evt) {
+      stop(evt);
+    }
+
+  xhr.onloadstart =
+    function (evt) {
+      logEvent(evt);
+    }
+  xhr.onprogress =
+    function (evt) {
+      logEvent(evt);
+    }
+  xhr.onuploadprogress =
+    function (evt) {
+      logEvent(evt);
+    }
+
+  if ("upload" in xhr) {
+    xhr.upload.onloadstart =
+      function (evt) {
+        logEvent(evt);
+      }
+    xhr.upload.onprogress =
+      function (evt) {
+        logEvent(evt);
+      }
+    xhr.upload.onload =
+      function (evt) {
+        logEvent(evt);
+      }
+    xhr.upload.onerror =
+      function (evt) {
+        logEvent(evt);
+      }
+    xhr.upload.onabort =
+      function (evt) {
+        logEvent(evt);
+      }
+  }
+
+  try {
+    var url;
+    var privileged = false;
+    if (obj.testRedirectError) {
+      url = "bug435425_redirect.sjs";
+    } else if (obj.testNetworkError) {
+      url = "http://nosuchdomain.localhost";
+      privileged = true;
+    } else {
+      url = "bug435425.sjs";
+      if (obj.withUpload) {
+        url += "?" + obj.withUpload;
+      }
+    }
+    openXHR(xhr, obj.method, url, privileged);
+    xhr.send(obj.withUpload);
+    if (obj.testAbort) {
+      xhr.abort();
+    }
+  } catch (ex) {
+    ok(false, ex);
+  }
+}
+
+var none = null;
+var small = "";
+var mid = "";
+var large = "";
+
+
+for (var smallLength = 0; smallLength < (0x00000000 + 2); ++smallLength) {
+  small += "A";
+}
+
+for (var midLength = 0; midLength < (0x00000FFF + 2); ++midLength) {
+  mid += "A";
+}
+
+for (var largeLength = 0; largeLength < (0x0000FFFF + 2); ++largeLength) {
+  large += "A";
+}
+
+const XHR = Components.interfaces.nsIXMLHttpRequest;
+const UPLOAD = Components.interfaces.nsIXMLHttpRequestUpload;
+
+var tests = 
+  [
+    { method: "GET", withUpload: none, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "GET", withUpload: none, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false}]},
+    { method: "GET", withUpload: none, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+    { method: "GET", withUpload: none, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+
+    { method: "GET", withUpload: small, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "GET", withUpload: small, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false}]},
+    { method: "GET", withUpload: small, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+    { method: "GET", withUpload: small, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+
+    { method: "GET", withUpload: mid, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "GET", withUpload: mid, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false}]},
+    { method: "GET", withUpload: mid, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+    { method: "GET", withUpload: mid, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+
+    { method: "GET", withUpload: large, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "GET", withUpload: large, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false}]},
+    { method: "GET", withUpload: large, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+    { method: "GET", withUpload: large, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+
+    { method: "POST", withUpload: none, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "POST", withUpload: none, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false}]},
+    { method: "POST", withUpload: none, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+    { method: "POST", withUpload: none, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: XHR, type: "error", optional: false}]},
+
+    { method: "POST", withUpload: small, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: UPLOAD, type: "load", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "POST", withUpload: small, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false},
+                       {target: UPLOAD, type: "abort", optional: false}]},
+    { method: "POST", withUpload: small, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: XHR, type: "error", optional: false},
+                       {target: UPLOAD, type: "error", optional: false}]},
+    { method: "POST", withUpload: small, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: XHR, type: "error", optional: false},
+                       {target: UPLOAD, type: "error", optional: false}]},
+
+    { method: "POST", withUpload: mid, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: UPLOAD, type: "load", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "POST", withUpload: mid, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false},
+                       {target: UPLOAD, type: "abort", optional: false}]},
+    { method: "POST", withUpload: mid, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: XHR, type: "error", optional: false},
+                       {target: UPLOAD, type: "error", optional: false}]},
+    { method: "POST", withUpload: mid, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: XHR, type: "error", optional: false},
+                       {target: UPLOAD, type: "error", optional: false}]},
+
+    { method: "POST", withUpload: large, testAbort: false, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: UPLOAD, type: "load", optional: false},
+                       {target: XHR, type: "progress", optional: true},
+                       {target: XHR, type: "load", optional: false}]},
+    { method: "POST", withUpload: large, testAbort: true, testRedirectError: false, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "abort", optional: false},
+                       {target: UPLOAD, type: "abort", optional: false}]},
+    { method: "POST", withUpload: large, testAbort: false, testRedirectError: true, testNetworkError: false,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: XHR, type: "error", optional: false},
+                       {target: UPLOAD, type: "error", optional: false}]},
+    { method: "POST", withUpload: large, testAbort: false, testRedirectError: false, testNetworkError: true,
+      expectedEvents: [{target: XHR, type: "loadstart", optional: false},
+                       {target: UPLOAD, type: "loadstart", optional: false},
+                       {target: XHR, type: "uploadprogress", optional: true},
+                       {target: UPLOAD, type: "progress", optional: true},
+                       {target: XHR, type: "error", optional: false},
+                       {target: UPLOAD, type: "error", optional: false}]},
+];
+
+function runTest() {
+  var test = tests.shift();
+  start(test);
+}
+
+function nextTest() {
+  if (tests.length > 1) {
+    setTimeout("runTest()", 0);
+  } else {
+    SimpleTest.finish();
+  }
+}
+
+ok("upload" in (new XMLHttpRequest()), "XMLHttpRequest.upload isn't supported!");
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -39,18 +39,17 @@
 DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = content/canvas/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
-
-_TEST_FILES_A = \
+_TEST_FILES_0 = \
 	test_fallback.basic.html \
 	test_fallback.multiple.html \
 	test_fallback.nested.html \
 	test_type.name.html \
 	test_type.exists.html \
 	test_type.delete.html \
 	test_type.prototype.html \
 	test_type.replace.html \
@@ -82,29 +81,46 @@ include $(topsrcdir)/config/rules.mk
 	test_initial.colour.html \
 	test_initial.reset.different.html \
 	test_initial.reset.same.html \
 	test_initial.reset.path.html \
 	test_initial.reset.clip.html \
 	test_initial.reset.transform.html \
 	test_initial.reset.gradient.html \
 	test_initial.reset.pattern.html \
+	test_context.emptystring.html \
+	test_context.unrecognised.badname.html \
+	test_context.unrecognised.badsuffix.html \
+	test_context.unrecognised.nullsuffix.html \
+	test_context.unrecognised.unicode.html \
+	test_context.casesensitive.html \
+	test_context.arguments.missing.html \
+	test_context.arguments.extra.html \
 	test_toDataURL.default.html \
 	test_toDataURL.png.html \
+	test_toDataURL.unrecognised.html \
+	test_toDataURL.lowercase.html \
+	test_toDataURL.arguments.1.html \
+	test_toDataURL.arguments.2.html \
+	test_toDataURL.arguments.3.html \
 	test_toDataURL.nocontext.html \
+	test_toDataURL.zerosize.html \
+	test_toDataURL.primarycolours.html \
+	test_toDataURL.complexcolours.html \
 	test_2d.getcontext.exists.html \
-	test_2d.type.name.html \
 	test_2d.type.exists.html \
 	test_2d.type.delete.html \
 	test_2d.type.prototype.html \
 	test_2d.type.replace.html \
 	test_2d.type.extend.html \
 	test_2d.getcontext.unique.html \
 	test_2d.getcontext.shared.html \
 	test_2d.voidreturn.html \
+	test_2d.missingargs.html \
+	test_2d.scaled.html \
 	test_2d.canvas.reference.html \
 	test_2d.canvas.readonly.html \
 	test_2d.state.saverestore.strokeStyle.html \
 	test_2d.state.saverestore.fillStyle.html \
 	test_2d.state.saverestore.globalAlpha.html \
 	test_2d.state.saverestore.lineWidth.html \
 	test_2d.state.saverestore.lineCap.html \
 	test_2d.state.saverestore.lineJoin.html \
@@ -116,453 +132,700 @@ include $(topsrcdir)/config/rules.mk
 	test_2d.state.saverestore.globalCompositeOperation.html \
 	test_initial.reset.2dstate.html \
 	test_2d.state.saverestore.transformation.html \
 	test_2d.state.saverestore.clip.html \
 	test_2d.state.saverestore.path.html \
 	test_2d.state.saverestore.bitmap.html \
 	test_2d.state.saverestore.stack.html \
 	test_2d.state.saverestore.stackdepth.html \
+	test_2d.state.saverestore.underflow.html \
 	test_2d.transformation.order.html \
 	test_2d.transformation.scale.basic.html \
 	test_2d.transformation.scale.zero.html \
 	test_2d.transformation.scale.negative.html \
 	test_2d.transformation.scale.large.html \
+	test_2d.transformation.scale.nonfinite.html \
 	test_2d.transformation.scale.multiple.html \
+	$(NULL)
+
+_TEST_FILES_1 = \
 	test_2d.transformation.rotate.zero.html \
 	test_2d.transformation.rotate.radians.html \
 	test_2d.transformation.rotate.direction.html \
 	test_2d.transformation.rotate.wrap.html \
 	test_2d.transformation.rotate.wrapnegative.html \
-	test_2d.transformation.rotate.infinity.html \
-	test_2d.transformation.rotate.neginfinity.html \
-	test_2d.transformation.rotate.nan.html \
+	test_2d.transformation.rotate.nonfinite.html \
 	test_2d.transformation.translate.basic.html \
+	test_2d.transformation.translate.nonfinite.html \
 	test_2d.transformation.transform.identity.html \
 	test_2d.transformation.transform.skewed.html \
 	test_2d.transformation.transform.multiply.html \
+	test_2d.transformation.transform.nonfinite.html \
 	test_2d.transformation.setTransform.skewed.html \
 	test_2d.transformation.setTransform.multiple.html \
+	test_2d.transformation.setTransform.nonfinite.html \
 	test_2d.composite.globalAlpha.range.html \
+	test_2d.composite.globalAlpha.invalid.html \
 	test_2d.composite.globalAlpha.default.html \
 	test_2d.composite.globalAlpha.fill.html \
 	test_2d.composite.globalAlpha.image.html \
 	test_2d.composite.globalAlpha.canvas.html \
 	test_2d.composite.globalAlpha.imagepattern.html \
 	test_2d.composite.globalAlpha.canvaspattern.html \
-	$(NULL)
-# The following two tests tend to fail randomly.
-#       test_toDataURL.primarycolours.html 
-#       test_toDataURL.complexcolours.html 
-
-_TEST_FILES_B = \
 	test_2d.composite.solid.source-over.html \
 	test_2d.composite.solid.destination-over.html \
 	test_2d.composite.solid.source-in.html \
 	test_2d.composite.solid.destination-in.html \
 	test_2d.composite.solid.source-out.html \
 	test_2d.composite.solid.destination-out.html \
 	test_2d.composite.solid.source-atop.html \
 	test_2d.composite.solid.destination-atop.html \
 	test_2d.composite.solid.copy.html \
-	test_2d.composite.solid.lighter.html \
 	test_2d.composite.transparent.source-over.html \
 	test_2d.composite.transparent.destination-over.html \
 	test_2d.composite.transparent.source-in.html \
 	test_2d.composite.transparent.destination-in.html \
 	test_2d.composite.transparent.source-out.html \
 	test_2d.composite.transparent.destination-out.html \
 	test_2d.composite.transparent.source-atop.html \
 	test_2d.composite.transparent.destination-atop.html \
-	test_2d.composite.transparent.xor.html \
 	test_2d.composite.transparent.copy.html \
-	test_2d.composite.transparent.lighter.html \
 	test_2d.composite.image.source-over.html \
-	test_2d.composite.image.source-in.html \
-	test_2d.composite.image.source-out.html \
-	test_2d.composite.image.source-atop.html \
 	test_2d.composite.image.destination-over.html \
+	test_2d.composite.image.source-in.html \
 	test_2d.composite.image.destination-in.html \
+	test_2d.composite.image.source-out.html \
 	test_2d.composite.image.destination-out.html \
+	test_2d.composite.image.source-atop.html \
 	test_2d.composite.image.destination-atop.html \
-	test_2d.composite.image.xor.html \
 	test_2d.composite.image.copy.html \
-	test_2d.composite.image.lighter.html \
+	test_2d.composite.canvas.source-over.html \
+	test_2d.composite.canvas.destination-over.html \
+	test_2d.composite.canvas.source-in.html \
+	test_2d.composite.canvas.destination-in.html \
+	test_2d.composite.canvas.source-out.html \
+	test_2d.composite.canvas.destination-out.html \
+	test_2d.composite.canvas.source-atop.html \
+	test_2d.composite.canvas.destination-atop.html \
+	test_2d.composite.canvas.copy.html \
+	test_2d.composite.uncovered.fill.copy.html \
+	test_2d.composite.uncovered.image.source-in.html \
+	test_2d.composite.uncovered.image.destination-in.html \
+	test_2d.composite.uncovered.image.source-out.html \
+	test_2d.composite.uncovered.image.destination-atop.html \
+	test_2d.composite.uncovered.image.copy.html \
+	test_2d.composite.uncovered.pattern.copy.html \
+	test_2d.composite.clip.source-over.html \
+	test_2d.composite.clip.destination-over.html \
+	test_2d.composite.clip.source-in.html \
+	test_2d.composite.clip.destination-in.html \
+	test_2d.composite.clip.source-out.html \
+	test_2d.composite.clip.destination-out.html \
+	test_2d.composite.clip.source-atop.html \
+	test_2d.composite.clip.destination-atop.html \
+	test_2d.composite.clip.copy.html \
 	test_2d.composite.operation.get.html \
+	test_2d.composite.operation.unrecognised.html \
 	test_2d.composite.operation.darker.html \
 	test_2d.composite.operation.over.html \
 	test_2d.composite.operation.clear.html \
+	test_2d.composite.operation.highlight.html \
+	test_2d.composite.operation.nullsuffix.html \
+	$(NULL)
+
+_TEST_FILES_2 = \
+	test_2d.composite.operation.casesensitive.html \
 	test_2d.composite.operation.default.html \
 	test_2d.fillStyle.parse.html4.html \
 	test_2d.fillStyle.parse.hex3.html \
 	test_2d.fillStyle.parse.hex6.html \
 	test_2d.fillStyle.parse.rgb-num.html \
 	test_2d.fillStyle.parse.rgb-clamp-1.html \
 	test_2d.fillStyle.parse.rgb-clamp-2.html \
+	test_2d.fillStyle.parse.rgb-clamp-3.html \
+	test_2d.fillStyle.parse.rgb-clamp-4.html \
+	test_2d.fillStyle.parse.rgb-clamp-5.html \
 	test_2d.fillStyle.parse.rgb-percent.html \
 	test_2d.fillStyle.parse.rgba-solid-1.html \
 	test_2d.fillStyle.parse.rgba-solid-2.html \
 	test_2d.fillStyle.parse.rgba-num-1.html \
 	test_2d.fillStyle.parse.rgba-num-2.html \
 	test_2d.fillStyle.parse.rgba-percent.html \
 	test_2d.fillStyle.parse.rgba-clamp-1.html \
 	test_2d.fillStyle.parse.rgba-clamp-2.html \
 	test_2d.fillStyle.parse.transparent-1.html \
 	test_2d.fillStyle.parse.transparent-2.html \
 	test_2d.fillStyle.parse.hsl-1.html \
 	test_2d.fillStyle.parse.hsl-2.html \
 	test_2d.fillStyle.parse.hsl-3.html \
 	test_2d.fillStyle.parse.hsl-4.html \
 	test_2d.fillStyle.parse.hsl-5.html \
+	test_2d.fillStyle.parse.hsl-clamp-1.html \
+	test_2d.fillStyle.parse.hsl-clamp-2.html \
+	test_2d.fillStyle.parse.hsl-clamp-3.html \
+	test_2d.fillStyle.parse.hsl-clamp-4.html \
 	test_2d.fillStyle.parse.hsla-1.html \
 	test_2d.fillStyle.parse.hsla-2.html \
+	test_2d.fillStyle.parse.hsla-clamp-1.html \
+	test_2d.fillStyle.parse.hsla-clamp-2.html \
+	test_2d.fillStyle.parse.hsla-clamp-3.html \
+	test_2d.fillStyle.parse.hsla-clamp-4.html \
+	test_2d.fillStyle.parse.hsla-clamp-5.html \
+	test_2d.fillStyle.parse.hsla-clamp-6.html \
 	test_2d.fillStyle.parse.svg-1.html \
 	test_2d.fillStyle.parse.svg-2.html \
 	test_2d.fillStyle.parse.invalid.hex3.html \
 	test_2d.fillStyle.parse.invalid.hex6.html \
 	test_2d.fillStyle.parse.invalid.rgb-1.html \
 	test_2d.fillStyle.parse.invalid.rgb-2.html \
 	test_2d.fillStyle.parse.invalid.rgb-3.html \
 	test_2d.fillStyle.parse.invalid.rgb-4.html \
+	test_2d.fillStyle.parse.invalid.rgb-5.html \
+	test_2d.fillStyle.parse.invalid.rgb-6.html \
+	test_2d.fillStyle.parse.invalid.rgb-7.html \
 	test_2d.fillStyle.parse.invalid.rgba-1.html \
 	test_2d.fillStyle.parse.invalid.rgba-2.html \
 	test_2d.fillStyle.parse.invalid.rgba-3.html \
 	test_2d.fillStyle.parse.invalid.rgba-4.html \
 	test_2d.fillStyle.parse.invalid.rgba-5.html \
 	test_2d.fillStyle.parse.invalid.hsl-1.html \
 	test_2d.fillStyle.parse.invalid.hsl-2.html \
 	test_2d.fillStyle.parse.invalid.hsl-3.html \
 	test_2d.fillStyle.parse.invalid.hsl-4.html \
+	test_2d.fillStyle.parse.invalid.hsl-5.html \
+	test_2d.fillStyle.parse.invalid.hsla-1.html \
+	test_2d.fillStyle.parse.invalid.hsla-2.html \
 	test_2d.fillStyle.parse.system.html \
-	test_2d.fillStyle.parse.flavor.html \
+	test_2d.fillStyle.parse.current.basic.html \
+	test_2d.fillStyle.parse.current.changed.html \
+	test_2d.fillStyle.parse.current.removed.html \
 	test_2d.fillStyle.invalidstring.html \
 	test_2d.fillStyle.invalidtype.html \
 	test_2d.fillStyle.get.solid.html \
 	test_2d.fillStyle.get.semitransparent.html \
 	test_2d.fillStyle.get.transparent.html \
 	test_2d.fillStyle.default.html \
 	test_2d.strokeStyle.default.html \
+	test_2d.gradient.object.type.html \
 	test_2d.gradient.object.return.html \
 	test_2d.gradient.interpolate.solid.html \
 	test_2d.gradient.interpolate.colour.html \
 	test_2d.gradient.interpolate.alpha.html \
 	test_2d.gradient.interpolate.colouralpha.html \
 	test_2d.gradient.interpolate.outside.html \
 	test_2d.gradient.interpolate.zerosize.html \
 	test_2d.gradient.interpolate.vertical.html \
 	test_2d.gradient.interpolate.multiple.html \
 	test_2d.gradient.interpolate.overlap.html \
 	test_2d.gradient.interpolate.overlap2.html \
+	test_2d.gradient.empty.html \
 	test_2d.gradient.object.update.html \
 	test_2d.gradient.object.compare.html \
 	test_2d.gradient.object.crosscanvas.html \
 	test_2d.gradient.object.invalidoffset.html \
 	test_2d.gradient.object.invalidcolour.html \
+	test_2d.gradient.linear.nonfinite.html \
+	test_2d.gradient.linear.transform.1.html \
+	test_2d.gradient.linear.transform.2.html \
+	test_2d.gradient.linear.transform.3.html \
+	test_2d.gradient.radial.negative.html \
+	test_2d.gradient.radial.nonfinite.html \
+	test_2d.gradient.radial.inside1.html \
 	$(NULL)
 
-_TEST_FILES_C = \
-	test_2d.gradient.radial.negative.html \
-	test_2d.gradient.radial.invalid.html \
-	test_2d.gradient.radial.inside1.html \
-	test_2d.gradient.radial.inside2.html \
-	test_2d.gradient.radial.outside1.html \
-	test_2d.gradient.radial.cone.front.html \
+_TEST_FILES_3 = \
 	test_2d.gradient.radial.cone.bottom.html \
-	test_2d.gradient.radial.cone.top.html \
 	test_2d.gradient.radial.cone.cylinder.html \
 	test_2d.gradient.radial.cone.shape1.html \
+	test_2d.gradient.radial.transform.1.html \
+	test_2d.gradient.radial.transform.2.html \
+	test_2d.gradient.radial.transform.3.html \
 	test_2d.pattern.basic.type.html \
 	test_2d.pattern.basic.image.html \
 	test_2d.pattern.basic.canvas.html \
+	test_2d.pattern.basic.zerocanvas.html \
 	test_2d.pattern.basic.nocontext.html \
 	test_2d.pattern.image.undefined.html \
 	test_2d.pattern.image.null.html \
 	test_2d.pattern.image.string.html \
 	test_2d.pattern.image.incomplete.html \
 	test_2d.pattern.image.broken.html \
 	test_2d.pattern.repeat.empty.html \
 	test_2d.pattern.repeat.null.html \
 	test_2d.pattern.repeat.undefined.html \
-	test_2d.pattern.repeat.missing.html \
 	test_2d.pattern.repeat.unrecognised.html \
 	test_2d.pattern.repeat.case.html \
 	test_2d.pattern.repeat.nullsuffix.html \
 	test_2d.pattern.modify.image1.html \
 	test_2d.pattern.modify.image2.html \
 	test_2d.pattern.modify.canvas1.html \
 	test_2d.pattern.modify.canvas2.html \
 	test_2d.pattern.crosscanvas.html \
 	test_2d.pattern.paint.norepeat.basic.html \
 	test_2d.pattern.paint.norepeat.outside.html \
 	test_2d.pattern.paint.norepeat.coord1.html \
 	test_2d.pattern.paint.norepeat.coord2.html \
-	test_2d.pattern.paint.coord3.html \
+	test_2d.pattern.paint.norepeat.coord3.html \
 	test_2d.pattern.paint.repeat.basic.html \
 	test_2d.pattern.paint.repeat.outside.html \
 	test_2d.pattern.paint.repeat.coord1.html \
 	test_2d.pattern.paint.repeat.coord2.html \
 	test_2d.pattern.paint.repeat.coord3.html \
 	test_2d.pattern.paint.repeatx.basic.html \
 	test_2d.pattern.paint.repeatx.outside.html \
 	test_2d.pattern.paint.repeatx.coord1.html \
 	test_2d.pattern.paint.repeaty.basic.html \
 	test_2d.pattern.paint.repeaty.outside.html \
 	test_2d.pattern.paint.repeaty.coord1.html \
+	test_2d.pattern.paint.orientation.image.html \
+	test_2d.pattern.paint.orientation.canvas.html \
+	test_2d.pattern.animated.gif.html \
 	test_2d.line.defaults.html \
-	test_2d.line.invalid.lineWidth.html \
-	test_2d.line.invalid.miterLimit.html \
-	test_2d.line.lineWidth.basic.html \
-	test_2d.line.lineWidth.transformed.html \
-	test_2d.line.lineCap.butt.html \
-	test_2d.line.lineCap.round.html \
-	test_2d.line.lineCap.square.html \
-	test_2d.line.lineJoin.bevel.html \
-	test_2d.line.lineJoin.round.html \
-	test_2d.line.lineJoin.miter.html \
+	test_2d.line.width.basic.html \
+	test_2d.line.width.transformed.html \
+	test_2d.line.width.invalid.html \
+	test_2d.line.cap.butt.html \
+	test_2d.line.cap.round.html \
+	test_2d.line.cap.square.html \
+	test_2d.line.cap.open.html \
+	test_2d.line.cap.invalid.html \
+	test_2d.line.join.bevel.html \
+	test_2d.line.join.round.html \
+	test_2d.line.join.miter.html \
 	test_2d.line.join.open.html \
 	test_2d.line.join.closed.html \
-	test_2d.line.join.zeroline.join.html \
-	test_2d.line.cap.open.html \
-	test_2d.line.cap.zeroline.round.html \
-	test_2d.line.cap.zeroline.square.html \
+	test_2d.line.join.invalid.html \
 	test_2d.line.miter.exceeded.html \
+	test_2d.line.miter.acute.html \
+	test_2d.line.miter.obtuse.html \
 	test_2d.line.miter.rightangle.html \
 	test_2d.line.miter.lineedge.html \
+	test_2d.line.miter.within.html \
+	test_2d.line.miter.invalid.html \
 	test_2d.line.cross.html \
 	test_2d.line.union.html \
 	test_2d.clearRect.basic.html \
 	test_2d.clearRect.path.html \
 	test_2d.clearRect.zero.html \
+	test_2d.clearRect.negative.html \
 	test_2d.clearRect.transform.html \
 	test_2d.clearRect.globalalpha.html \
 	test_2d.clearRect.globalcomposite.html \
 	test_2d.clearRect.clip.html \
 	test_2d.clearRect.shadow.html \
-	test_2d.fillRect.negative.html \
+	test_2d.clearRect.nonfinite.html \
 	test_2d.fillRect.basic.html \
 	test_2d.fillRect.path.html \
 	test_2d.fillRect.zero.html \
+	test_2d.fillRect.negative.html \
 	test_2d.fillRect.transform.html \
 	test_2d.fillRect.clip.html \
 	test_2d.fillRect.shadow.html \
-	test_2d.strokeRect.negative.html \
+	$(NULL)
+
+_TEST_FILES_4 = \
+	test_2d.fillRect.nonfinite.html \
 	test_2d.strokeRect.basic.html \
 	test_2d.strokeRect.path.html \
 	test_2d.strokeRect.zero.1.html \
 	test_2d.strokeRect.zero.2.html \
 	test_2d.strokeRect.zero.3.html \
 	test_2d.strokeRect.zero.4.html \
+	test_2d.strokeRect.negative.html \
 	test_2d.strokeRect.transform.html \
 	test_2d.strokeRect.globalalpha.html \
 	test_2d.strokeRect.globalcomposite.html \
 	test_2d.strokeRect.clip.html \
 	test_2d.strokeRect.shadow.html \
-	$(NULL)
-
-_TEST_FILES_D = \
+	test_2d.strokeRect.nonfinite.html \
 	test_2d.path.initial.html \
 	test_2d.path.beginPath.html \
 	test_2d.path.moveTo.basic.html \
 	test_2d.path.moveTo.newsubpath.html \
 	test_2d.path.moveTo.multiple.html \
+	test_2d.path.moveTo.nonfinite.html \
 	test_2d.path.closePath.empty.html \
 	test_2d.path.closePath.newline.html \
 	test_2d.path.closePath.nextpoint.html \
 	test_2d.path.lineTo.emptysubpath.html \
 	test_2d.path.lineTo.basic.html \
 	test_2d.path.lineTo.nextpoint.html \
+	test_2d.path.lineTo.nonfinite.html \
 	test_2d.path.quadraticCurveTo.emptysubpath.html \
 	test_2d.path.quadraticCurveTo.basic.html \
 	test_2d.path.quadraticCurveTo.shape.html \
 	test_2d.path.quadraticCurveTo.scaled.html \
+	test_2d.path.quadraticCurveTo.nonfinite.html \
 	test_2d.path.bezierCurveTo.emptysubpath.html \
 	test_2d.path.bezierCurveTo.basic.html \
 	test_2d.path.bezierCurveTo.shape.html \
 	test_2d.path.bezierCurveTo.scaled.html \
+	test_2d.path.bezierCurveTo.nonfinite.html \
+	test_2d.path.arcTo.emptysubpath.html \
+	test_2d.path.arcTo.coincide.1.html \
+	test_2d.path.arcTo.coincide.2.html \
+	test_2d.path.arcTo.collinear.1.html \
+	test_2d.path.arcTo.collinear.2.html \
+	test_2d.path.arcTo.collinear.3.html \
+	test_2d.path.arcTo.shape.curve1.html \
+	test_2d.path.arcTo.shape.curve2.html \
+	test_2d.path.arcTo.shape.start.html \
+	test_2d.path.arcTo.shape.end.html \
+	test_2d.path.arcTo.negative.html \
+	test_2d.path.arcTo.zero.1.html \
+	test_2d.path.arcTo.zero.2.html \
+	test_2d.path.arcTo.transformation.html \
+	test_2d.path.arcTo.scale.html \
+	test_2d.path.arcTo.nonfinite.html \
 	test_2d.path.arc.empty.html \
 	test_2d.path.arc.nonempty.html \
 	test_2d.path.arc.end.html \
 	test_2d.path.arc.angle.1.html \
 	test_2d.path.arc.angle.2.html \
 	test_2d.path.arc.angle.3.html \
 	test_2d.path.arc.angle.4.html \
+	test_2d.path.arc.angle.5.html \
+	test_2d.path.arc.angle.6.html \
 	test_2d.path.arc.zero.1.html \
 	test_2d.path.arc.zero.2.html \
-	test_2d.path.arc.zero.3.html \
-	test_2d.path.arc.zero.4.html \
-	test_2d.path.arc.zero.5.html \
-	test_2d.path.arc.zero.6.html \
+	test_2d.path.arc.twopie.1.html \
+	test_2d.path.arc.twopie.2.html \
+	test_2d.path.arc.twopie.3.html \
+	test_2d.path.arc.twopie.4.html \
 	test_2d.path.arc.shape.1.html \
 	test_2d.path.arc.shape.2.html \
-	test_2d.path.arc.shape.3.html \
 	test_2d.path.arc.shape.4.html \
 	test_2d.path.arc.shape.5.html \
 	test_2d.path.arc.selfintersect.1.html \
 	test_2d.path.arc.selfintersect.2.html \
 	test_2d.path.arc.negative.html \
-	test_2d.path.arc.zero.html \
+	test_2d.path.arc.zeroradius.html \
+	test_2d.path.arc.scale.1.html \
+	test_2d.path.arc.scale.2.html \
+	test_2d.path.arc.nonfinite.html \
 	test_2d.path.rect.basic.html \
 	test_2d.path.rect.newsubpath.html \
 	test_2d.path.rect.closed.html \
 	test_2d.path.rect.end.1.html \
 	test_2d.path.rect.end.2.html \
 	test_2d.path.rect.zero.1.html \
 	test_2d.path.rect.zero.2.html \
 	test_2d.path.rect.zero.3.html \
 	test_2d.path.rect.zero.4.html \
 	test_2d.path.rect.zero.5.html \
 	test_2d.path.rect.negative.html \
+	test_2d.path.rect.winding.html \
+	test_2d.path.rect.nonfinite.html \
+	test_2d.path.fill.overlap.html \
 	test_2d.path.fill.winding.add.html \
 	test_2d.path.fill.winding.subtract.1.html \
 	test_2d.path.fill.winding.subtract.2.html \
+	$(NULL)
+
+_TEST_FILES_5 = \
 	test_2d.path.fill.winding.subtract.3.html \
 	test_2d.path.fill.closed.basic.html \
 	test_2d.path.fill.closed.unaffected.html \
+	test_2d.path.stroke.overlap.html \
 	test_2d.path.stroke.union.html \
 	test_2d.path.stroke.unaffected.html \
+	test_2d.path.stroke.scale1.html \
+	test_2d.path.stroke.scale2.html \
+	test_2d.path.stroke.skew.html \
+	test_2d.path.stroke.empty.html \
+	test_2d.path.stroke.prune.line.html \
+	test_2d.path.stroke.prune.closed.html \
+	test_2d.path.stroke.prune.curve.html \
+	test_2d.path.stroke.prune.arc.html \
+	test_2d.path.stroke.prune.rect.html \
+	test_2d.path.stroke.prune.corner.html \
 	test_2d.path.transformation.basic.html \
-	test_2d.path.transformation.multiple.1.html \
-	test_2d.path.transformation.multiple.2.html \
-	test_2d.path.transformation.multiple.3.html \
+	test_2d.path.transformation.multiple.html \
+	test_2d.path.transformation.changing.html \
 	test_2d.path.clip.empty.html \
 	test_2d.path.clip.basic.1.html \
 	test_2d.path.clip.basic.2.html \
 	test_2d.path.clip.intersect.html \
 	test_2d.path.clip.winding.1.html \
 	test_2d.path.clip.winding.2.html \
 	test_2d.path.clip.unaffected.html \
 	test_2d.path.isPointInPath.basic.1.html \
 	test_2d.path.isPointInPath.basic.2.html \
+	test_2d.path.isPointInPath.edge.html \
 	test_2d.path.isPointInPath.empty.html \
+	test_2d.path.isPointInPath.subpath.html \
+	test_2d.path.isPointInPath.outside.html \
 	test_2d.path.isPointInPath.unclosed.html \
+	test_2d.path.isPointInPath.arc.html \
+	test_2d.path.isPointInPath.bigarc.html \
+	test_2d.path.isPointInPath.bezier.html \
 	test_2d.path.isPointInPath.winding.html \
 	test_2d.path.isPointInPath.transform.1.html \
 	test_2d.path.isPointInPath.transform.2.html \
 	test_2d.path.isPointInPath.transform.3.html \
+	test_2d.path.isPointInPath.nonfinite.html \
 	test_2d.drawImage.3arg.html \
 	test_2d.drawImage.5arg.html \
 	test_2d.drawImage.9arg.basic.html \
 	test_2d.drawImage.9arg.sourcepos.html \
 	test_2d.drawImage.9arg.sourcesize.html \
 	test_2d.drawImage.9arg.destpos.html \
 	test_2d.drawImage.9arg.destsize.html \
+	test_2d.drawImage.canvas.html \
+	test_2d.drawImage.self.1.html \
+	test_2d.drawImage.self.2.html \
 	test_2d.drawImage.null.html \
 	test_2d.drawImage.wrongtype.html \
 	test_2d.drawImage.floatsource.html \
 	test_2d.drawImage.zerosource.html \
 	test_2d.drawImage.negativesource.html \
 	test_2d.drawImage.negativedest.html \
 	test_2d.drawImage.outsidesource.html \
 	test_2d.drawImage.incomplete.html \
 	test_2d.drawImage.broken.html \
+	test_2d.drawImage.animated.gif.html \
+	test_2d.drawImage.animated.apng.html \
+	test_2d.drawImage.animated.poster.html \
 	test_2d.drawImage.path.html \
 	test_2d.drawImage.transform.html \
 	test_2d.drawImage.alpha.html \
 	test_2d.drawImage.clip.html \
 	test_2d.drawImage.composite.html \
-	test_2d.drawImage.self.html \
-	$(NULL)
-
-_TEST_FILES_E = \
+	test_2d.drawImage.nowrap.html \
+	test_2d.drawImage.nonfinite.html \
+	test_2d.imageData.create.basic.html \
+	test_2d.imageData.create.type.html \
+	test_2d.imageData.create.initial.html \
+	test_2d.imageData.create.large.html \
+	test_2d.imageData.create.tiny.html \
+	test_2d.imageData.create.negative.html \
+	test_2d.imageData.create.zero.html \
+	test_2d.imageData.create.nonfinite.html \
+	test_2d.imageData.create.round.html \
 	test_2d.imageData.get.basic.html \
-	test_2d.imageData.get.sourcepos.html \
-	test_2d.imageData.get.values.html \
-	test_2d.imageData.get.sourcesize.html \
-	test_2d.imageData.get.properties.html \
+	test_2d.imageData.get.type.html \
+	test_2d.imageData.get.zero.html \
+	test_2d.imageData.get.nonfinite.html \
+	test_2d.imageData.get.source.outside.html \
+	test_2d.imageData.get.source.negative.html \
+	test_2d.imageData.get.source.size.html \
+	test_2d.imageData.get.tiny.html \
 	test_2d.imageData.get.nonpremul.html \
+	test_2d.imageData.get.range.html \
+	test_2d.imageData.get.clamp.html \
 	test_2d.imageData.get.order.cols.html \
 	test_2d.imageData.get.order.rows.html \
 	test_2d.imageData.get.order.rgb.html \
 	test_2d.imageData.get.order.alpha.html \
-	test_2d.imageData.get.smallest.html \
-	test_2d.imageData.get.nonpositive.html \
-	test_2d.imageData.get.nonfinite.html \
+	test_2d.imageData.get.unaffected.html \
+	test_2d.imageData.object.properties.html \
+	test_2d.imageData.object.readonly.html \
+	test_2d.imageData.object.ctor.html \
+	test_2d.imageData.object.set.html \
+	test_2d.imageData.object.undefined.html \
+	$(NULL)
+
+_TEST_FILES_6 = \
+	test_2d.imageData.object.nan.html \
+	test_2d.imageData.object.string.html \
+	test_2d.imageData.object.clamp.html \
+	test_2d.imageData.object.round.html \
+	test_2d.imageData.put.null.html \
+	test_2d.imageData.put.nonfinite.html \
 	test_2d.imageData.put.basic.html \
+	test_2d.imageData.put.created.html \
+	test_2d.imageData.put.wrongtype.html \
+	test_2d.imageData.put.cross.html \
 	test_2d.imageData.put.alpha.html \
 	test_2d.imageData.put.modified.html \
-	test_2d.imageData.put.type.correct.html \
-	test_2d.imageData.put.type.onepixel.html \
-	test_2d.imageData.put.type.extra.html \
-	test_2d.imageData.put.type.missing.html \
-	test_2d.imageData.put.type.invalidsize.html \
-	test_2d.imageData.put.type.invalidvalues.html \
+	test_2d.imageData.put.dirty.zero.html \
+	test_2d.imageData.put.dirty.rect1.html \
+	test_2d.imageData.put.dirty.rect2.html \
+	test_2d.imageData.put.dirty.negative.html \
+	test_2d.imageData.put.dirty.outside.html \
 	test_2d.imageData.put.unchanged.html \
 	test_2d.imageData.put.unaffected.html \
+	test_2d.imageData.put.clip.html \
 	test_2d.imageData.put.path.html \
+	test_2d.shadow.attributes.shadowBlur.1.html \
+	test_2d.shadow.attributes.shadowBlur.2.html \
+	test_2d.shadow.attributes.shadowOffset.1.html \
+	test_2d.shadow.attributes.shadowOffset.2.html \
+	test_2d.shadow.attributes.shadowColor.1.html \
+	test_2d.shadow.attributes.shadowColor.2.html \
+	test_2d.shadow.basic.1.html \
+	test_2d.shadow.basic.2.html \
+	test_2d.shadow.offset.positiveX.html \
+	test_2d.shadow.offset.negativeX.html \
+	test_2d.shadow.offset.positiveY.html \
+	test_2d.shadow.offset.negativeY.html \
+	test_2d.shadow.outside.html \
+	test_2d.shadow.clip.1.html \
+	test_2d.shadow.clip.2.html \
+	test_2d.shadow.clip.3.html \
+	test_2d.shadow.stroke.basic.html \
+	test_2d.shadow.stroke.cap.1.html \
+	test_2d.shadow.stroke.cap.2.html \
+	test_2d.shadow.stroke.join.1.html \
+	test_2d.shadow.stroke.join.2.html \
+	test_2d.shadow.stroke.join.3.html \
+	test_2d.shadow.image.basic.html \
+	test_2d.shadow.image.transparent.1.html \
+	test_2d.shadow.image.transparent.2.html \
+	test_2d.shadow.image.alpha.html \
+	test_2d.shadow.image.section.html \
+	test_2d.shadow.image.scale.html \
+	test_2d.shadow.canvas.basic.html \
+	test_2d.shadow.canvas.transparent.1.html \
+	test_2d.shadow.canvas.transparent.2.html \
+	test_2d.shadow.canvas.alpha.html \
+	test_2d.shadow.pattern.basic.html \
+	test_2d.shadow.pattern.transparent.1.html \
+	test_2d.shadow.pattern.transparent.2.html \
+	test_2d.shadow.pattern.alpha.html \
+	test_2d.shadow.gradient.basic.html \
+	test_2d.shadow.gradient.transparent.1.html \
+	test_2d.shadow.gradient.transparent.2.html \
+	test_2d.shadow.gradient.alpha.html \
+	test_2d.shadow.transform.1.html \
+	test_2d.shadow.transform.2.html \
+	test_2d.shadow.blur.low.html \
+	test_2d.shadow.blur.high.html \
+	test_2d.shadow.alpha.1.html \
+	test_2d.shadow.alpha.2.html \
+	test_2d.shadow.alpha.3.html \
+	test_2d.shadow.alpha.4.html \
+	test_2d.shadow.alpha.5.html \
+	test_2d.shadow.composite.1.html \
+	test_2d.shadow.composite.2.html \
+	test_2d.shadow.composite.3.html \
+	test_2d.shadow.composite.4.html \
 	test_bug397524.html \
 	test_bug405982.html \
-	image_transparent50.png \
-	image_redtransparent.png \
-	image_yellow.png \
-	image_green-16x16.png \
-	image_red-16x16.png \
-	image_green-1x1.png \
-	image_green-redirect \
-	image_green-redirect^headers^ \
-	image_ggrr-256x256.png \
-	image_yellow75.png \
-	image_broken.png \
-	image_rgrg-256x256.png \
-	image_red.png \
-	image_transparent.png \
-	image_green.png \
 	test_text.font.html \
 	test_text.textAlign.html \
 	test_text.textBaseline.html \
 	test_text.measure.html \
 	test_text.space.replace.html \
+	image_transparent50.png \
+	image_redtransparent.png \
+	image_yellow.png \
+	image_anim-poster-gr.png \
+	image_green-16x16.png \
+	image_red-16x16.png \
+	image_green-1x1.png \
+	image_ggrr-256x256.png \
+	image_yellow75.png \
+	image_anim-gr.gif \
+	image_rrgg-256x256.png \
+	image_broken.png \
+	image_anim-gr.png \
+	image_rgrg-256x256.png \
+	image_red.png \
+	image_transparent.png \
+	image_green.png \
+	image_green-redirect \
+	image_green-redirect^headers^ \
 	$(NULL)
 
-# This one test crashes Mac for now.  Bug 407104
-ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
-_TEST_FILES_E += \
-	test_2d.gradient.empty.html \
-	$(NULL)
-endif
+# xor and lighter aren't well handled by cairo; they mostly work, but we don't want
+# to test that
+#	test_2d.composite.solid.xor.html \
+#	test_2d.composite.solid.lighter.html \
+#	test_2d.composite.transparent.xor.html \
+#	test_2d.composite.transparent.lighter.html \
+#	test_2d.composite.image.xor.html \
+#	test_2d.composite.image.lighter.html \
+#	test_2d.composite.canvas.xor.html \
+#	test_2d.composite.canvas.lighter.html \
+#	test_2d.composite.clip.xor.html \
+#	test_2d.composite.clip.lighter.html \
+#
 
 # Tests that fail on Mac (possibly because spec is underdefined?).  Bug 407105
 ifneq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 # XXX vlad don't test these anywhere, cairo behaviour changed
-#_TEST_FILES_E += \
-#	test_2d.line.join.parallel.html \
-#	test_2d.strokeRect.zero.5.html \
-#	test_2d.line.join.zeroline.corner.html \
-#	test_2d.line.miter.within.html \
-#	$(NULL)
+_TEST_FILES_3 += \
+	test_2d.line.join.parallel.html \
+	test_2d.strokeRect.zero.5.html \
+	$(NULL)
 
 # This is an issue with Quartz's handling of radial gradients and some numeric
 # imprecision that results in errors here.
-_TEST_FILES_D += test_2d.gradient.radial.inside3.html
+_TEST_FILES_2 += \
+	test_2d.gradient.radial.inside2.html \
+	test_2d.gradient.radial.inside3.html \
+	test_2d.gradient.radial.outside1.html \
+	$(NULL)
+
+_TEST_FILES_3 += \
+	test_2d.gradient.radial.cone.front.html \
+	test_2d.gradient.radial.cone.top.html \
+	$(NULL)
 
 # This is another Quartz bug -- closed paths that don't lie fully within the
 # destination bounds seem to have problems with the BEVEL/SQUARE join/cap combo.
 # The joins are rendered as if with MITER; the correct behaviour is also seen
 # if BUTT is used instead of SQUARE.
-_TEST_FILES_D += test_2d.line.cap.closed.html
+_TEST_FILES_4 += test_2d.line.cap.closed.html
 
-# test_2d.line.cap.zerobezier.round.html disabled for now, from above
 endif
 
 # Tests that fail on non-Mac (bug 407107)
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
-_TEST_FILES_E += \
-	test_2d.path.rect.selfintersect.html \
+
+# still need bug numbers
+_TEST_FILES_1 += \
+	test_2d.composite.uncovered.fill.source-in.html \
+	test_2d.composite.uncovered.fill.destination-in.html \
+	test_2d.composite.uncovered.fill.source-out.html \
+	test_2d.composite.uncovered.fill.destination-atop.html \
+	test_2d.composite.uncovered.pattern.source-in.html \
+	test_2d.composite.uncovered.pattern.destination-in.html \
+	test_2d.composite.uncovered.pattern.source-out.html \
+	test_2d.composite.uncovered.pattern.destination-atop.html \
 	$(NULL)
+
+# still need bug numbers
+_TEST_FILES_3 += \
+	test_2d.gradient.radial.outside2.html \
+	test_2d.gradient.radial.outside3.html \
+	test_2d.gradient.radial.touch1.html \
+	test_2d.gradient.radial.touch2.html \
+	test_2d.gradient.radial.touch3.html \
+	test_2d.gradient.radial.equal.html \
+	test_2d.gradient.radial.cone.shape2.html \
+	test_2d.gradient.radial.cone.behind.html \
+	test_2d.gradient.radial.cone.beside.html \
+	$(NULL)
+
+# still need bug numbers
+_TEST_FILES_4 += test_2d.path.arc.shape.3.html
+
+_TEST_FILES_5 += test_2d.path.rect.selfintersect.html
 endif
 
 # This test is bogus according to the spec; see bug 407107
 # test_2d.path.rect.zero.6.html
 
 # split up into groups to work around command-line length limits
-libs:: $(_TEST_FILES_A)
+libs:: $(_TEST_FILES_0)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
-libs:: $(_TEST_FILES_B)
+libs:: $(_TEST_FILES_1)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+libs:: $(_TEST_FILES_2)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
-libs:: $(_TEST_FILES_C)
+libs:: $(_TEST_FILES_3)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
+libs:: $(_TEST_FILES_4)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
-libs:: $(_TEST_FILES_D)
+libs:: $(_TEST_FILES_5)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
-libs:: $(_TEST_FILES_E)
+libs:: $(_TEST_FILES_6)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..45263e0afba7b708417510df24cadf70d82d9116
GIT binary patch
literal 241
zc${<hbhEHbOkpr$_`txx@E?d76o0ZXFoNj++<vYh!Oo5Wu10zW%pf5hkUU5+1Cwt{
z|H{*E`4`XGa;tmuy*<DA+a7sLd)B$^)v0aoxQ~DGx&E#9`LA=||MBy1wI5mZvBO7e
u`k7^)IeWd9Us?6F>ulEcJL|r4^K~D8vgv1zHpEf^btD@az;2<sJ=Oq7Zf$q~
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..925e2efc9a97ade490f04d57271adc10b2fe69b6
GIT binary patch
literal 460
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*!3HE(nbz$CQXGlNAwEEw35Xd!_f9SVQc`IU
zF$S0h1{h#ue!<AdlH<k+WKZ{WaSW-L^Y)w}FVL6+27hL^RdXHNc*P;zZ2gPI3341S
z2ZA`j$fEOFd$OSQ6eN!@qI*PL0OXMyX6lJR&V;lS#}H5u06lYYAuof0z>y8N>tDW?
y;59JlpK`aX<V`t4+Y(8kWRD(2!?q(5v}W*E9(=9Mn=k1Na;c}QpUXO@geCx54v$#?
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6941207373e513cfe10729077f59d369c59e6046
GIT binary patch
literal 422
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*!3HE(nbz$CQXGlNAwEEw5r`SK=)PP4q^5hi
zIEGZrd3(-~7pUNX!JpY})m+CmUU5h_TmPbQf*i-ofglbrvgo|lo-AlR1?WVnG>Eeq
zV18nNfnUro7#XcQ)Lnt>327;gAt28IJ#%p(FN1-=kqx)&U%r>%H8AL(a<{DHO*uo`
m5=o(Cj~+$Cwj&a>X7E=Ye64+b=gDaxhkCmDxvX<aXaWFlH;v)|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7f6351565473f4b8db1fa69530700491f7c88a54
GIT binary patch
literal 120
zc%17D@N?(olHy`uVBq!ia0y~yU}OMcMrI(Dw#P~pNU;U@gt#*N2SSF6v%S^<MRYw~
z978hhy*;&&mw|zUdBMN`TjpIjxZ|MDvJM4~CKx(o2vo{o6K${h;gSC5>uw;Pr>mdK
II;Vst0P+qZp#T5?
--- a/content/canvas/test/test_2d.canvas.readonly.html
+++ b/content/canvas/test/test_2d.canvas.readonly.html
@@ -1,25 +1,27 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.canvas.readonly</title>
+<!-- Testing: CanvasRenderingContext2D.canvas is readonly -->
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
 
 var canvas = document.getElementById('c');
 var ctx = canvas.getContext('2d');
 
 var c = document.createElement('canvas');
 var d = ctx.canvas;
-try { ctx.canvas = c; } catch (e) {} // not specified whether this throws, I think
+ok(c !== d, "c !== d");
+try { ctx.canvas = c; } catch (e) {} // not sure whether this should throw or not...
 ok(ctx.canvas === d, "ctx.canvas === d");
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.canvas.reference.html
+++ b/content/canvas/test/test_2d.canvas.reference.html
@@ -1,22 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.canvas.reference</title>
+<!-- Testing: CanvasRenderingContext2D.canvas refers back to its canvas -->
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
 
 var canvas = document.getElementById('c');
 var ctx = canvas.getContext('2d');
 
 ok(ctx.canvas === canvas, "ctx.canvas === canvas");
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.basic.html
+++ b/content/canvas/test/test_2d.clearRect.basic.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.basic</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -26,12 +25,13 @@ MochiKit.DOM.addLoadEvent(function () {
 var canvas = document.getElementById('c');
 var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.clearRect(0, 0, 100, 50);
 isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.clip.html
+++ b/content/canvas/test/test_2d.clearRect.clip.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.clip</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -35,12 +34,13 @@ ctx.clip();
 
 ctx.clearRect(0, 0, 100, 50);
 
 ctx.fillStyle = '#0f0';
 ctx.fillRect(0, 0, 16, 16);
 
 isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.globalalpha.html
+++ b/content/canvas/test/test_2d.clearRect.globalalpha.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.globalalpha</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -27,12 +26,13 @@ var canvas = document.getElementById('c'
 var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.globalAlpha = 0.1;
 ctx.clearRect(0, 0, 100, 50);
 isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.globalcomposite.html
+++ b/content/canvas/test/test_2d.clearRect.globalcomposite.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.globalcomposite</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -27,12 +26,13 @@ var canvas = document.getElementById('c'
 var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.globalCompositeOperation = 'destination-atop';
 ctx.clearRect(0, 0, 100, 50);
 isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.negative.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.negative</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 50, 25);
+ctx.clearRect(100, 0, -50, 25);
+ctx.clearRect(0, 50, 50, -25);
+ctx.clearRect(100, 50, -50, -25);
+isPixel(ctx, 25,12, 0,0,0,0, "25,12", "0,0,0,0", 0);
+isPixel(ctx, 75,12, 0,0,0,0, "75,12", "0,0,0,0", 0);
+isPixel(ctx, 25,37, 0,0,0,0, "25,37", "0,0,0,0", 0);
+isPixel(ctx, 75,37, 0,0,0,0, "75,37", "0,0,0,0", 0);
+
+SimpleTest.finish();
+
+});
+</script>
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.clearRect.nonfinite.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.clearRect.nonfinite</title>
+<!-- Testing: clearRect() with Infinity/NaN is ignored -->
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+var _thrown_outer = false;
+try {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.clearRect(Infinity, 0, 100, 50);
+ctx.clearRect(-Infinity, 0, 100, 50);
+ctx.clearRect(NaN, 0, 100, 50);
+ctx.clearRect(0, Infinity, 100, 50);
+ctx.clearRect(0, -Infinity, 100, 50);
+ctx.clearRect(0, NaN, 100, 50);
+ctx.clearRect(0, 0, Infinity, 50);
+ctx.clearRect(0, 0, -Infinity, 50);
+ctx.clearRect(0, 0, NaN, 50);
+ctx.clearRect(0, 0, 100, Infinity);
+ctx.clearRect(0, 0, 100, -Infinity);
+ctx.clearRect(0, 0, 100, NaN);
+ctx.clearRect(Infinity, Infinity, 100, 50);
+ctx.clearRect(Infinity, Infinity, Infinity, 50);
+ctx.clearRect(Infinity, Infinity, Infinity, Infinity);
+ctx.clearRect(Infinity, Infinity, 100, Infinity);
+ctx.clearRect(Infinity, 0, Infinity, 50);
+ctx.clearRect(Infinity, 0, Infinity, Infinity);
+ctx.clearRect(Infinity, 0, 100, Infinity);
+ctx.clearRect(0, Infinity, Infinity, 50);
+ctx.clearRect(0, Infinity, Infinity, Infinity);
+ctx.clearRect(0, Infinity, 100, Infinity);
+ctx.clearRect(0, 0, Infinity, Infinity);
+
+isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
+
+} catch (e) {
+    _thrown_outer = true;
+}
+todo(!_thrown_outer, 'should not throw exception');
+
+SimpleTest.finish();
+
+});
+</script>
+
--- a/content/canvas/test/test_2d.clearRect.path.html
+++ b/content/canvas/test/test_2d.clearRect.path.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.path</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -28,12 +27,13 @@ var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#0f0';
 ctx.beginPath();
 ctx.rect(0, 0, 100, 50);
 ctx.clearRect(0, 0, 16, 16);
 ctx.fill();
 isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.shadow.html
+++ b/content/canvas/test/test_2d.clearRect.shadow.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.shadow</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -30,12 +29,13 @@ ctx.fillStyle = '#0f0';
 ctx.fillRect(0, 0, 100, 50);
 ctx.shadowColor = '#f00';
 ctx.shadowBlur = 0;
 ctx.shadowOffsetX = 0;
 ctx.shadowOffsetY = 50;
 ctx.clearRect(0, -50, 100, 50);
 isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.transform.html
+++ b/content/canvas/test/test_2d.clearRect.transform.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.transform</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #0f0"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -28,12 +27,13 @@ var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#f00';
 ctx.fillRect(0, 0, 100, 50);
 ctx.scale(10, 10);
 ctx.translate(0, 5);
 ctx.clearRect(0, -5, 10, 5);
 isPixel(ctx, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
--- a/content/canvas/test/test_2d.clearRect.zero.html
+++ b/content/canvas/test/test_2d.clearRect.zero.html
@@ -1,24 +1,23 @@
 <!DOCTYPE HTML>
 <title>Canvas test: 2d.clearRect.zero</title>
 <script src="/MochiKit/MochiKit.js"></script>
 <script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
 <body>
 <canvas id="c" width="100" height="50" style="background: #f00"><p class="fallback">FAIL (fallback content)</p></canvas>
 <script>
-var _deferred = false;
-function isPixel(ctx, x,y, r,g,b,a, pos, colour, d, f) {
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
     var pixel = ctx.getImageData(x, y, 1, 1);
     var pr = pixel.data[0],
         pg = pixel.data[1],
         pb = pixel.data[2],
         pa = pixel.data[3];
-    (f || ok)(r-d <= pr && pr <= r+d &&
+    ok(r-d <= pr && pr <= r+d &&
        g-d <= pg && pg <= g+d &&
        b-d <= pb && pb <= b+d &&
        a-d <= pa && pa <= a+d,
        "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
 }
 
 SimpleTest.waitForExplicitFinish();
 MochiKit.DOM.addLoadEvent(function () {
@@ -28,12 +27,13 @@ var ctx = canvas.getContext('2d');
 
 ctx.fillStyle = '#0f0';
 ctx.fillRect(0, 0, 100, 50);
 ctx.clearRect(0, 0, 100, 0);
 ctx.clearRect(0, 0, 0, 50);
 ctx.clearRect(0, 0, 0, 0);
 isPixel(ctx, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 0);
 
-if (!_deferred) SimpleTest.finish();
+SimpleTest.finish();
+
 });
 </script>
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.canvas.copy.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.canvas.copy</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.drawImage(canvas2, 0, 0);
+isPixel(ctx, 50,25, 255,255,0,191, "50,25", "255,255,0,191", 5);
+
+SimpleTest.finish();
+
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.canvas.destination-atop.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.canvas.destination-atop</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&
+       b-d <= pb && pb <= b+d &&
+       a-d <= pa && pa <= a+d,
+       "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+}
+
+SimpleTest.waitForExplicitFinish();
+MochiKit.DOM.addLoadEvent(function () {
+
+var canvas = document.getElementById('c');
+var ctx = canvas.getContext('2d');
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.drawImage(canvas2, 0, 0);
+isPixel(ctx, 50,25, 127,255,127,191, "50,25", "127,255,127,191", 5);
+
+SimpleTest.finish();
+
+});
+</script>
+<img src="image_yellow75.png" id="yellow75.png" class="resource">
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_2d.composite.canvas.destination-in.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Canvas test: 2d.composite.canvas.destination-in</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<script>
+function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+    var pixel = ctx.getImageData(x, y, 1, 1);
+    var pr = pixel.data[0],
+        pg = pixel.data[1],
+        pb = pixel.data[2],
+        pa = pixel.data[3];
+    ok(r-d <= pr && pr <= r+d &&
+       g-d <= pg && pg <= g+d &&