Bug 1231565 - Basic test, no r
MozReview-Commit-ID: 7uBCMfJ7kT5
--- a/netwerk/cache2/CacheStorageService.cpp
+++ b/netwerk/cache2/CacheStorageService.cpp
@@ -2209,10 +2209,37 @@ CacheStorageService::ResumeCacheIOThread
MOZ_ASSERT(mActiveIOSuspender);
RefPtr<IOThreadSuspender> suspender;
suspender.swap(mActiveIOSuspender);
suspender->Notify();
return NS_OK;
}
+NS_IMETHODIMP
+CacheStorageService::Flush(nsIObserver* aObserver)
+{
+ RefPtr<CacheIOThread> thread = CacheFileIOManager::IOThread();
+ if (!thread) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ if (!observerService) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ // Adding as weak, the consumer is responsible to keep the reference
+ // until notified.
+ observerService->AddObserver(aObserver, "cacheservice:purge-memory-pools", false);
+
+ // This runnable will do the purging and when done, notifies the above observer.
+ // We dispatch it to the CLOSE level, so all data writes scheduled up to this time
+ // will be done before this purging happens.
+ RefPtr<CacheStorageService::PurgeFromMemoryRunnable> r =
+ new CacheStorageService::PurgeFromMemoryRunnable(this, CacheEntry::PURGE_WHOLE);
+
+ return thread->Dispatch(r, CacheIOThread::CLOSE);
+}
+
} // namespace net
} // namespace mozilla
--- a/netwerk/cache2/nsICacheTesting.idl
+++ b/netwerk/cache2/nsICacheTesting.idl
@@ -1,17 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
+interface nsIObserver;
+
/**
* This is an internal interface used only for testing purposes.
*
* THIS IS NOT AN API TO BE USED BY EXTENSIONS! ONLY USED BY MOZILLA TESTS.
*/
[scriptable, builtinclass, uuid(4e8ba935-92e1-4a74-944b-b1a2f02a7480)]
interface nsICacheTesting : nsISupports
{
void suspendCacheIOThread(in uint32_t aLevel);
void resumeCacheIOThread();
+ void flush(in nsIObserver aObserver);
};
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_alt-data_simple.js
@@ -0,0 +1,105 @@
+/**
+ * Test for the "alternative data stream" stored withing a cache entry.
+ *
+ * - we load a URL with preference for an alt data (check what we get is the raw data,
+ * since there was nothing previously cached)
+ * - we store the alt data along the channel (to the cache entry)
+ * - we flush the HTTP cache
+ * - we reload the same URL using a new channel, again prefering the alt data be loaded
+ * - this time the alt data must arive
+ */
+
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "URL", function() {
+ return "http://localhost:" + httpServer.identity.primaryPort + "/content";
+});
+
+var httpServer = null;
+var cacheFlushObserver; // needs to be rooted
+
+function make_channel(url, callback, ctx) {
+ return NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true});
+}
+
+const responseContent = "response body";
+const altContent = "!@#$%^&*()";
+const altContentType = "text/binary";
+
+var servedNotModified = false;
+
+function contentHandler(metadata, response)
+{
+ response.setHeader("Content-Type", "text/plain");
+ response.setHeader("Cache-Control", "no-cache");
+ response.setHeader("ETag", "test-etag1");
+
+ try {
+ var etag = metadata.getHeader("If-None-Match");
+ } catch(ex) {
+ var etag = "";
+ }
+
+ if (etag == "test-etag1") {
+ response.setStatusLine(metadata.httpVersion, 304, "Not Modified");
+ servedNotModified = true;
+ } else {
+ response.bodyOutputStream.write(responseContent, responseContent.length);
+ }
+}
+
+function run_test()
+{
+ httpServer = new HttpServer();
+ httpServer.registerPathHandler("/content", contentHandler);
+ httpServer.start(-1);
+
+
+ var chan = make_channel(URL);
+
+ var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
+ cc.preferAlternativeDataType(altContentType);
+
+ chan.asyncOpen2(new ChannelListener(readServerContent, null));
+ do_test_pending();
+}
+
+function readServerContent(request, buffer)
+{
+ var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
+
+ do_check_eq(buffer, responseContent);
+ do_check_eq(cc.alternativeDataType, "");
+
+ var os = cc.openAlternativeOutputStream(altContentType);
+ os.write(altContent, altContent.length);
+ os.close();
+
+ cacheFlushObserver = { observe: function() {
+ cacheFlushObserver = null;
+
+ var chan = make_channel(URL);
+ var cc = chan.QueryInterface(Ci.nsICacheInfoChannel);
+ cc.preferAlternativeDataType(altContentType);
+
+ chan.asyncOpen2(new ChannelListener(readAltContent, null));
+ }};
+
+ // we may need some gc() calls first here...
+ // check one of test_cache2-26-no-outputstream-open.js or test_cache2-30c-pinning-deferred-doom.js
+ // but the entry is inside the channel, so probably no need to...
+ do_execute_soon(() => Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(cacheFlushObserver));
+}
+
+function readAltContent(request, buffer)
+{
+ var cc = request.QueryInterface(Ci.nsICacheInfoChannel);
+
+ do_check_eq(servedNotModified, true);
+ do_check_eq(cc.alternativeDataType, altContentType);
+ do_check_eq(buffer, altContent);
+
+ httpServer.stop(do_test_finished);
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -348,9 +348,10 @@ firefox-appdir = browser
[test_dns_disable_ipv6.js]
[test_packaged_app_service_paths.js]
[test_bug1195415.js]
[test_cookie_blacklist.js]
[test_getHost.js]
[test_packaged_app_bug1214079.js]
[test_bug412457.js]
[test_bug464591.js]
+[test_alt-data_simple.js]
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit_ipc/test_alt-data_simple.js_wrap.js
@@ -0,0 +1,3 @@
+function run_test() {
+ run_test_in_child("../unit/test_alt-data_simple.js.js");
+}
--- a/netwerk/test/unit_ipc/xpcshell.ini
+++ b/netwerk/test/unit_ipc/xpcshell.ini
@@ -87,10 +87,11 @@ skip-if = true
[test_simple_wrap.js]
[test_synthesized_response_wrap.js]
[test_xmlhttprequest_wrap.js]
[test_XHR_redirects.js]
[test_redirect_history_wrap.js]
[test_reply_without_content_type_wrap.js]
[test_app_offline_http.js]
[test_getHost_wrap.js]
+[test_alt-data_simple.js_wrap.js]
[test_app_offline_notifications.js]
[test_original_sent_received_head_wrap.js]