bug 717759 - negative pipeline feedback on img decode problem r=bz r=jdrew r=honzab
authorPatrick McManus <mcmanus@ducksong.com>
Thu, 22 Mar 2012 19:39:32 -0400
changeset 93418 6018a0d6b33dc24ece8c2be6a348b0dff909d00f
parent 93417 f94cf04e8d736d67c6ed72be46c83ad6aceef539
child 93419 81aff28f132fe8a92c7eaa5b85d096ee78a84764
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, jdrew, honzab
bugs717759
milestone14.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
bug 717759 - negative pipeline feedback on img decode problem r=bz r=jdrew r=honzab
image/src/imgRequest.cpp
image/test/mochitest/Makefile.in
image/test/mochitest/invalid.jpg
image/test/mochitest/test_net_failedtoprocess.html
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpConnectionMgr.h
netwerk/protocol/http/nsHttpHandler.cpp
--- a/image/src/imgRequest.cpp
+++ b/image/src/imgRequest.cpp
@@ -680,16 +680,25 @@ NS_IMETHODIMP imgRequest::OnStopDecode(i
   mImage->GetStatusTracker().RecordStopDecode(aStatus, aStatusArg);
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
   while (iter.HasMore()) {
     mImage->GetStatusTracker().SendStopDecode(iter.GetNext(), aStatus,
                                               aStatusArg);
   }
 
+  if (NS_FAILED(aStatus)) {
+    // Some kind of problem has happened with image decoding.
+    // Report the URI to net:failed-to-decode-uri observers.
+
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (os)
+      os->NotifyObservers(mURI, "net:failed-to-process-uri", nsnull);
+  }
+
   // RasterImage and everything below it is completely correct and
   // bulletproof about its handling of decoder notifications.
   // Unfortunately, here and above we have to make some gross and
   // inappropriate use of things to get things to work without
   // completely overhauling the decoder observer interface (this will,
   // thankfully, happen in bug 505385). From imgRequest and above (for
   // the time being), OnStopDecode is just a companion to OnStopRequest
   // that signals success or failure of the _load_ (not the _decode_).
--- a/image/test/mochitest/Makefile.in
+++ b/image/test/mochitest/Makefile.in
@@ -113,15 +113,18 @@ include $(topsrcdir)/config/rules.mk
                 filter-final.svg \
                 test_svg_filter_animation.html \
                 test_xultree_animation.xhtml \
                 test_changeOfSource.html \
                 test_changeOfSource2.html \
                 test_undisplayed_iframe.html \
                 iframe.html \
                 ref-iframe.html \
+                test_net_failedtoprocess.html \
+                invalid.jpg \
+                damon.jpg \
                 $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/image/test/mochitest/invalid.jpg
@@ -0,0 +1,1 @@
+notajpg
new file mode 100644
--- /dev/null
+++ b/image/test/mochitest/test_net_failedtoprocess.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Test that a image decoding error producs a net:failed-to-process-uri
+observer event with the nsIURI of the failed image as the subject
+-->
+<head>
+  <title>Test for image net:failed-to-process-uri</title>
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+var observer = {
+  QueryInterface: function (aIID) {
+    if (aIID.equals(Ci.nsISupports) ||
+        aIID.equals(Ci.nsIObserver))
+      return this;
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  },
+
+  observe: function(subject, topic, data) {
+    ok(topic == "net:failed-to-process-uri", "wrong topic");
+    subject = subject.QueryInterface(Ci.nsIURI);
+    ok(subject.asciiSpec == "chrome://mochitests/content/chrome/image/test/mochitest/invalid.jpg", "wrong subject");
+    SimpleTest.finish();
+  }
+};
+
+var obs = Cc["@mozilla.org/observer-service;1"].getService();
+obs = obs.QueryInterface(Ci.nsIObserverService);
+obs.addObserver(observer, "net:failed-to-process-uri", false);
+
+</script>
+</pre>
+<img src="damon.jpg">
+<img src="invalid.jpg">
+</body>
+</html>
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -985,16 +985,39 @@ nsHttpConnectionMgr::PipelineFeedbackInf
     }
 
     nsConnectionEntry *ent = mCT.Get(ci->HashKey());
 
     if (ent)
         ent->OnPipelineFeedbackInfo(info, conn, data);
 }
 
+void
+nsHttpConnectionMgr::ReportFailedToProcess(nsIURI *uri)
+{
+    NS_ABORT_IF_FALSE(uri, "precondition");
+
+    nsCAutoString host;
+    PRInt32 port = -1;
+    bool usingSSL = false;
+
+    nsresult rv = uri->SchemeIs("https", &usingSSL);
+    if (NS_SUCCEEDED(rv))
+        rv = uri->GetAsciiHost(host);
+    if (NS_SUCCEEDED(rv))
+        rv = uri->GetPort(&port);
+    if (NS_FAILED(rv) || host.IsEmpty())
+        return;
+
+    nsRefPtr<nsHttpConnectionInfo> ci =
+        new nsHttpConnectionInfo(host, port, nsnull, usingSSL);
+    
+    PipelineFeedbackInfo(ci, RedCorruptedContent, nsnull, 0);
+}
+
 // we're at the active connection limit if any one of the following conditions is true:
 //  (1) at max-connections
 //  (2) keep-alive enabled and at max-persistent-connections-per-server/proxy
 //  (3) keep-alive disabled and at max-connections-per-server
 bool
 nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 caps)
 {
     nsHttpConnectionInfo *ci = ent->mConnInfo;
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -200,16 +200,18 @@ public:
     
     // called to provide information relevant to the pipelining manager
     // may be called from any thread
     void     PipelineFeedbackInfo(nsHttpConnectionInfo *,
                                   PipelineFeedbackInfoType info,
                                   nsHttpConnection *,
                                   PRUint32);
 
+    void ReportFailedToProcess(nsIURI *uri);
+
     //-------------------------------------------------------------------------
     // NOTE: functions below may be called only on the socket thread.
     //-------------------------------------------------------------------------
 
     // called to force the transaction queue to be processed once more, giving
     // preference to the specified connection.
     nsresult ProcessPendingQ(nsHttpConnectionInfo *);
     bool     ProcessPendingQForEntry(nsHttpConnectionInfo *);
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -338,16 +338,17 @@ nsHttpHandler::Init()
     mObserverService = mozilla::services::GetObserverService();
     if (mObserverService) {
         mObserverService->AddObserver(this, "profile-change-net-teardown", true);
         mObserverService->AddObserver(this, "profile-change-net-restore", true);
         mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
         mObserverService->AddObserver(this, "net:clear-active-logins", true);
         mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
         mObserverService->AddObserver(this, "net:prune-dead-connections", true);
+        mObserverService->AddObserver(this, "net:failed-to-process-uri", true);
     }
  
     return NS_OK;
 }
 
 nsresult
 nsHttpHandler::InitConnectionMgr()
 {
@@ -1629,16 +1630,21 @@ nsHttpHandler::Observe(nsISupports *subj
         if (mConnMgr)
             mConnMgr->ClosePersistentConnections();
     }
     else if (strcmp(topic, "net:prune-dead-connections") == 0) {
         if (mConnMgr) {
             mConnMgr->PruneDeadConnections();
         }
     }
+    else if (strcmp(topic, "net:failed-to-process-uri") == 0) {
+        nsCOMPtr<nsIURI> uri = do_QueryInterface(subject);
+        if (uri && mConnMgr)
+            mConnMgr->ReportFailedToProcess(uri);
+    }
   
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpsHandler implementation
 //-----------------------------------------------------------------------------