diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp index 88322b757d9c..2d84d1d23848 100644 --- a/docshell/base/nsWebShell.cpp +++ b/docshell/base/nsWebShell.cpp @@ -119,9 +119,6 @@ #include "nsCExternalHandlerService.h" #include "nsIIDNService.h" -#include "nsIPrefBranch.h" -#include "nsIPrefService.h" -#define NS_NET_PREF_IDNSHOWPUNYCODE "network.IDN_show_punycode" #ifdef NS_DEBUG /** @@ -734,30 +731,26 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, if(keywordsEnabled && (kNotFound == dotLoc)) { // only send non-qualified hosts to the keyword server nsCAutoString keywordSpec("keyword:"); - nsCOMPtr prefBranch = - do_GetService(NS_PREFSERVICE_CONTRACTID); - PRBool showPunycode = PR_FALSE; - if (prefBranch && - NS_SUCCEEDED(prefBranch->GetBoolPref(NS_NET_PREF_IDNSHOWPUNYCODE, - &showPunycode)) && showPunycode) { - prefBranch->SetBoolPref(NS_NET_PREF_IDNSHOWPUNYCODE, PR_FALSE); - nsCOMPtr idnSrv = - do_GetService(NS_IDNSERVICE_CONTRACTID); - if (idnSrv) { - PRBool isACE; - nsCAutoString utf8Host; - if (NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE && - NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))) - keywordSpec.Append(utf8Host); - else - keywordSpec.Append(host); - } - else - keywordSpec.Append(host); - prefBranch->SetBoolPref(NS_NET_PREF_IDNSHOWPUNYCODE, PR_TRUE); - } - else - keywordSpec.Append(host); + // + // If this string was passed through nsStandardURL by chance, then it + // may have been converted from UTF-8 to ACE, which would result in a + // completely bogus keyword query. Here we try to recover the + // original Unicode value, but this is not 100% correct since the + // value may have been normalized per the IDN normalization rules. + // + // Since we don't have access to the exact original string that was + // entered by the user, this will just have to do. + // + PRBool isACE; + nsCAutoString utf8Host; + nsCOMPtr idnSrv = + do_GetService(NS_IDNSERVICE_CONTRACTID); + if (idnSrv && + NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE && + NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))) + keywordSpec.Append(utf8Host); + else + keywordSpec.Append(host); NS_NewURI(getter_AddRefs(newURI), keywordSpec, nsnull); diff --git a/netwerk/base/src/nsStandardURL.cpp b/netwerk/base/src/nsStandardURL.cpp index 5d73d769d738..1b9ef1636b23 100644 --- a/netwerk/base/src/nsStandardURL.cpp +++ b/netwerk/base/src/nsStandardURL.cpp @@ -58,11 +58,12 @@ static NS_DEFINE_CID(kThisImplCID, NS_THIS_STANDARDURL_IMPL_CID); static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID); -nsIIDNService *nsStandardURL::gIDNService = nsnull; +nsIIDNService *nsStandardURL::gIDN = nsnull; nsICharsetConverterManager *nsStandardURL::gCharsetMgr = nsnull; PRBool nsStandardURL::gInitialized = PR_FALSE; PRBool nsStandardURL::gEscapeUTF8 = PR_TRUE; PRBool nsStandardURL::gAlwaysEncodeInUTF8 = PR_TRUE; +PRBool nsStandardURL::gShowPunycode = PR_FALSE; #if defined(PR_LOGGING) // @@ -135,6 +136,7 @@ end: #define NS_NET_PREF_ESCAPEUTF8 "network.standard-url.escape-utf8" #define NS_NET_PREF_ENABLEIDN "network.enableIDN" #define NS_NET_PREF_ALWAYSENCODEINUTF8 "network.standard-url.encode-utf8" +#define NS_NET_PREF_SHOWPUNYCODE "network.IDN_show_punycode" NS_IMPL_ISUPPORTS1(nsStandardURL::nsPrefObserver, nsIObserver) @@ -297,6 +299,7 @@ nsStandardURL::InitGlobalObjects() prefBranch->AddObserver(NS_NET_PREF_ESCAPEUTF8, obs.get(), PR_FALSE); prefBranch->AddObserver(NS_NET_PREF_ALWAYSENCODEINUTF8, obs.get(), PR_FALSE); prefBranch->AddObserver(NS_NET_PREF_ENABLEIDN, obs.get(), PR_FALSE); + prefBranch->AddObserver(NS_NET_PREF_SHOWPUNYCODE, obs.get(), PR_FALSE); PrefsChanged(prefBranch, nsnull); } @@ -305,7 +308,7 @@ nsStandardURL::InitGlobalObjects() void nsStandardURL::ShutdownGlobalObjects() { - NS_IF_RELEASE(gIDNService); + NS_IF_RELEASE(gIDN); NS_IF_RELEASE(gCharsetMgr); } @@ -379,16 +382,16 @@ nsStandardURL::NormalizeIDN(const nsCSubstring &host, nsCString &result) if (IsASCII(host)) { PRBool isACE; - if (gIDNService && - NS_SUCCEEDED(gIDNService->IsACE(host, &isACE)) && isACE && - NS_SUCCEEDED(gIDNService->ConvertACEtoUTF8(host, result))) { + if (gIDN && + NS_SUCCEEDED(gIDN->IsACE(host, &isACE)) && isACE && + NS_SUCCEEDED(ACEtoUTF8(host, result))) { mHostEncoding = eEncoding_UTF8; return PR_TRUE; } } else { mHostEncoding = eEncoding_UTF8; - if (gIDNService && NS_SUCCEEDED(gIDNService->Normalize(host, result))) { + if (gIDN && NS_SUCCEEDED(NormalizeUTF8(host, result))) { // normalization could result in an ASCII only hostname if (IsASCII(result)) mHostEncoding = eEncoding_ASCII; @@ -806,14 +809,14 @@ nsStandardURL::PrefsChanged(nsIPrefBranch *prefs, const char *pref) #define GOT_PREF(p, b) (NS_SUCCEEDED(prefs->GetBoolPref(p, &b))) if (PREF_CHANGED(NS_NET_PREF_ENABLEIDN)) { - NS_IF_RELEASE(gIDNService); + NS_IF_RELEASE(gIDN); if (GOT_PREF(NS_NET_PREF_ENABLEIDN, val) && val) { // initialize IDN nsCOMPtr serv(do_GetService(NS_IDNSERVICE_CONTRACTID)); if (serv) - NS_ADDREF(gIDNService = serv.get()); + NS_ADDREF(gIDN = serv.get()); } - LOG(("IDN support %s\n", gIDNService ? "enabled" : "disabled")); + LOG(("IDN support %s\n", gIDN ? "enabled" : "disabled")); } if (PREF_CHANGED(NS_NET_PREF_ESCAPEUTF8)) { @@ -827,9 +830,36 @@ nsStandardURL::PrefsChanged(nsIPrefBranch *prefs, const char *pref) gAlwaysEncodeInUTF8 = val; LOG(("encode in UTF-8 %s\n", gAlwaysEncodeInUTF8 ? "enabled" : "disabled")); } + + if (PREF_CHANGED(NS_NET_PREF_SHOWPUNYCODE)) { + if (GOT_PREF(NS_NET_PREF_SHOWPUNYCODE, val)) + gShowPunycode = val; + LOG(("show punycode %s\n", gShowPunycode ? "enabled" : "disabled")); + } #undef PREF_CHANGED #undef GOT_PREF } + +/* static */ nsresult +nsStandardURL::ACEtoUTF8(const nsCSubstring &host, nsCString &result) +{ + if (gShowPunycode) { + result = host; + return NS_OK; + } + + return gIDN->ConvertACEtoUTF8(host, result); +} + +/* static */ nsresult +nsStandardURL::NormalizeUTF8(const nsCSubstring &host, nsCString &result) +{ + if (gShowPunycode) + return gIDN->ConvertUTF8toACE(host, result); + + return gIDN->Normalize(host, result); +} + //---------------------------------------------------------------------------- // nsStandardURL::nsISupports //---------------------------------------------------------------------------- @@ -987,9 +1017,9 @@ nsStandardURL::GetAsciiHost(nsACString &result) return NS_OK; } - if (gIDNService) { + if (gIDN) { nsresult rv; - rv = gIDNService->ConvertUTF8toACE(Host(), result); + rv = gIDN->ConvertUTF8toACE(Host(), result); if (NS_SUCCEEDED(rv)) { mHostA = ToNewCString(result); return NS_OK; diff --git a/netwerk/base/src/nsStandardURL.h b/netwerk/base/src/nsStandardURL.h index 7641f630b5da..d1612df48ed2 100644 --- a/netwerk/base/src/nsStandardURL.h +++ b/netwerk/base/src/nsStandardURL.h @@ -218,6 +218,10 @@ private: static void PrefsChanged(nsIPrefBranch *prefs, const char *pref); + // IDN routines + static nsresult ACEtoUTF8(const nsCSubstring &in, nsCString &out); + static nsresult NormalizeUTF8(const nsCSubstring &in, nsCString &out); + // mSpec contains the normalized version of the URL spec (UTF-8 encoded). nsCString mSpec; PRInt32 mDefaultPort; @@ -262,11 +266,12 @@ private: // global objects. don't use COMPtr as its destructor will cause a // coredump if we leak it. - static nsIIDNService *gIDNService; + static nsIIDNService *gIDN; static nsICharsetConverterManager *gCharsetMgr; static PRBool gInitialized; static PRBool gEscapeUTF8; static PRBool gAlwaysEncodeInUTF8; + static PRBool gShowPunycode; }; #define NS_THIS_STANDARDURL_IMPL_CID \ diff --git a/netwerk/dns/src/nsIDNService.cpp b/netwerk/dns/src/nsIDNService.cpp index 04ffe23a9baf..b83b24bdf27a 100644 --- a/netwerk/dns/src/nsIDNService.cpp +++ b/netwerk/dns/src/nsIDNService.cpp @@ -56,7 +56,6 @@ static const PRUint32 kMaxDNSNodeLen = 63; #define NS_NET_PREF_IDNTESTBED "network.IDN_testbed" #define NS_NET_PREF_IDNPREFIX "network.IDN_prefix" -#define NS_NET_PREF_IDNSHOWPUNYCODE "network.IDN_show_punycode" //----------------------------------------------------------------------------- // nsIDNService @@ -74,7 +73,6 @@ nsresult nsIDNService::Init() if (prefInternal) { prefInternal->AddObserver(NS_NET_PREF_IDNTESTBED, this, PR_TRUE); prefInternal->AddObserver(NS_NET_PREF_IDNPREFIX, this, PR_TRUE); - prefInternal->AddObserver(NS_NET_PREF_IDNSHOWPUNYCODE, this, PR_TRUE); prefsChanged(prefInternal, nsnull); } return NS_OK; @@ -105,11 +103,6 @@ void nsIDNService::prefsChanged(nsIPrefBranch *prefBranch, const PRUnichar *pref if (NS_SUCCEEDED(rv) && prefix.Length() <= kACEPrefixLen) PL_strncpyz(nsIDNService::mACEPrefix, prefix.get(), kACEPrefixLen + 1); } - if (!pref || NS_LITERAL_STRING(NS_NET_PREF_IDNSHOWPUNYCODE).Equals(pref)) { - PRBool val; - if (NS_SUCCEEDED(prefBranch->GetBoolPref(NS_NET_PREF_IDNSHOWPUNYCODE, &val))) - mShowPunycode = val; - } } nsIDNService::nsIDNService() @@ -121,7 +114,6 @@ nsIDNService::nsIDNService() strcpy(mACEPrefix, kIDNSPrefix); mMultilingualTestBed = PR_FALSE; - mShowPunycode = PR_FALSE; if (idn_success != idn_nameprep_create(NULL, &mNamePrepHandle)) mNamePrepHandle = nsnull; @@ -192,7 +184,7 @@ NS_IMETHODIMP nsIDNService::ConvertACEtoUTF8(const nsACString & input, nsACStrin // ToUnicode never fails. If any step fails, then the original input // sequence is returned immediately in that step. - if (mShowPunycode || !IsASCII(input)) { + if (!IsASCII(input)) { _retval.Assign(input); return NS_OK; } @@ -255,9 +247,6 @@ NS_IMETHODIMP nsIDNService::Normalize(const nsACString & input, nsACString & out // protect against bogus input NS_ENSURE_TRUE(IsUTF8(input), NS_ERROR_UNEXPECTED); - if (mShowPunycode) - return ConvertUTF8toACE(input, output); - NS_ConvertUTF8toUTF16 inUTF16(input); normalizeFullStops(inUTF16); diff --git a/netwerk/dns/src/nsIDNService.h b/netwerk/dns/src/nsIDNService.h index ddad79ef2d7f..dfd21cce5349 100644 --- a/netwerk/dns/src/nsIDNService.h +++ b/netwerk/dns/src/nsIDNService.h @@ -77,7 +77,6 @@ private: void prefsChanged(nsIPrefBranch *prefBranch, const PRUnichar *pref); PRBool mMultilingualTestBed; // if true generates extra node for mulitlingual testbed - PRBool mShowPunycode; idn_nameprep_t mNamePrepHandle; nsCOMPtr mNormalizer; char mACEPrefix[kACEPrefixLen+1];