summaryrefslogtreecommitdiffstats
path: root/url/url_canon_icu.cc
diff options
context:
space:
mode:
authorjshin@chromium.org <jshin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-29 10:52:50 +0000
committerjshin@chromium.org <jshin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-29 10:52:50 +0000
commit18f00cd7013b44d0015cfdca3385fa3aeecf99fb (patch)
tree0226419c695ab9b38922ee688b98100fff3920c0 /url/url_canon_icu.cc
parent6d066c94c5329c4f3cdc567c4a2508a8178349be (diff)
downloadchromium_src-18f00cd7013b44d0015cfdca3385fa3aeecf99fb.zip
chromium_src-18f00cd7013b44d0015cfdca3385fa3aeecf99fb.tar.gz
chromium_src-18f00cd7013b44d0015cfdca3385fa3aeecf99fb.tar.bz2
Support IDNA 2008 with UTS46.
UTS 46 provides a migration path from IDNA 2003 to IDNA 2008. 1. Use the up-to-date Unicode data; new characters were added and some case-folding/mapping have changed since Unicode 3.2 on which IDNA 2003 is based. 2. Define a case folding/mapping as is the case with IDNA 2003. 3. Use transitional mechanism for 4 deviant characters : German sharp-S, Greek final-sigma, ZWJ and ZWNJ. That is, the former two are mapped to 'ss' and regular sigma and the latter two are dropped. All the major browsers do this at the moment so allowing them does not do any good. We'll review this later as the consensus builds among browser vendors and registrars. We can also consider handling them separately. For instance, ZWJ/ZWNJ can be allowed with ContextJ rules, which requires a minor change in ICU's UTS 46 implementation. 4. Symbol and punctuations continue to be allowed. We also do the following: 1. Continue to "violate" STD3 rules about non-LDH (Letter, digits and hyphens) by allowing non-LDH's. That is no change from the current implementation. 2. Do not allow unassigned code points any more. With an up-to-date Unicode data, this does not make much difference. And the chance of new characters not yet reflected in our Unicode data popping up in a domain name is extremely low. 3. Continue to use CHECK_BIDI. The Bidi rule in IDNA 2008 is more permissive than in IDNA 2003. References: 1. http://unicode.org/reports/tr46/ and references therein to IDNA 2003 and 2008 RFCs. 2. What IE 10 does : http://goo.gl/3XBhqw 3. Mozilla bug : https://bugzilla.mozilla.org/show_bug.cgi?id=479520 BUG=61328 TEST=url_unittests (URLCanonTest.Host), net_unittests (NetUtilTest.IDNToU*), unittests (X509CertificateModelTest.*) R=brettw@chromium.org, pkasting@chromium.org, rsleevi@chromium.org, thakis@chromium.org Review URL: https://codereview.chromium.org/23642003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225878 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'url/url_canon_icu.cc')
-rw-r--r--url/url_canon_icu.cc66
1 files changed, 56 insertions, 10 deletions
diff --git a/url/url_canon_icu.cc b/url/url_canon_icu.cc
index 8d6bdfc..cabbbf2 100644
--- a/url/url_canon_icu.cc
+++ b/url/url_canon_icu.cc
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "third_party/icu/source/common/unicode/ucnv.h"
#include "third_party/icu/source/common/unicode/ucnv_cb.h"
@@ -71,6 +72,40 @@ class AppendHandlerInstaller {
const void* old_context_;
};
+// A wrapper to use LazyInstance<>::Leaky with ICU's UIDNA, a C pointer to
+// a UTS46/IDNA 2008 handling object opened with uidna_openUTS46().
+//
+// We use UTS46 with BiDiCheck to migrate from IDNA 2003 (with unassigned
+// code points allowed) to IDNA 2008 with
+// the backward compatibility in mind. What it does:
+//
+// 1. Use the up-to-date Unicode data.
+// 2. Define a case folding/mapping with the up-to-date Unicode data as
+// in IDNA 2003.
+// 3. Use transitional mechanism for 4 deviation characters (sharp-s,
+// final sigma, ZWJ and ZWNJ) for now.
+// 4. Continue to allow symbols and punctuations.
+// 5. Apply new BiDi check rules more permissive than the IDNA 2003 BiDI rules.
+// 6. Do not apply STD3 rules
+// 7. Do not allow unassigned code points.
+//
+// It also closely matches what IE 10 does except for the BiDi check (
+// http://goo.gl/3XBhqw ).
+// See http://http://unicode.org/reports/tr46/ and references therein
+// for more details.
+struct UIDNAWrapper {
+ UIDNAWrapper() {
+ UErrorCode err = U_ZERO_ERROR;
+ // TODO(jungshik): Change options as different parties (browsers,
+ // registrars, search engines) converge toward a consensus.
+ value = uidna_openUTS46(UIDNA_CHECK_BIDI, &err);
+ if (U_FAILURE(err))
+ value = NULL;
+ }
+
+ UIDNA* value;
+};
+
} // namespace
ICUCharsetConverter::ICUCharsetConverter(UConverter* converter)
@@ -107,6 +142,9 @@ void ICUCharsetConverter::ConvertFromUTF16(const base::char16* input,
} while (true);
}
+static base::LazyInstance<UIDNAWrapper>::Leaky
+ g_uidna = LAZY_INSTANCE_INITIALIZER;
+
// Converts the Unicode input representing a hostname to ASCII using IDN rules.
// The output must be ASCII, but is represented as wide characters.
//
@@ -116,25 +154,33 @@ void ICUCharsetConverter::ConvertFromUTF16(const base::char16* input,
// the length of the output will be set to the length of the new host name.
//
// On error, this will return false. The output in this case is undefined.
+// TODO(jungshik): use UTF-8/ASCII version of nameToASCII.
+// Change the function signature and callers accordingly to avoid unnecessary
+// conversions in our code. In addition, consider using icu::IDNA's UTF-8/ASCII
+// version with StringByteSink. That way, we can avoid C wrappers and additional
+// string conversion.
bool IDNToASCII(const base::char16* src, int src_len, CanonOutputW* output) {
DCHECK(output->length() == 0); // Output buffer is assumed empty.
+
+ UIDNA* uidna = g_uidna.Get().value;
+ DCHECK(uidna != NULL);
while (true) {
- // Use ALLOW_UNASSIGNED to be more tolerant of hostnames that violate
- // the spec (which do exist). This does not present any risk and is a
- // little more future proof.
UErrorCode err = U_ZERO_ERROR;
- int num_converted = uidna_IDNToASCII(src, src_len, output->data(),
- output->capacity(),
- UIDNA_ALLOW_UNASSIGNED, NULL, &err);
- if (err == U_ZERO_ERROR) {
- output->set_length(num_converted);
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ int output_length = uidna_nameToASCII(uidna, src, src_len, output->data(),
+ output->capacity(), &info, &err);
+ if (U_SUCCESS(err) && info.errors == 0) {
+ output->set_length(output_length);
return true;
}
- if (err != U_BUFFER_OVERFLOW_ERROR)
+
+ // TODO(jungshik): Look at info.errors to handle them case-by-case basis
+ // if necessary.
+ if (err != U_BUFFER_OVERFLOW_ERROR || info.errors != 0)
return false; // Unknown error, give up.
// Not enough room in our buffer, expand.
- output->Resize(output->capacity() * 2);
+ output->Resize(output_length);
}
}