bug 742935: fix landing problem with 717350 r=honzab
authorPatrick McManus <mcmanus@ducksong.com>
Mon, 09 Apr 2012 10:21:28 -0400
changeset 94560 10f864a9b5c5f154cc712fc3280bb179f39f388d
parent 94559 dc8f2d891d8fbb9789ff5311dcb4fb1e75b75ef2
child 94561 bf132b7a5a9d839643f832f9e0996e6d0e3e6def
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)
reviewershonzab
bugs742935, 717350
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 742935: fix landing problem with 717350 r=honzab
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/test/unit/test_mismatch_last-modified.js
netwerk/test/unit/test_mismatch_lm.js
netwerk/test/unit/xpcshell.ini
toolkit/components/telemetry/TelemetryHistograms.h
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -1981,34 +1981,38 @@ nsHttpChannel::ProcessNotModified()
 
     // If the 304 response contains a Last-Modified different than the
     // one in our cache that is pretty suspicious and is, in at least the
     // case of bug 716840, a sign of the server having previously corrupted
     // our cache with a bad response. Take the minor step here of just dooming
     // that cache entry so there is a fighting chance of getting things on the
     // right track as well as disabling pipelining for that host.
 
-    nsCAutoString lastModified;
+    nsCAutoString lastModifiedCached;
     nsCAutoString lastModified304;
 
     rv = mCachedResponseHead->GetHeader(nsHttp::Last_Modified,
-                                        lastModified);
-    if (NS_SUCCEEDED(rv))
+                                        lastModifiedCached);
+    if (NS_SUCCEEDED(rv)) {
         rv = mResponseHead->GetHeader(nsHttp::Last_Modified, 
                                       lastModified304);
-    if (NS_SUCCEEDED(rv) && !lastModified304.Equals(lastModified)) {
+    }
+
+    if (NS_SUCCEEDED(rv) && !lastModified304.Equals(lastModifiedCached)) {
         LOG(("Cache Entry and 304 Last-Modified Headers Do Not Match "
-             "%s and %s\n", lastModified.get(), lastModified304.get()));
+             "[%s] and [%s]\n",
+             lastModifiedCached.get(), lastModified304.get()));
 
         mCacheEntry->Doom();
         if (mConnectionInfo)
             gHttpHandler->ConnMgr()->
                 PipelineFeedbackInfo(mConnectionInfo,
                                      nsHttpConnectionMgr::RedCorruptedContent,
                                      nsnull, 0);
+        Telemetry::Accumulate(Telemetry::CACHE_LM_INCONSISTENT, true);
     }
 
     // merge any new headers with the cached response headers
     rv = mCachedResponseHead->UpdateHeaders(mResponseHead->Headers());
     if (NS_FAILED(rv)) return rv;
 
     // update the cached response head
     nsCAutoString head;
rename from netwerk/test/unit/test_mismatch_lm.js
rename to netwerk/test/unit/test_mismatch_last-modified.js
--- a/netwerk/test/unit/test_mismatch_lm.js
+++ b/netwerk/test/unit/test_mismatch_last-modified.js
@@ -14,95 +14,112 @@ var ios;
 // back, the second time that wrong data is revalidated with a 304 but
 // a L-M header of the right data (this triggers a cache purge), and
 // the third time the right data is returned.
 
 var listener_3 = {
     // this listener is used to process the the request made after
     // the cache invalidation. it expects to see the 'right data'
 
+    QueryInterface: function(iid) {
+	if (iid.equals(Components.interfaces.nsIStreamListener) ||
+            iid.equals(Components.interfaces.nsIRequestObserver) ||
+            iid.equals(Components.interfaces.nsISupports))
+	    return this;
+	throw Components.results.NS_ERROR_NO_INTERFACE;
+    },
+
     onStartRequest: function test_onStartR(request, ctx) {},
     
     onDataAvailable: function test_ODA(request, cx, inputStream,
                                        offset, count) {
 	var data = new BinaryInputStream(inputStream).readByteArray(count);
       
-	// This is 'B'
-	do_check_eq(data, 66);
+	do_check_eq(data[0], "B".charCodeAt(0));
     },
 
     onStopRequest: function test_onStopR(request, ctx, status) {
 	httpserver.stop(do_test_finished);
     }
 };
 
 var listener_2 = {
     // this listener is used to process the revalidation of the
     // corrupted cache entry. its revalidation prompts it to be cleaned
 
+    QueryInterface: function(iid) {
+	if (iid.equals(Components.interfaces.nsIStreamListener) ||
+            iid.equals(Components.interfaces.nsIRequestObserver) ||
+            iid.equals(Components.interfaces.nsISupports))
+	    return this;
+	throw Components.results.NS_ERROR_NO_INTERFACE;
+    },
+
     onStartRequest: function test_onStartR(request, ctx) {},
     
     onDataAvailable: function test_ODA(request, cx, inputStream,
                                        offset, count) {
 	var data = new BinaryInputStream(inputStream).readByteArray(count);
       
 	// This is 'A' from a cache revalidation, but that reval will clean the cache
 	// because of mismatched last-modified response headers
 	
-	do_check_eq(data, 65);
+	do_check_eq(data[0], "A".charCodeAt(0));
     },
 
     onStopRequest: function test_onStopR(request, ctx, status) {
 	var channel = request.QueryInterface(Ci.nsIHttpChannel);
 
 	var chan = ios.newChannel("http://localhost:4444/test1", "", null);
-	var httpChan = chan.QueryInterface(Ci.nsIHttpChannel);
-	httpChan.requestMethod = "GET";
-	httpChan.asyncOpen(listener_3, null);
+	chan.asyncOpen(listener_3, null);
     }
 };
 
 var listener_1 = {
     // this listener processes the initial request from a empty cache.
     // the server responds with the wrong data ('A')
 
+    QueryInterface: function(iid) {
+	if (iid.equals(Components.interfaces.nsIStreamListener) ||
+            iid.equals(Components.interfaces.nsIRequestObserver) ||
+            iid.equals(Components.interfaces.nsISupports))
+	    return this;
+	throw Components.results.NS_ERROR_NO_INTERFACE;
+    },
+
     onStartRequest: function test_onStartR(request, ctx) {},
     
     onDataAvailable: function test_ODA(request, cx, inputStream,
                                        offset, count) {
 	var data = new BinaryInputStream(inputStream).readByteArray(count);
-	do_check_eq(data, 65);
+	do_check_eq(data[0], "A".charCodeAt(0));
     },
 
     onStopRequest: function test_onStopR(request, ctx, status) {
 	var channel = request.QueryInterface(Ci.nsIHttpChannel);
 
 	var chan = ios.newChannel("http://localhost:4444/test1", "", null);
-	var httpChan = chan.QueryInterface(Ci.nsIHttpChannel);
-	httpChan.requestMethod = "GET";
-	httpChan.asyncOpen(listener_2, null);
+	chan.asyncOpen(listener_2, null);
     }
 };
 
 function run_test() {
     do_get_profile();
     cacheService = Cc["@mozilla.org/network/cache-service;1"].
         getService(Ci.nsICacheService);
     ios = Cc["@mozilla.org/network/io-service;1"]
             .getService(Ci.nsIIOService);
 
     cacheService.evictEntries(Ci.nsICache.STORE_ANYWHERE);
 
     httpserver.registerPathHandler("/test1", handler);
     httpserver.start(4444);
 
     var chan = ios.newChannel("http://localhost:4444/test1", "", null);
-    var httpChan = chan.QueryInterface(Ci.nsIHttpChannel);
-    httpChan.requestMethod = "GET";
-    httpChan.asyncOpen(listener_1, null);
+    chan.asyncOpen(listener_1, null);
 
     do_test_pending();
 }
 
 var iter=0;
 function handler(metadata, response) {
     iter++;
     if (metadata.hasHeader("If-Modified-Since")) {
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -129,17 +129,17 @@ skip-if = os == "android"
 [test_gzipped_206.js]
 [test_head.js]
 [test_headers.js]
 [test_http_headers.js]
 [test_httpcancel.js]
 [test_httpsuspend.js]
 [test_idnservice.js]
 [test_localstreams.js]
-[test_mismatch_lm.js]
+[test_mismatch_last-modified.js]
 [test_MIME_params.js]
 [test_multipart_streamconv.js]
 [test_multipart_streamconv_missing_lead_boundary.js]
 [test_nestedabout_serialize.js]
 [test_net_addr.js]
 # Bug 732363: test fails on windows for unknown reasons.
 skip-if = os == "win"
 [test_nojsredir.js]
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -230,16 +230,17 @@ HISTOGRAM(DISK_CACHE_CORRUPT, 0, 1, 2, B
 HISTOGRAM(HTTP_DISK_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Disk Cache Hit, Reval, Failed-Reval, Miss")
 HISTOGRAM(HTTP_MEMORY_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Memory Cache Hit, Reval, Failed-Reval, Miss")
 HISTOGRAM(HTTP_OFFLINE_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Offline Cache Hit, Reval, Failed-Reval, Miss")
 HISTOGRAM(CACHE_DEVICE_SEARCH, 1, 100, 100, LINEAR, "Time to search cache (ms)")
 HISTOGRAM(CACHE_MEMORY_SEARCH, 1, 100, 100, LINEAR, "Time to search memory cache (ms)")
 HISTOGRAM(CACHE_DISK_SEARCH, 1, 100, 100, LINEAR, "Time to search disk cache (ms)")
 HISTOGRAM(CACHE_OFFLINE_SEARCH, 1, 100, 100, LINEAR, "Time to search offline cache (ms)")
 HISTOGRAM(HTTP_DISK_CACHE_OVERHEAD, 1, 32000000, 100, EXPONENTIAL, "HTTP Disk cache memory overhead (bytes)")
+HISTOGRAM(CACHE_LM_INCONSISTENT, 0, 1, 2, BOOLEAN,  "Cache discovered inconsistent last-modified entry")
 HISTOGRAM(CACHE_SERVICE_LOCK_WAIT, 1, 10000, 10000, LINEAR, "Time spent waiting on the cache service lock (ms)")
 HISTOGRAM(CACHE_SERVICE_LOCK_WAIT_MAINTHREAD, 1, 10000, 10000, LINEAR, "Time spent waiting on the cache service lock on the main thread (ms)")
 
 HISTOGRAM(DNS_LOOKUP_METHOD, 1, 7, 7, LINEAR, "DNS Lookup Type (hit, renewal, negative-hit, literal, overflow, network-first, network-shared)")
 HISTOGRAM(DNS_CLEANUP_AGE, 1, 1440, 50, EXPONENTIAL, "DNS Cache Entry Age at Removal Time (minutes)")
 HISTOGRAM(DNS_LOOKUP_TIME, 1, 60000, 50, EXPONENTIAL, "Time for a successful DNS OS resolution (msec)")
 HISTOGRAM(DNS_RENEWAL_TIME, 1, 60000, 50, EXPONENTIAL, "Time for a renewed DNS OS resolution (msec)")
 HISTOGRAM(DNS_FAILED_LOOKUP_TIME, 1, 60000, 50, EXPONENTIAL, "Time for an unsuccessful DNS OS resolution (msec)")