// // Test that "max_entry_size" prefs for disk- and memory-cache prevents // caching resources with size out of bounds // do_load_httpd_js(); do_get_profile(); const prefService = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefBranch); const httpserver = new nsHttpServer(); // Repeats the given data until the total size is larger than 1K function repeatToLargerThan1K(data) { while(data.length <= 1024) data += data; return data; } function SyncWithCacheThread(aFunc) { do_check_eq(sync_with_cache_IO_thread_cb.listener, null); sync_with_cache_IO_thread_cb.listener = aFunc; var cache = Cc["@mozilla.org/network/cache-service;1"]. getService(Ci.nsICacheService); var session = cache.createSession( "HTTP", Ci.nsICache.STORE_ANYWHERE, Ci.nsICache.STREAM_BASED); var cacheEntry = session.asyncOpenCacheEntry( "nonexistententry", Ci.nsICache.ACCESS_READ, sync_with_cache_IO_thread_cb); } var sync_with_cache_IO_thread_cb = { listener: null, onCacheEntryAvailable: function oCEA(descriptor, accessGranted, status) { do_check_neq(status, Cr.NS_OK); cb = this.listener; this.listener = null; do_execute_soon(cb); } }; function clearCache() { var service = Components.classes["@mozilla.org/network/cache-service;1"] .getService(Ci.nsICacheService); service.evictEntries(Ci.nsICache.STORE_ANYWHERE); } function setupChannel(suffix, value) { var ios = Components.classes["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); var chan = ios.newChannel("http://localhost:4444" + suffix, "", null); var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); httpChan.setRequestHeader("x-request", value, false); return httpChan; } var tests = [ new InitializeCacheDevices(true, false), // enable and create mem-device new TestCacheEntrySize( function() { prefService.setIntPref("browser.cache.memory.max_entry_size", 1); }, "012345", "9876543210", "012345"), // expect cached value new TestCacheEntrySize( function() { prefService.setIntPref("browser.cache.memory.max_entry_size", 1); }, "0123456789a", "9876543210", "9876543210"), // expect fresh value new TestCacheEntrySize( function() { prefService.setIntPref("browser.cache.memory.max_entry_size", -1); }, "0123456789a", "9876543210", "0123456789a"), // expect cached value new InitializeCacheDevices(false, true), // enable and create disk-device new TestCacheEntrySize( function() { prefService.setIntPref("browser.cache.disk.max_entry_size", 1); }, "012345", "9876543210", "012345"), // expect cached value new TestCacheEntrySize( function() { prefService.setIntPref("browser.cache.disk.max_entry_size", 1); }, "0123456789a", "9876543210", "9876543210"), // expect fresh value new TestCacheEntrySize( function() { prefService.setIntPref("browser.cache.disk.max_entry_size", -1); }, "0123456789a", "9876543210", "0123456789a"), // expect cached value ]; function nextTest() { // We really want each test to be self-contained. Make sure cache is // cleared and also let all operations finish before starting a new test SyncWithCacheThread(function() { clearCache(); SyncWithCacheThread(runNextTest); }); } function runNextTest() { var aTest = tests.shift(); if (!aTest) { httpserver.stop(do_test_finished); return; } do_execute_soon(function() { aTest.start(); } ); } // Just make sure devices are created function InitializeCacheDevices(memDevice, diskDevice) { this.start = function() { prefService.setBoolPref("browser.cache.memory.enable", memDevice); if (memDevice) { try { cap = prefService.getIntPref("browser.cache.memory.capacity"); } catch(ex) { cap = 0; } if (cap == 0) { prefService.setIntPref("browser.cache.memory.capacity", 1024); } } prefService.setBoolPref("browser.cache.disk.enable", diskDevice); if (diskDevice) { try { cap = prefService.getIntPref("browser.cache.disk.capacity"); } catch(ex) { cap = 0; } if (cap == 0) { prefService.setIntPref("browser.cache.disk.capacity", 1024); } } var channel = setupChannel("/bug650995", "Initial value"); channel.asyncOpen(new ChannelListener( nextTest, null), null); } } function TestCacheEntrySize(setSizeFunc, firstRequest, secondRequest, secondExpectedReply) { // Initially, this test used 10 bytes as the limit for caching entries. // Since we now use 1K granularity we have to extend lengths to be larger // than 1K if it is larger than 10 if (firstRequest.length > 10) firstRequest = repeatToLargerThan1K(firstRequest); if (secondExpectedReply.length > 10) secondExpectedReply = repeatToLargerThan1K(secondExpectedReply); this.start = function() { setSizeFunc(); var channel = setupChannel("/bug650995", firstRequest); channel.asyncOpen(new ChannelListener(this.initialLoad, this), null); }, this.initialLoad = function(request, data, ctx) { do_check_eq(firstRequest, data); var channel = setupChannel("/bug650995", secondRequest); do_execute_soon(function() { channel.asyncOpen(new ChannelListener(ctx.testAndTriggerNext, ctx), null); }); }, this.testAndTriggerNext = function(request, data, ctx) { do_check_eq(secondExpectedReply, data); do_execute_soon(nextTest); } } function run_test() { httpserver.registerPathHandler("/bug650995", handler); httpserver.start(4444); prefService.setBoolPref("browser.cache.offline.enable", false); nextTest(); do_test_pending(); } function handler(metadata, response) { var body = "BOOM!"; try { body = metadata.getHeader("x-request"); } catch(e) {} response.setStatusLine(metadata.httpVersion, 200, "Ok"); response.setHeader("Content-Type", "text/plain", false); response.setHeader("Cache-Control", "max-age=3600", false); response.bodyOutputStream.write(body, body.length); }