Bug 767633 - Part 4 - nsObjectLoadingContent - Don't erroneously decide state changed because the channel went away. r=josh
authorJohn Schoenick <jschoenick@mozilla.com>
Tue, 04 Dec 2012 17:10:29 -0800
changeset 121554 a2476e368fb6b63939fbd3dda29008ee696d105f
parent 121553 11341616d7cb84252fe339b8e1bec3b2ae3dd3c3
child 121555 62389ec6712c98697ef122b6e9ec43f14d33c1ff
push idunknown
push userunknown
push dateunknown
reviewersjosh
bugs767633
milestone20.0a1
Bug 767633 - Part 4 - nsObjectLoadingContent - Don't erroneously decide state changed because the channel went away. r=josh
content/base/src/nsObjectLoadingContent.cpp
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1372,17 +1372,21 @@ nsObjectLoadingContent::UpdateObjectPara
   ///
   /// If we have a channel, see if its MIME type should take precendence and
   /// check the final (redirected) URL
   ///
 
   // If we have a loaded channel and channel parameters did not change, use it
   // to determine what we would load.
   bool useChannel = mChannelLoaded && !(retval & eParamChannelChanged);
-  if (mChannel && useChannel) {
+  // If we have a channel and are type loading, as opposed to having an existing
+  // channel for a previous load.
+  bool newChannel = useChannel && mType == eType_Loading;
+
+  if (newChannel && mChannel) {
     nsCString channelType;
     rv = mChannel->GetContentType(channelType);
     if (NS_FAILED(rv)) {
       NS_NOTREACHED("GetContentType failed");
       stateInvalid = true;
       channelType.Assign("");
     }
 
@@ -1460,21 +1464,18 @@ nsObjectLoadingContent::UpdateObjectPara
         // changes how we may have interpreted the codebase to construct this
         // URI above.  Because the behavior here is more or less undefined, play
         // it safe and reject the load.
         LOG(("OBJLC [%p]: Refusing to load with channel with java MIME",
              this));
         stateInvalid = true;
       }
     }
-  }
-
-  if (useChannel && !mChannel) {
-    // - (useChannel && !mChannel) is true if a channel was opened but
-    //   is no longer around, in which case we can't load.
+  } else if (newChannel) {
+    LOG(("OBJLC [%p]: We failed to open a channel, marking invalid", this));
     stateInvalid = true;
   }
 
   ///
   /// Determine final type
   ///
   // In order of preference:
   //  1) If we have attempted channel load, or set stateInvalid above, the type
@@ -1486,18 +1487,18 @@ nsObjectLoadingContent::UpdateObjectPara
   //  5) if we have a URI, set type to loading to indicate we'd need a channel
   //     to proceed.
   //  6) Otherwise, type null to indicate unloadable content (fallback)
   //
 
   if (stateInvalid) {
     newType = eType_Null;
     newMime.Truncate();
-  } else if (useChannel) {
-      // If useChannel is set above, we considered it in setting newMime
+  } else if (newChannel) {
+      // If newChannel is set above, we considered it in setting newMime
       newType = GetTypeOfContent(newMime);
       LOG(("OBJLC [%p]: Using channel type", this));
   } else if (((caps & eAllowPluginSkipChannel) || !newURI) &&
              GetTypeOfContent(newMime) == eType_Plugin) {
     newType = eType_Plugin;
     LOG(("OBJLC [%p]: Plugin type with no URI, skipping channel load", this));
   } else if (newURI) {
     // We could potentially load this if we opened a channel on mURI, indicate
@@ -1505,16 +1506,32 @@ nsObjectLoadingContent::UpdateObjectPara
     newType = eType_Loading;
   } else {
     // Unloadable - no URI, and no plugin type. Non-plugin types (images,
     // documents) always load with a channel.
     newType = eType_Null;
   }
 
   ///
+  /// Handle existing channels
+  ///
+
+  if (useChannel && newType == eType_Loading) {
+    // We decided to use a channel, and also that the previous channel is still
+    // usable, so re-use the existing values.
+    newType = mType;
+    newMime = mContentType;
+    newURI = mURI;
+  } else if (useChannel && !newChannel) {
+    // We have an existing channel, but did not decide to use one.
+    retval = (ParameterUpdateFlags)(retval | eParamChannelChanged);
+    useChannel = false;
+  }
+
+  ///
   /// Update changed values
   ///
 
   if (newType != mType) {
     retval = (ParameterUpdateFlags)(retval | eParamStateChanged);
     LOG(("OBJLC [%p]: Type changed from %u -> %u", this, mType, newType));
     mType = newType;
   }
@@ -1543,16 +1560,23 @@ nsObjectLoadingContent::UpdateObjectPara
   if (mType != eType_Loading && mContentType != newMime) {
     retval = (ParameterUpdateFlags)(retval | eParamStateChanged);
     retval = (ParameterUpdateFlags)(retval | eParamContentTypeChanged);
     LOG(("OBJLC [%p]: Object effective mime type changed (%s -> %s)",
          this, mContentType.get(), newMime.get()));
     mContentType = newMime;
   }
 
+  // If we decided to keep using info from an old channel, but also that state
+  // changed, we need to invalidate it.
+  if (useChannel && !newChannel && (retval & eParamStateChanged)) {
+    mType = eType_Loading;
+    retval = (ParameterUpdateFlags)(retval | eParamChannelChanged);
+  }
+
   return retval;
 }
 
 // Only OnStartRequest should be passing the channel parameter
 nsresult
 nsObjectLoadingContent::LoadObject(bool aNotify,
                                    bool aForceLoad)
 {