Bug 967792 - Make localhost resolve offline. r=dragana

This commit is contained in:
Patrick McManus 2015-02-25 14:02:38 -05:00
parent 24d3abfbf9
commit 9dbe80428a
8 changed files with 103 additions and 7 deletions

View File

@ -37,6 +37,7 @@ add_task(function* setup_server() {
add_task(function* error_offline() {
Services.io.offline = true;
Services.prefs.setBoolPref("network.dns.offline-localhost", false);
yield MozLoopServiceInternal.hawkRequestInternal(LOOP_SESSION_TYPE.GUEST, "/offline", "GET").then(
() => Assert.ok(false, "Should have rejected"),
(error) => {
@ -179,6 +180,7 @@ function run_test() {
Services.prefs.clearUserPref("loop.hawk-session-token");
Services.prefs.clearUserPref("loop.hawk-session-token.fxa");
Services.prefs.clearUserPref("loop.urlsExpiryTimeSeconds");
Services.prefs.clearUserPref("network.dns.offline-localhost");
MozLoopService.errors.clear();
});

View File

@ -6,6 +6,9 @@
var gExpectedStatus = null;
var gNextTestFunc = null;
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
var asyncXHR = {
load: function() {
var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
@ -39,6 +42,7 @@ function run_test_pt1() {
catch (e) {
}
ioService.offline = true;
prefs.setBoolPref("network.dns.offline-localhost", false);
gExpectedStatus = Components.results.NS_ERROR_OFFLINE;
gNextTestFunc = run_test_pt2;
@ -51,6 +55,7 @@ function run_test_pt2() {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
ioService.offline = false;
prefs.clearUserPref("network.dns.offline-localhost");
gExpectedStatus = Components.results.NS_ERROR_CONNECTION_REFUSED;
gNextTestFunc = end_test;

View File

@ -1589,6 +1589,9 @@ pref("network.dnsCacheExpirationGracePeriod", 60);
// This preference can be used to turn off DNS prefetch.
pref("network.dns.disablePrefetch", false);
// Contols whether or not "localhost" should resolve when offline
pref("network.dns.offline-localhost", true);
// This preference controls whether or not URLs with UTF-8 characters are
// escaped. Set this preference to TRUE for strict RFC2396 conformance.
pref("network.standard-url.escape-utf8", true);

View File

@ -50,6 +50,7 @@ static const char kPrefIPv4OnlyDomains[] = "network.dns.ipv4OnlyDomains";
static const char kPrefDisableIPv6[] = "network.dns.disableIPv6";
static const char kPrefDisablePrefetch[] = "network.dns.disablePrefetch";
static const char kPrefDnsLocalDomains[] = "network.dns.localDomains";
static const char kPrefDnsOfflineLocalhost[] = "network.dns.offline-localhost";
static const char kPrefDnsNotifyResolution[] = "network.dns.notifyResolution";
//-----------------------------------------------------------------------------
@ -535,12 +536,12 @@ nsDNSService::Init()
if (mResolver)
return NS_OK;
NS_ENSURE_TRUE(!mResolver, NS_ERROR_ALREADY_INITIALIZED);
// prefs
uint32_t maxCacheEntries = 400;
uint32_t defaultCacheLifetime = 120; // seconds
uint32_t defaultGracePeriod = 60; // seconds
bool disableIPv6 = false;
bool offlineLocalhost = true;
bool disablePrefetch = false;
int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
bool notifyResolution = false;
@ -563,6 +564,7 @@ nsDNSService::Init()
prefs->GetBoolPref(kPrefDisableIPv6, &disableIPv6);
prefs->GetCharPref(kPrefIPv4OnlyDomains, getter_Copies(ipv4OnlyDomains));
prefs->GetCharPref(kPrefDnsLocalDomains, getter_Copies(localDomains));
prefs->GetBoolPref(kPrefDnsOfflineLocalhost, &offlineLocalhost);
prefs->GetBoolPref(kPrefDisablePrefetch, &disablePrefetch);
// If a manual proxy is in use, disable prefetch implicitly
@ -581,6 +583,7 @@ nsDNSService::Init()
prefs->AddObserver(kPrefIPv4OnlyDomains, this, false);
prefs->AddObserver(kPrefDnsLocalDomains, this, false);
prefs->AddObserver(kPrefDisableIPv6, this, false);
prefs->AddObserver(kPrefDnsOfflineLocalhost, this, false);
prefs->AddObserver(kPrefDisablePrefetch, this, false);
prefs->AddObserver(kPrefDnsNotifyResolution, this, false);
@ -621,6 +624,7 @@ nsDNSService::Init()
mResolver = res;
mIDN = idn;
mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership
mOfflineLocalhost = offlineLocalhost;
mDisableIPv6 = disableIPv6;
// Disable prefetching either by explicit preference or if a manual proxy is configured
@ -753,13 +757,15 @@ nsDNSService::AsyncResolveExtended(const nsACString &aHostname,
if (!res)
return NS_ERROR_OFFLINE;
if (mOffline)
flags |= RESOLVE_OFFLINE;
nsCString hostname;
if (!PreprocessHostname(localDomain, aHostname, idn, hostname))
return NS_ERROR_FAILURE;
if (mOffline &&
(!mOfflineLocalhost || !hostname.LowerCaseEqualsASCII("localhost"))) {
flags |= RESOLVE_OFFLINE;
}
// make sure JS callers get notification on the main thread
nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
if (wrappedListener && !target) {
@ -867,13 +873,15 @@ nsDNSService::Resolve(const nsACString &aHostname,
NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
if (mOffline)
flags |= RESOLVE_OFFLINE;
nsCString hostname;
if (!PreprocessHostname(localDomain, aHostname, idn, hostname))
return NS_ERROR_FAILURE;
if (mOffline &&
(!mOfflineLocalhost || !hostname.LowerCaseEqualsASCII("localhost"))) {
flags |= RESOLVE_OFFLINE;
}
//
// sync resolve: since the host resolver only works asynchronously, we need
// to use a mutex and a condvar to wait for the result. however, since the

View File

@ -60,6 +60,7 @@ private:
bool mFirstTime;
bool mOffline;
bool mNotifyResolution;
bool mOfflineLocalhost;
nsMainThreadPtrHandle<nsIObserverService> mObserverService;
nsTHashtable<nsCStringHashKey> mLocalDomains;
};

View File

@ -0,0 +1,74 @@
var dns = Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService);
var ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
var threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
var mainThread = threadManager.currentThread;
var listener1 = {
onLookupComplete: function(inRequest, inRecord, inStatus) {
do_check_eq(inStatus, Cr.NS_ERROR_OFFLINE);
test2();
do_test_finished();
}
};
var listener2 = {
onLookupComplete: function(inRequest, inRecord, inStatus) {
do_check_eq(inStatus, Cr.NS_OK);
var answer = inRecord.getNextAddrAsString();
do_check_true(answer == "127.0.0.1" || answer == "::1");
test3();
do_test_finished();
}
};
var listener3 = {
onLookupComplete: function(inRequest, inRecord, inStatus) {
do_check_eq(inStatus, Cr.NS_OK);
var answer = inRecord.getNextAddrAsString();
do_check_true(answer == "127.0.0.1" || answer == "::1");
cleanup();
do_test_finished();
}
};
function run_test() {
do_test_pending();
prefs.setBoolPref("network.dns.offline-localhost", false);
ioService.offline = true;
try {
dns.asyncResolve("localhost", 0, listener1, mainThread);
} catch (e) {
do_check_eq(e.result, Cr.NS_ERROR_OFFLINE);
test2();
do_test_finished();
}
}
function test2() {
do_test_pending();
prefs.setBoolPref("network.dns.offline-localhost", true);
ioService.offline = false;
ioService.offline = true;
// we need to let the main thread run and apply the changes
do_timeout(0, test2Continued);
}
function test2Continued() {
dns.asyncResolve("localhost", 0, listener2, mainThread);
}
function test3() {
do_test_pending();
ioService.offline = false;
// we need to let the main thread run and apply the changes
do_timeout(0, test3Continued);
}
function test3Continued() {
dns.asyncResolve("localhost", 0, listener3, mainThread);
}
function cleanup() {
prefs.clearUserPref("network.dns.offline-localhost");
}

View File

@ -176,6 +176,7 @@ skip-if = bits != 32
[test_dns_per_interface.js]
[test_data_protocol.js]
[test_dns_service.js]
[test_dns_offline.js]
[test_dns_localredirect.js]
[test_dns_proxy_bypass.js]
[test_duplicate_headers.js]

View File

@ -200,6 +200,7 @@ add_identity_test(this, function test_service_offline() {
let deferred = Promise.defer();
server.stop(() => {
Services.io.offline = true;
Services.prefs.setBoolPref("network.dns.offline-localhost", false);
try {
do_check_eq(Status.sync, SYNC_SUCCEEDED);
@ -214,6 +215,7 @@ add_identity_test(this, function test_service_offline() {
Service.startOver();
}
Services.io.offline = false;
Services.prefs.clearUserPref("network.dns.offline-localhost");
deferred.resolve();
});
yield deferred.promise;