Merge mozilla-inbound into mozilla-central
authorEhsan Akhgari <ehsan@mozilla.com>
Thu, 09 Jun 2011 18:30:11 -0400
changeset 70849 974c34e96293
parent 70838 da8f7ac2a16d (current diff)
parent 70848 a19e5f55f67c (diff)
child 70850 21d7ea8200eb
push id20429
push usermlamouri@mozilla.com
push date2011-06-10 07:58 +0000
treeherdermozilla-central@1e3af440ce23 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound into mozilla-central
mobile/app/mobile.js
--- a/gfx/cairo/cairo/src/cairo-d2d-private.h
+++ b/gfx/cairo/cairo/src/cairo-d2d-private.h
@@ -44,16 +44,17 @@
 #include <dxgi.h>
 
 #include "cairoint.h"
 #include "cairo-surface-clipper-private.h"
 
 #include "cairo-win32-refptr.h"
 #include "cairo-d2d-private-fx.h"
 #include "cairo-win32.h"
+#include "cairo-list-private.h"
 
 /* describes the type of the currently applied clip so that we can pop it */
 struct d2d_clip;
 
 #define MAX_OPERATORS CAIRO_OPERATOR_HSL_LUMINOSITY + 1
 
 struct _cairo_d2d_device
 {
@@ -76,17 +77,21 @@ const unsigned int TEXT_TEXTURE_WIDTH = 
 const unsigned int TEXT_TEXTURE_HEIGHT = 512;
 typedef struct _cairo_d2d_device cairo_d2d_device_t;
 
 struct _cairo_d2d_surface {
     _cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
             textRenderingState(TEXT_RENDERING_UNINITIALIZED)
     {
 	_cairo_clip_init (&this->clip);
+        cairo_list_init(&this->dependent_surfaces);
     }
+    
+    ~_cairo_d2d_surface();
+
 
     cairo_surface_t base;
     /* Device used by this surface 
      * NOTE: In upstream cairo this is in the surface base class */
     cairo_d2d_device_t *device;
 
     /** Render target of the texture we render to */
     RefPtr<ID2D1RenderTarget> rt;
@@ -134,21 +139,33 @@ struct _cairo_d2d_surface {
         TEXT_RENDERING_NORMAL,
         TEXT_RENDERING_GDI_CLASSIC
     };
     TextRenderingState textRenderingState;
 
     RefPtr<ID3D10RenderTargetView> buffer_rt_view;
     RefPtr<ID3D10ShaderResourceView> buffer_sr_view;
 
-
+    // Other d2d surfaces which depend on this one and need to be flushed if
+    // it is drawn to. This is required for situations where this surface is
+    // drawn to another surface, but may be modified before the other surface
+    // has flushed. When the flush of the other surface then happens and the
+    // drawing command is actually executed, the contents of this surface will
+    // no longer be what it was when the drawing command was issued.
+    cairo_list_t dependent_surfaces;
     //cairo_surface_clipper_t clipper;
 };
 typedef struct _cairo_d2d_surface cairo_d2d_surface_t;
 
+struct _cairo_d2d_surface_entry
+{
+    cairo_list_t link;
+    cairo_d2d_surface_t *surface;
+};
+
 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
     __in D2D1_FACTORY_TYPE factoryType,
     __in REFIID iid,
     __in_opt CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
     __out void **factory
 );
 
 typedef HRESULT (WINAPI*D3D10CreateDevice1Func)(
--- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
@@ -1048,25 +1048,45 @@ static cairo_status_t
 
     /* push the new clip paths up to current_clip_path */
     if (current_clip_path != clip->path)
 	return clipper_intersect_clip_path_recursive (d2dsurf, current_clip_path, clip->path);
     else
 	return CAIRO_STATUS_SUCCESS;
 }
 
+static void _cairo_d2d_add_dependent_surface(cairo_d2d_surface_t *surf, cairo_d2d_surface_t *user)
+{
+    _cairo_d2d_surface_entry *entry = new _cairo_d2d_surface_entry;
+    entry->surface = user;
+    cairo_surface_reference(&user->base);
+    cairo_list_add(&entry->link, &surf->dependent_surfaces);
+};
+
+static void _cairo_d2d_flush_dependent_surfaces(cairo_d2d_surface_t *surf)
+{
+    _cairo_d2d_surface_entry *entry, *next;
+    cairo_list_foreach_entry_safe(entry, next, _cairo_d2d_surface_entry, &surf->dependent_surfaces, link) {
+	_cairo_d2d_flush(entry->surface);
+	cairo_surface_destroy(&entry->surface->base);
+	delete entry;
+    }
+    cairo_list_init(&surf->dependent_surfaces);
+}
+
 /**
  * Enter the state where the surface is ready for drawing. This will guarantee
  * the surface is in the correct state, and the correct clipping area is pushed.
  *
  * \param surface D2D surface
  */
 static void _begin_draw_state(cairo_d2d_surface_t* surface)
 {
     if (!surface->isDrawing) {
+	_cairo_d2d_flush_dependent_surfaces(surface);
 	surface->rt->BeginDraw();
 	surface->isDrawing = true;
     }
 }
 
 /**
  * Get a D2D matrix from a cairo matrix. Note that D2D uses row vectors where cairo
  * uses column vectors. Hence the transposition.
@@ -1773,16 +1793,19 @@ static RefPtr<ID2D1Brush>
 		 * fairly efficient here, for now, fallback.
 		 */
 		return NULL;
 	    }
 
 	    _cairo_d2d_update_surface_bitmap(srcSurf);
 	    _cairo_d2d_flush(srcSurf);
 
+	    // Mark a dependency on the source surface.
+	    _cairo_d2d_add_dependent_surface(srcSurf, d2dsurf);
+
 	    if (pattern->extend == CAIRO_EXTEND_NONE) {
 		ID2D1Bitmap *srcSurfBitmap = srcSurf->surfaceBitmap;
 		d2dsurf->rt->CreateBitmap(
 		    D2D1::SizeU(srcSurfBitmap->GetPixelSize().width + 2,
 				srcSurfBitmap->GetPixelSize().height + 2),
 		    D2D1::BitmapProperties(srcSurfBitmap->GetPixelFormat()),
 		    &sourceBitmap);
 		D2D1_POINT_2U point = D2D1::Point2U(1, 1);
@@ -2322,16 +2345,28 @@ void
 _cairo_d2d_surface_init(cairo_d2d_surface_t *newSurf, cairo_d2d_device_t *d2d_device, cairo_format_t format)
 {
     newSurf->format = format;
 
     newSurf->device = d2d_device;
     cairo_addref_device(&d2d_device->base);
     d2d_device->mVRAMUsage += _cairo_d2d_compute_surface_mem_size(newSurf);
 }
+    
+_cairo_d2d_surface::~_cairo_d2d_surface()
+{
+    _cairo_d2d_surface_entry *entry, *next;
+    cairo_list_foreach_entry_safe(entry, next, _cairo_d2d_surface_entry, &dependent_surfaces, link) {
+	// We do not need to flush, the contents of our texture has not changed,
+	// our users have their own reference and can just use it later.
+	cairo_surface_destroy(&entry->surface->base);
+	delete entry;
+    }
+
+}
 
 // Implementation
 static cairo_surface_t*
 _cairo_d2d_create_similar(void			*surface,
 			  cairo_content_t	 content,
 			  int			 width,
 			  int			 height)
 {
@@ -2788,16 +2823,18 @@ static cairo_int_status_t
     }
     if (rectSrc.top > rectSrc.bottom) {
 	rectDst.top = -rectDst.top;
 	rectDst.bottom = -rectDst.bottom;
 	matrix._22 = -1.0;
 	needsTransform = true;
     }
 
+    _cairo_d2d_add_dependent_surface(src, dst);
+
     D2D1_BITMAP_INTERPOLATION_MODE interpMode =
       D2D1_BITMAP_INTERPOLATION_MODE_LINEAR;
 
     if (needsTransform) {
 	dst->rt->SetTransform(matrix);
     }
 
     if (filter == CAIRO_FILTER_NEAREST) {
@@ -2981,16 +3018,18 @@ static RefPtr<ID2D1RenderTarget>
 	}
     }
     return new_rt;
 }
 
 static cairo_int_status_t
 _cairo_d2d_blend_temp_surface(cairo_d2d_surface_t *surf, cairo_operator_t op, ID2D1RenderTarget *rt, cairo_clip_t *clip, const cairo_rectangle_int_t *bounds = NULL)
 {
+    _cairo_d2d_flush_dependent_surfaces(surf);
+
     int numPaths = 0;
     if (clip) {
 	cairo_clip_path_t *path = clip->path;
 	while (path) {
 	    numPaths++;
 	    path = path->prev;
 	}
 	
@@ -3585,16 +3624,20 @@ cairo_int_status_t
     // aligned quads.
     if (clip) {
 	_cairo_clip_get_region(clip, &clip_region);
 	if (!clip_region) {
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
     }
 
+    if (!dst->isDrawing) {
+	_cairo_d2d_flush_dependent_surfaces(dst);
+    }
+
     _cairo_d2d_set_clip(dst, NULL);
     dst->rt->Flush();
 
     DWRITE_GLYPH_RUN run;
     _cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, scaled_font, &run, &transform);
 
     RefPtr<IDWriteGlyphRunAnalysis> analysis;
     DWRITE_MATRIX dwmat = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
--- a/mobile/app/mobile.js
+++ b/mobile/app/mobile.js
@@ -642,12 +642,12 @@ pref("urlclassifier.confirm-age", 2700);
 pref("urlclassifier.updatecachemax", 4194304);
 
 // URL for checking the reason for a malware warning.
 pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
 #endif
 
 // True if this is the first time we are showing about:firstrun
 pref("browser.firstrun.show.uidiscovery", true);
-pref("browser.firstrun.show.localepicker", false);
+pref("browser.firstrun.show.localepicker", true);
 
 // initiated by a user
 pref("content.ime.strict_policy", true);
--- a/mobile/chrome/content/Util.js
+++ b/mobile/chrome/content/Util.js
@@ -157,17 +157,17 @@ let Util = {
   },
 
   isParentProcess: function isInParentProcess() {
     let appInfo = Cc["@mozilla.org/xre/app-info;1"];
     return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
   },
 
   isTablet: function isTablet() {
-    let dpi = Util.getWindowUtils(window).displayDPI;
+    let dpi = this.displayDPI;
     if (dpi <= 96)
       return (window.innerWidth > 1024);
 
     // See the tablet_panel_minwidth from mobile/themes/core/defines.inc
     let tablet_panel_minwidth = 124;
     let dpmm = 25.4 * window.innerWidth / dpi;
     return (dpmm >= tablet_panel_minwidth);
   },
@@ -183,16 +183,22 @@ let Util = {
   },
 
   get isKeyboardOpened() {
     let isChromeWindow = this.isParentProcess() && window["ViewableAreaObserver"];
     if (isChromeWindow)
       return ViewableAreaObserver.isKeyboardOpened;
 
     return (sendSyncMessage("Content:IsKeyboardOpened", {}))[0];
+  },
+
+  // because this uses the global window, will only work in the parent process
+  get displayDPI() function() {
+    delete this.displayDPI;
+    return this.displayDPI = this.getWindowUtils(window).displayDPI;
   }
 };
 
 
 /**
  * Helper class to nsITimer that adds a little more pizazz.  Callback can be an
  * object with a notify method or a function.
  */
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -359,17 +359,17 @@ var BrowserUI = {
   _isKeyboardFullscreen: function _isKeyboardFullscreen() {
 #ifdef ANDROID
     if (!Util.isPortrait()) {
       switch (Services.prefs.getIntPref("widget.ime.android.landscape_fullscreen")) {
         case 1:
           return true;
         case -1: {
           let threshold = Services.prefs.getIntPref("widget.ime.android.fullscreen_threshold");
-          let dpi = Util.getWindowUtils(window).displayDPI;
+          let dpi = Util.displayDPI;
           return (window.innerHeight * 100 < threshold * dpi);
         }
       }
     }
 #endif
     return false;
   },
 
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1107,17 +1107,17 @@ var Browser = {
 
   // The device-pixel-to-CSS-px ratio used to adjust meta viewport values.
   // This is higher on higher-dpi displays, so pages stay about the same physical size.
   getScaleRatio: function getScaleRatio() {
     let prefValue = Services.prefs.getIntPref("browser.viewport.scaleRatio");
     if (prefValue > 0)
       return prefValue / 100;
 
-    let dpi = this.windowUtils.displayDPI;
+    let dpi = Utils.displayDPI;
     if (dpi < 200) // Includes desktop displays, and LDPI and MDPI Android devices
       return 1;
     else if (dpi < 300) // Includes Nokia N900, and HDPI Android devices
       return 1.5;
 
     // For very high-density displays like the iPhone 4, calculate an integer ratio.
     return Math.floor(dpi / 150);
   },
@@ -1804,17 +1804,17 @@ const ContentTouchHandler = {
   },
 
   touchTimeout: null,
   canCancelPan: false,
   clickPrevented: false,
   panningPrevented: false,
 
   updateCanCancel: function(aX, aY) {
-    let dpi = Browser.windowUtils.displayDPI;
+    let dpi = Utils.displayDPI;
 
     const kSafetyX = Services.prefs.getIntPref("dom.w3c_touch_events.safetyX") / 240 * dpi;
     const kSafetyY = Services.prefs.getIntPref("dom.w3c_touch_events.safetyY") / 240 * dpi;
     let browser = getBrowser();
     let bcr = browser.getBoundingClientRect();
     let rect = new Rect(0, 0, window.innerWidth, window.innerHeight);
     rect.restrictTo(Rect.fromRect(bcr));
 
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -63,17 +63,21 @@ const ElementTouchHelper = {
   get weight() {
     delete this.weight;
     return this.weight = { "visited": Services.prefs.getIntPref("browser.ui.touch.weight.visited")
                          };
   },
 
   /* Retrieve the closest element to a point by looking at borders position */
   getClosest: function getClosest(aWindowUtils, aX, aY) {
-    let dpiRatio = aWindowUtils.displayDPI / kReferenceDpi;
+    // cached for the child process, since Utils.displayDPI is only available in the parent
+    if (!this.dpiRatio)
+      this.dpiRatio = aWindowUtils.displayDPI / kReferenceDpi;
+
+    let dpiRatio = this.dpiRatio;
 
     let target = aWindowUtils.elementFromPoint(aX, aY,
                                                true,   /* ignore root scroll frame*/
                                                false); /* don't flush layout */
 
     // return early if the click is just over a clickable element
     if (this._isElementClickable(target))
       return target;
--- a/mobile/chrome/content/input.js
+++ b/mobile/chrome/content/input.js
@@ -113,17 +113,17 @@ function MouseModule() {
 
   this._kinetic = new KineticController(this._dragBy.bind(this),
                                         this._kineticStop.bind(this));
 
   this._singleClickTimeout = new Util.Timeout(this._doSingleClick.bind(this));
   this._mouseOverTimeout = new Util.Timeout(this._doMouseOver.bind(this));
   this._longClickTimeout = new Util.Timeout(this._doLongClick.bind(this));
 
-  this._doubleClickRadius = Util.getWindowUtils(window).displayDPI * kDoubleClickRadius;
+  this._doubleClickRadius = Util.displayDPI * kDoubleClickRadius;
 
   window.addEventListener("mousedown", this, true);
   window.addEventListener("mouseup", this, true);
   window.addEventListener("mousemove", this, true);
   window.addEventListener("contextmenu", this, false);
   window.addEventListener("CancelTouchSequence", this, true);
 }
 
@@ -565,17 +565,17 @@ MouseModule.prototype = {
       + 'length=' + this._downUpEvents.length + ', '
       + '\n\ttargetScroller=' + this._targetScrollInterface + '}';
   }
 };
 
 var ScrollUtils = {
   // threshold in pixels for sensing a tap as opposed to a pan
   get tapRadius() {
-    let dpi = Util.getWindowUtils(window).displayDPI;
+    let dpi = Util.displayDPI;
 
     delete this.tapRadius;
     return this.tapRadius = Services.prefs.getIntPref("ui.dragThresholdX") / 240 * dpi;
   },
 
   /**
    * Walk up (parentward) the DOM tree from elem in search of a scrollable element.
    * Return the element and its scroll interface if one is found, two nulls otherwise.
@@ -681,17 +681,17 @@ var ScrollUtils = {
 };
 
 /**
  * DragData handles processing drags on the screen, handling both
  * locking of movement on one axis, and click detection.
  */
 function DragData() {
   this._domUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
-  this._lockRevertThreshold = Util.getWindowUtils(window).displayDPI * kAxisLockRevertThreshold;
+  this._lockRevertThreshold = Util.displayDPI * kAxisLockRevertThreshold;
   this.reset();
 };
 
 DragData.prototype = {
   reset: function reset() {
     this.dragging = false;
     this.sX = null;
     this.sY = null;
--- a/mobile/chrome/tests/browser_tabs.js
+++ b/mobile/chrome/tests/browser_tabs.js
@@ -143,17 +143,17 @@ function tab_undo() {
   checkExpectedSize();
   tab_on_undo();
 }
 
 function tab_on_undo() {
   let undoBox = document.getElementById("tabs")._tabsUndo;
   is(undoBox.firstChild, null, "It should be no tab in the undo box");
 
-  Browser.loadURI("about:firstrun");
+  Browser.loadURI("about:home");
   is(undoBox.firstChild, null, "It should be no tab in the undo box when opening a new local page");
 
   // loadURI will open a new tab so ensure new_tab_05 point to the newly opened tab
   new_tab_05 = Browser.selectedTab;
 
   let tabs = [new_tab_01, new_tab_02, new_tab_03, new_tab_04, new_tab_05];
   while (tabs.length)
     Browser.closeTab(tabs.shift(), { forceClose: true });
--- a/mobile/components/AboutRedirector.js
+++ b/mobile/components/AboutRedirector.js
@@ -115,22 +115,16 @@ AboutGeneric.prototype = {
 };
 
 function AboutEmpty() {}
 AboutEmpty.prototype = {
   __proto__: AboutGeneric.prototype,
   classID: Components.ID("{433d2d75-5923-49b0-854d-f37267b03dc7}")
 }
 
-function AboutFirstrun() {}
-AboutFirstrun.prototype = {
-  __proto__: AboutGeneric.prototype,
-  classID: Components.ID("{077ea23e-0f22-4168-a744-8e444b560197}")
-}
-
 function AboutFennec() {}
 AboutFennec.prototype = {
   __proto__: AboutGeneric.prototype,
   classID: Components.ID("{842a6d11-b369-4610-ba66-c3b5217e82be}")
 }
 
 function AboutFirefox() {}
 AboutFirefox.prototype = {
@@ -157,11 +151,11 @@ AboutHome.prototype = {
 }
 
 function AboutBlocked() {}
 AboutBlocked.prototype = {
   __proto__: AboutGeneric.prototype,
   classID: Components.ID("{88fd40b6-c5c2-4120-9238-f2cb9ff98928}")
 }
 
-const components = [AboutEmpty, AboutFirstrun, AboutFennec, AboutRights,
+const components = [AboutEmpty, AboutFennec, AboutRights,
                     AboutCertError, AboutFirefox, AboutHome, AboutBlocked];
 const NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
--- a/mobile/components/MobileComponents.manifest
+++ b/mobile/components/MobileComponents.manifest
@@ -1,13 +1,11 @@
 # AboutRedirector.js
 component {433d2d75-5923-49b0-854d-f37267b03dc7} AboutRedirector.js
 contract @mozilla.org/network/protocol/about;1?what=empty {433d2d75-5923-49b0-854d-f37267b03dc7}
-component {077ea23e-0f22-4168-a744-8e444b560197} AboutRedirector.js
-contract @mozilla.org/network/protocol/about;1?what=firstrun {077ea23e-0f22-4168-a744-8e444b560197}
 component {842a6d11-b369-4610-ba66-c3b5217e82be} AboutRedirector.js
 contract @mozilla.org/network/protocol/about;1?what=fennec {842a6d11-b369-4610-ba66-c3b5217e82be}
 component {dd40c467-d206-4f22-9215-8fcc74c74e38} AboutRedirector.js
 contract @mozilla.org/network/protocol/about;1?what=firefox {dd40c467-d206-4f22-9215-8fcc74c74e38}
 component {3b988fbf-ec97-4e1c-a5e4-573d999edc9c} AboutRedirector.js
 contract @mozilla.org/network/protocol/about;1?what=rights {3b988fbf-ec97-4e1c-a5e4-573d999edc9c}
 component {972efe64-8ac0-4e91-bdb0-22835d987815} AboutRedirector.js
 contract @mozilla.org/network/protocol/about;1?what=certerror {972efe64-8ac0-4e91-bdb0-22835d987815}
--- a/mobile/locales/en-US/profile/bookmarks.inc
+++ b/mobile/locales/en-US/profile/bookmarks.inc
@@ -6,20 +6,16 @@
 
 # LOCALIZATION NOTE: Some of these URLs are currently 404s, but should be coming
 # online shortly.
 
 # LOCALIZATION NOTE (bookmarks_title):
 # title for the folder that will contains the default bookmarks
 #define bookmarks_title Mobile
 
-# LOCALIZATION NOTE (bookmarks_welcome):
-# link title for about:firstrun
-#define bookmarks_welcome Firefox: Welcome
-
 # LOCALIZATION NOTE (bookmarks_aboutBrowser):
 # link title for about:fennec
 #define bookmarks_aboutBrowser Firefox: About your browser
 
 # LOCALIZATION NOTE (bookmarks_addons):
 # link title for https://addons.mozilla.org/en-US/mobile
 #define bookmarks_addons Firefox: Customize with add-ons
 
--- a/mobile/locales/generic/profile/bookmarks.json.in
+++ b/mobile/locales/generic/profile/bookmarks.json.in
@@ -1,16 +1,13 @@
 #filter substitution
 {"type":"text/x-moz-place-container","root":"placesRoot","children":
   [{"type":"text/x-moz-place-container","title":"@bookmarks_title@","annos":[{"name":"mobile/bookmarksRoot","expires":4,"type":1,"value":1}],
     "children":
      [
-       {          "title":"@bookmarks_welcome@",  "type":"text/x-moz-place", "uri":"about:firstrun",
-        "iconUri":"chrome://branding/content/favicon32.png"
-       },
        {"index":1,"title":"@bookmarks_aboutBrowser@", "type":"text/x-moz-place", "uri":"about:firefox",
         "iconUri":"chrome://branding/content/favicon32.png"
        },
        {"index":2,"title":"@bookmarks_addons@",   "type":"text/x-moz-place", "uri":"https://addons.mozilla.org/@AB_CD@/mobile/",
         "icon":"data:image/png;base64,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"
        },
        {"index":3,"title":"@bookmarks_support@",  "type":"text/x-moz-place", "uri":"http://support.mozilla.com/@AB_CD@/mobile",
         "icon":"data:image/png;base64,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"
--- a/modules/libpr0n/src/imgRequest.cpp
+++ b/modules/libpr0n/src/imgRequest.cpp
@@ -221,16 +221,18 @@ nsresult imgRequest::Init(nsIURI *aURI,
   mProperties = do_CreateInstance("@mozilla.org/properties;1");
 
   mStatusTracker = new imgStatusTracker(nsnull);
 
   mURI = aURI;
   mKeyURI = aKeyURI;
   mRequest = aRequest;
   mChannel = aChannel;
+  mTimedChannel = do_QueryInterface(mChannel);
+
   mChannel->GetNotificationCallbacks(getter_AddRefs(mPrevChannelSink));
 
   NS_ASSERTION(mPrevChannelSink != this,
                "Initializing with a channel that already calls back to us!");
 
   mChannel->SetNotificationCallbacks(this);
 
   mCacheEntry = aCacheEntry;
@@ -951,16 +953,17 @@ NS_IMETHODIMP imgRequest::OnStopRequest(
   }
 
   /* notify the kids */
   nsTObserverArray<imgRequestProxy*>::ForwardIterator srIter(mObservers);
   while (srIter.HasMore()) {
     statusTracker.SendStopRequest(srIter.GetNext(), lastPart, status);
   }
 
+  mTimedChannel = nsnull;
   return NS_OK;
 }
 
 /* prototype for these defined below */
 static NS_METHOD sniff_mimetype_callback(nsIInputStream* in, void* closure, const char* fromRawSegment,
                                          PRUint32 toOffset, PRUint32 count, PRUint32 *writeCount);
 
 /** nsIStreamListener methods **/
@@ -1272,16 +1275,17 @@ imgRequest::OnRedirectVerifyCallback(nsr
   if (NS_FAILED(result)) {
       mRedirectCallback->OnRedirectVerifyCallback(result);
       mRedirectCallback = nsnull;
       mNewRedirectChannel = nsnull;
       return NS_OK;
   }
 
   mChannel = mNewRedirectChannel;
+  mTimedChannel = do_QueryInterface(mChannel);
   mNewRedirectChannel = nsnull;
 
   // Don't make any cache changes if we're going to point to the same thing. We
   // compare specs and not just URIs here because URIs that compare as
   // .Equals() might have different hashes.
   nsCAutoString oldspec;
   if (mKeyURI)
     mKeyURI->GetSpec(oldspec);
--- a/modules/libpr0n/src/imgRequest.h
+++ b/modules/libpr0n/src/imgRequest.h
@@ -46,16 +46,17 @@
 #include "nsIChannelEventSink.h"
 #include "nsIContentSniffer.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIRequest.h"
 #include "nsIProperties.h"
 #include "nsIStreamListener.h"
 #include "nsIURI.h"
 #include "nsIPrincipal.h"
+#include "nsITimedChannel.h"
 
 #include "nsCategoryCache.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTObserverArray.h"
 #include "nsWeakReference.h"
 #include "ImageErrors.h"
 #include "imgIRequest.h"
@@ -214,16 +215,18 @@ private:
   nsRefPtr<mozilla::imagelib::Image> mImage;
   nsCOMPtr<nsIProperties> mProperties;
   nsCOMPtr<nsISupports> mSecurityInfo;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
 
   nsTObserverArray<imgRequestProxy*> mObservers;
 
+  nsCOMPtr<nsITimedChannel> mTimedChannel;
+
   nsCString mContentType;
 
   nsRefPtr<imgCacheEntry> mCacheEntry; /* we hold on to this to this so long as we have observers */
 
   void *mCacheId;
 
   void *mLoadId;
   PRTime mLoadTime;
--- a/modules/libpr0n/src/imgRequestProxy.cpp
+++ b/modules/libpr0n/src/imgRequestProxy.cpp
@@ -52,18 +52,27 @@
 #include "Image.h"
 #include "ImageErrors.h"
 #include "ImageLogging.h"
 
 #include "nspr.h"
 
 using namespace mozilla::imagelib;
 
-NS_IMPL_ISUPPORTS4(imgRequestProxy, imgIRequest, nsIRequest,
-                   nsISupportsPriority, nsISecurityInfoProvider)
+NS_IMPL_ADDREF(imgRequestProxy)
+NS_IMPL_RELEASE(imgRequestProxy)
+
+NS_INTERFACE_MAP_BEGIN(imgRequestProxy)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, imgIRequest)
+  NS_INTERFACE_MAP_ENTRY(imgIRequest)
+  NS_INTERFACE_MAP_ENTRY(nsIRequest)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
+  NS_INTERFACE_MAP_ENTRY(nsISecurityInfoProvider)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITimedChannel, TimedChannel() != nsnull)
+NS_INTERFACE_MAP_END
 
 imgRequestProxy::imgRequestProxy() :
   mOwner(nsnull),
   mURI(nsnull),
   mImage(nsnull),
   mPrincipal(nsnull),
   mListener(nsnull),
   mLoadFlags(nsIRequest::LOAD_NORMAL),
--- a/modules/libpr0n/src/imgRequestProxy.h
+++ b/modules/libpr0n/src/imgRequestProxy.h
@@ -43,16 +43,17 @@
 #include "imgIRequest.h"
 #include "imgIDecoderObserver.h"
 #include "nsISecurityInfoProvider.h"
 
 #include "nsIRequestObserver.h"
 #include "nsIChannel.h"
 #include "nsILoadGroup.h"
 #include "nsISupportsPriority.h"
+#include "nsITimedChannel.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 
 #include "imgRequest.h"
 
 #define NS_IMGREQUESTPROXY_CID \
 { /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */         \
@@ -66,24 +67,28 @@ class imgRequestNotifyRunnable;
 class imgStatusNotifyRunnable;
 
 namespace mozilla {
 namespace imagelib {
 class Image;
 } // namespace imagelib
 } // namespace mozilla
 
-class imgRequestProxy : public imgIRequest, public nsISupportsPriority, public nsISecurityInfoProvider
+class imgRequestProxy : public imgIRequest, 
+                        public nsISupportsPriority, 
+                        public nsISecurityInfoProvider,
+                        public nsITimedChannel
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGIREQUEST
   NS_DECL_NSIREQUEST
   NS_DECL_NSISUPPORTSPRIORITY
   NS_DECL_NSISECURITYINFOPROVIDER
+  // nsITimedChannel declared below
 
   imgRequestProxy();
   virtual ~imgRequestProxy();
 
   // Callers to Init or ChangeOwner are required to call NotifyListener after
   // (although not immediately after) doing so.
   nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup,
                 mozilla::imagelib::Image* aImage,
@@ -191,16 +196,26 @@ protected:
   }
 
   // Return the imgStatusTracker associated with mOwner and/or mImage. It may
   // live either on mOwner or mImage, depending on whether
   //   (a) we have an mOwner at all
   //   (b) whether mOwner has instantiated its image yet
   imgStatusTracker& GetStatusTracker();
 
+  nsITimedChannel* TimedChannel()
+  {
+    if (!mOwner)
+      return nsnull;
+    return mOwner->mTimedChannel;
+  }
+
+public:
+  NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel())
+
 private:
   friend class imgCacheValidator;
 
   // We maintain the following invariant:
   // The proxy is registered at most with a single imgRequest as an observer,
   // and whenever it is, mOwner points to that object. This helps ensure that
   // imgRequestProxy::~imgRequestProxy unregisters the proxy as an observer
   // from whatever request it was registered with (if any). This, in turn,
--- a/netwerk/ipc/NeckoMessageUtils.h
+++ b/netwerk/ipc/NeckoMessageUtils.h
@@ -339,16 +339,19 @@ struct ParamTraits<PRNetAddr>
     } else if (aParam.raw.family == PR_AF_INET6) {
       WriteParam(aMsg, aParam.ipv6.port);
       WriteParam(aMsg, aParam.ipv6.flowinfo);
       WriteParam(aMsg, aParam.ipv6.ip.pr_s6_addr64[0]);
       WriteParam(aMsg, aParam.ipv6.ip.pr_s6_addr64[1]);
       WriteParam(aMsg, aParam.ipv6.scope_id);
 #if defined(XP_UNIX) || defined(XP_OS2)
     } else if (aParam.raw.family == PR_AF_LOCAL) {
+      // Train's already off the rails:  let's get a stack trace at least...
+      NS_RUNTIMEABORT("Error: please post stack trace to "
+                      "https://bugzilla.mozilla.org/show_bug.cgi?id=661158");
       aMsg->WriteBytes(aParam.local.path, sizeof(aParam.local.path));
 #endif
     }
 
     /* If we get here without hitting any of the cases above, there's not much
      * we can do but let the deserializer fail when it gets this message */
   }
 
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -82,16 +82,20 @@ HttpBaseChannel::HttpBaseChannel()
   , mTracingEnabled(PR_TRUE)
   , mTimingEnabled(PR_FALSE)
   , mRedirectedCachekeys(nsnull)
 {
   LOG(("Creating HttpBaseChannel @%x\n", this));
 
   // grab a reference to the handler to ensure that it doesn't go away.
   NS_ADDREF(gHttpHandler);
+
+  // Subfields of unions cannot be targeted in an initializer list
+  mSelfAddr.raw.family = PR_AF_UNSPEC;
+  mPeerAddr.raw.family = PR_AF_UNSPEC;
 }
 
 HttpBaseChannel::~HttpBaseChannel()
 {
   LOG(("Destroying HttpBaseChannel @%x\n", this));
 
   // Make sure we don't leak
   CleanRedirectCacheChainIfNecessary();
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -133,19 +133,16 @@ nsHttpChannel::nsHttpChannel()
     , mCustomConditionalRequest(PR_FALSE)
     , mFallingBack(PR_FALSE)
     , mWaitingForRedirectCallback(PR_FALSE)
     , mRequestTimeInitialized(PR_FALSE)
 {
     LOG(("Creating nsHttpChannel [this=%p]\n", this));
     mChannelCreationTime = PR_Now();
     mChannelCreationTimestamp = mozilla::TimeStamp::Now();
-    // Subfields of unions cannot be targeted in an initializer list
-    mSelfAddr.raw.family = PR_AF_UNSPEC;
-    mPeerAddr.raw.family = PR_AF_UNSPEC;
 }
 
 nsHttpChannel::~nsHttpChannel()
 {
     LOG(("Destroying nsHttpChannel [this=%p]\n", this));
 
     if (mAuthProvider)
         mAuthProvider->Disconnect(NS_ERROR_ABORT);