xref: /aosp_15_r20/external/libchrome/base/i18n/icu_util.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/i18n/icu_util.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
8*635a8641SAndroid Build Coastguard Worker #include <windows.h>
9*635a8641SAndroid Build Coastguard Worker #endif
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include <string>
12*635a8641SAndroid Build Coastguard Worker 
13*635a8641SAndroid Build Coastguard Worker #include "base/debug/alias.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/files/file_path.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/files/memory_mapped_file.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/path_service.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/strings/sys_string_conversions.h"
20*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
21*635a8641SAndroid Build Coastguard Worker #include "third_party/icu/source/common/unicode/putil.h"
22*635a8641SAndroid Build Coastguard Worker #include "third_party/icu/source/common/unicode/udata.h"
23*635a8641SAndroid Build Coastguard Worker #if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_ANDROID)
24*635a8641SAndroid Build Coastguard Worker #include "third_party/icu/source/i18n/unicode/timezone.h"
25*635a8641SAndroid Build Coastguard Worker #endif
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
28*635a8641SAndroid Build Coastguard Worker #include "base/android/apk_assets.h"
29*635a8641SAndroid Build Coastguard Worker #include "base/android/timezone_utils.h"
30*635a8641SAndroid Build Coastguard Worker #endif
31*635a8641SAndroid Build Coastguard Worker 
32*635a8641SAndroid Build Coastguard Worker #if defined(OS_IOS)
33*635a8641SAndroid Build Coastguard Worker #include "base/ios/ios_util.h"
34*635a8641SAndroid Build Coastguard Worker #endif
35*635a8641SAndroid Build Coastguard Worker 
36*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
37*635a8641SAndroid Build Coastguard Worker #include "base/mac/foundation_util.h"
38*635a8641SAndroid Build Coastguard Worker #endif
39*635a8641SAndroid Build Coastguard Worker 
40*635a8641SAndroid Build Coastguard Worker #if defined(OS_FUCHSIA)
41*635a8641SAndroid Build Coastguard Worker #include "base/base_paths_fuchsia.h"
42*635a8641SAndroid Build Coastguard Worker #endif
43*635a8641SAndroid Build Coastguard Worker 
44*635a8641SAndroid Build Coastguard Worker namespace base {
45*635a8641SAndroid Build Coastguard Worker namespace i18n {
46*635a8641SAndroid Build Coastguard Worker 
47*635a8641SAndroid Build Coastguard Worker #if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED
48*635a8641SAndroid Build Coastguard Worker #define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat"
49*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
50*635a8641SAndroid Build Coastguard Worker #define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt.dll"
51*635a8641SAndroid Build Coastguard Worker #endif
52*635a8641SAndroid Build Coastguard Worker #endif
53*635a8641SAndroid Build Coastguard Worker 
54*635a8641SAndroid Build Coastguard Worker namespace {
55*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL)
56*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
57*635a8641SAndroid Build Coastguard Worker // Assert that we are not called more than once.  Even though calling this
58*635a8641SAndroid Build Coastguard Worker // function isn't harmful (ICU can handle it), being called twice probably
59*635a8641SAndroid Build Coastguard Worker // indicates a programming error.
60*635a8641SAndroid Build Coastguard Worker bool g_check_called_once = true;
61*635a8641SAndroid Build Coastguard Worker bool g_called_once = false;
62*635a8641SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
63*635a8641SAndroid Build Coastguard Worker 
64*635a8641SAndroid Build Coastguard Worker #if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
65*635a8641SAndroid Build Coastguard Worker 
66*635a8641SAndroid Build Coastguard Worker // To debug http://crbug.com/445616.
67*635a8641SAndroid Build Coastguard Worker int g_debug_icu_last_error;
68*635a8641SAndroid Build Coastguard Worker int g_debug_icu_load;
69*635a8641SAndroid Build Coastguard Worker int g_debug_icu_pf_error_details;
70*635a8641SAndroid Build Coastguard Worker int g_debug_icu_pf_last_error;
71*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
72*635a8641SAndroid Build Coastguard Worker wchar_t g_debug_icu_pf_filename[_MAX_PATH];
73*635a8641SAndroid Build Coastguard Worker #endif  // OS_WIN
74*635a8641SAndroid Build Coastguard Worker // Use an unversioned file name to simplify a icu version update down the road.
75*635a8641SAndroid Build Coastguard Worker // No need to change the filename in multiple places (gyp files, windows
76*635a8641SAndroid Build Coastguard Worker // build pkg configurations, etc). 'l' stands for Little Endian.
77*635a8641SAndroid Build Coastguard Worker // This variable is exported through the header file.
78*635a8641SAndroid Build Coastguard Worker const char kIcuDataFileName[] = "icudtl.dat";
79*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
80*635a8641SAndroid Build Coastguard Worker const char kAndroidAssetsIcuDataFileName[] = "assets/icudtl.dat";
81*635a8641SAndroid Build Coastguard Worker #endif
82*635a8641SAndroid Build Coastguard Worker 
83*635a8641SAndroid Build Coastguard Worker // File handle intentionally never closed. Not using File here because its
84*635a8641SAndroid Build Coastguard Worker // Windows implementation guards against two instances owning the same
85*635a8641SAndroid Build Coastguard Worker // PlatformFile (which we allow since we know it is never freed).
86*635a8641SAndroid Build Coastguard Worker PlatformFile g_icudtl_pf = kInvalidPlatformFile;
87*635a8641SAndroid Build Coastguard Worker MemoryMappedFile* g_icudtl_mapped_file = nullptr;
88*635a8641SAndroid Build Coastguard Worker MemoryMappedFile::Region g_icudtl_region;
89*635a8641SAndroid Build Coastguard Worker 
LazyInitIcuDataFile()90*635a8641SAndroid Build Coastguard Worker void LazyInitIcuDataFile() {
91*635a8641SAndroid Build Coastguard Worker   if (g_icudtl_pf != kInvalidPlatformFile) {
92*635a8641SAndroid Build Coastguard Worker     return;
93*635a8641SAndroid Build Coastguard Worker   }
94*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
95*635a8641SAndroid Build Coastguard Worker   int fd = base::android::OpenApkAsset(kAndroidAssetsIcuDataFileName,
96*635a8641SAndroid Build Coastguard Worker                                        &g_icudtl_region);
97*635a8641SAndroid Build Coastguard Worker   g_icudtl_pf = fd;
98*635a8641SAndroid Build Coastguard Worker   if (fd != -1) {
99*635a8641SAndroid Build Coastguard Worker     return;
100*635a8641SAndroid Build Coastguard Worker   }
101*635a8641SAndroid Build Coastguard Worker // For unit tests, data file is located on disk, so try there as a fallback.
102*635a8641SAndroid Build Coastguard Worker #endif  // defined(OS_ANDROID)
103*635a8641SAndroid Build Coastguard Worker #if !defined(OS_MACOSX)
104*635a8641SAndroid Build Coastguard Worker   FilePath data_path;
105*635a8641SAndroid Build Coastguard Worker   if (!PathService::Get(DIR_ASSETS, &data_path)) {
106*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << "Can't find " << kIcuDataFileName;
107*635a8641SAndroid Build Coastguard Worker     return;
108*635a8641SAndroid Build Coastguard Worker   }
109*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
110*635a8641SAndroid Build Coastguard Worker   // TODO(brucedawson): http://crbug.com/445616
111*635a8641SAndroid Build Coastguard Worker   wchar_t tmp_buffer[_MAX_PATH] = {0};
112*635a8641SAndroid Build Coastguard Worker   wcscpy_s(tmp_buffer, data_path.value().c_str());
113*635a8641SAndroid Build Coastguard Worker   debug::Alias(tmp_buffer);
114*635a8641SAndroid Build Coastguard Worker #endif
115*635a8641SAndroid Build Coastguard Worker   data_path = data_path.AppendASCII(kIcuDataFileName);
116*635a8641SAndroid Build Coastguard Worker 
117*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
118*635a8641SAndroid Build Coastguard Worker   // TODO(brucedawson): http://crbug.com/445616
119*635a8641SAndroid Build Coastguard Worker   wchar_t tmp_buffer2[_MAX_PATH] = {0};
120*635a8641SAndroid Build Coastguard Worker   wcscpy_s(tmp_buffer2, data_path.value().c_str());
121*635a8641SAndroid Build Coastguard Worker   debug::Alias(tmp_buffer2);
122*635a8641SAndroid Build Coastguard Worker #endif
123*635a8641SAndroid Build Coastguard Worker 
124*635a8641SAndroid Build Coastguard Worker #else  // !defined(OS_MACOSX)
125*635a8641SAndroid Build Coastguard Worker   // Assume it is in the framework bundle's Resources directory.
126*635a8641SAndroid Build Coastguard Worker   ScopedCFTypeRef<CFStringRef> data_file_name(
127*635a8641SAndroid Build Coastguard Worker       SysUTF8ToCFStringRef(kIcuDataFileName));
128*635a8641SAndroid Build Coastguard Worker   FilePath data_path = mac::PathForFrameworkBundleResource(data_file_name);
129*635a8641SAndroid Build Coastguard Worker #if defined(OS_IOS)
130*635a8641SAndroid Build Coastguard Worker   FilePath override_data_path = base::ios::FilePathOfEmbeddedICU();
131*635a8641SAndroid Build Coastguard Worker   if (!override_data_path.empty()) {
132*635a8641SAndroid Build Coastguard Worker     data_path = override_data_path;
133*635a8641SAndroid Build Coastguard Worker   }
134*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_IOS)
135*635a8641SAndroid Build Coastguard Worker   if (data_path.empty()) {
136*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << kIcuDataFileName << " not found in bundle";
137*635a8641SAndroid Build Coastguard Worker     return;
138*635a8641SAndroid Build Coastguard Worker   }
139*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_MACOSX)
140*635a8641SAndroid Build Coastguard Worker   File file(data_path, File::FLAG_OPEN | File::FLAG_READ);
141*635a8641SAndroid Build Coastguard Worker   if (file.IsValid()) {
142*635a8641SAndroid Build Coastguard Worker     // TODO(brucedawson): http://crbug.com/445616.
143*635a8641SAndroid Build Coastguard Worker     g_debug_icu_pf_last_error = 0;
144*635a8641SAndroid Build Coastguard Worker     g_debug_icu_pf_error_details = 0;
145*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
146*635a8641SAndroid Build Coastguard Worker     g_debug_icu_pf_filename[0] = 0;
147*635a8641SAndroid Build Coastguard Worker #endif  // OS_WIN
148*635a8641SAndroid Build Coastguard Worker 
149*635a8641SAndroid Build Coastguard Worker     g_icudtl_pf = file.TakePlatformFile();
150*635a8641SAndroid Build Coastguard Worker     g_icudtl_region = MemoryMappedFile::Region::kWholeFile;
151*635a8641SAndroid Build Coastguard Worker   }
152*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
153*635a8641SAndroid Build Coastguard Worker   else {
154*635a8641SAndroid Build Coastguard Worker     // TODO(brucedawson): http://crbug.com/445616.
155*635a8641SAndroid Build Coastguard Worker     g_debug_icu_pf_last_error = ::GetLastError();
156*635a8641SAndroid Build Coastguard Worker     g_debug_icu_pf_error_details = file.error_details();
157*635a8641SAndroid Build Coastguard Worker     wcscpy_s(g_debug_icu_pf_filename, data_path.value().c_str());
158*635a8641SAndroid Build Coastguard Worker   }
159*635a8641SAndroid Build Coastguard Worker #endif  // OS_WIN
160*635a8641SAndroid Build Coastguard Worker }
161*635a8641SAndroid Build Coastguard Worker 
InitializeICUWithFileDescriptorInternal(PlatformFile data_fd,const MemoryMappedFile::Region & data_region)162*635a8641SAndroid Build Coastguard Worker bool InitializeICUWithFileDescriptorInternal(
163*635a8641SAndroid Build Coastguard Worker     PlatformFile data_fd,
164*635a8641SAndroid Build Coastguard Worker     const MemoryMappedFile::Region& data_region) {
165*635a8641SAndroid Build Coastguard Worker   // This can be called multiple times in tests.
166*635a8641SAndroid Build Coastguard Worker   if (g_icudtl_mapped_file) {
167*635a8641SAndroid Build Coastguard Worker     g_debug_icu_load = 0;  // To debug http://crbug.com/445616.
168*635a8641SAndroid Build Coastguard Worker     return true;
169*635a8641SAndroid Build Coastguard Worker   }
170*635a8641SAndroid Build Coastguard Worker   if (data_fd == kInvalidPlatformFile) {
171*635a8641SAndroid Build Coastguard Worker     g_debug_icu_load = 1;  // To debug http://crbug.com/445616.
172*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid file descriptor to ICU data received.";
173*635a8641SAndroid Build Coastguard Worker     return false;
174*635a8641SAndroid Build Coastguard Worker   }
175*635a8641SAndroid Build Coastguard Worker 
176*635a8641SAndroid Build Coastguard Worker   std::unique_ptr<MemoryMappedFile> icudtl_mapped_file(new MemoryMappedFile());
177*635a8641SAndroid Build Coastguard Worker   if (!icudtl_mapped_file->Initialize(File(data_fd), data_region)) {
178*635a8641SAndroid Build Coastguard Worker     g_debug_icu_load = 2;  // To debug http://crbug.com/445616.
179*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << "Couldn't mmap icu data file";
180*635a8641SAndroid Build Coastguard Worker     return false;
181*635a8641SAndroid Build Coastguard Worker   }
182*635a8641SAndroid Build Coastguard Worker   g_icudtl_mapped_file = icudtl_mapped_file.release();
183*635a8641SAndroid Build Coastguard Worker 
184*635a8641SAndroid Build Coastguard Worker   UErrorCode err = U_ZERO_ERROR;
185*635a8641SAndroid Build Coastguard Worker   udata_setCommonData(const_cast<uint8_t*>(g_icudtl_mapped_file->data()), &err);
186*635a8641SAndroid Build Coastguard Worker   if (err != U_ZERO_ERROR) {
187*635a8641SAndroid Build Coastguard Worker     g_debug_icu_load = 3;  // To debug http://crbug.com/445616.
188*635a8641SAndroid Build Coastguard Worker     g_debug_icu_last_error = err;
189*635a8641SAndroid Build Coastguard Worker   }
190*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
191*635a8641SAndroid Build Coastguard Worker   else {
192*635a8641SAndroid Build Coastguard Worker     // On Android, we can't leave it up to ICU to set the default timezone
193*635a8641SAndroid Build Coastguard Worker     // because ICU's timezone detection does not work in many timezones (e.g.
194*635a8641SAndroid Build Coastguard Worker     // Australia/Sydney, Asia/Seoul, Europe/Paris ). Use JNI to detect the host
195*635a8641SAndroid Build Coastguard Worker     // timezone and set the ICU default timezone accordingly in advance of
196*635a8641SAndroid Build Coastguard Worker     // actual use. See crbug.com/722821 and
197*635a8641SAndroid Build Coastguard Worker     // https://ssl.icu-project.org/trac/ticket/13208 .
198*635a8641SAndroid Build Coastguard Worker     base::string16 timezone_id = base::android::GetDefaultTimeZoneId();
199*635a8641SAndroid Build Coastguard Worker     icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(
200*635a8641SAndroid Build Coastguard Worker         icu::UnicodeString(FALSE, timezone_id.data(), timezone_id.length())));
201*635a8641SAndroid Build Coastguard Worker   }
202*635a8641SAndroid Build Coastguard Worker #endif
203*635a8641SAndroid Build Coastguard Worker   // Never try to load ICU data from files.
204*635a8641SAndroid Build Coastguard Worker   udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
205*635a8641SAndroid Build Coastguard Worker   return err == U_ZERO_ERROR;
206*635a8641SAndroid Build Coastguard Worker }
207*635a8641SAndroid Build Coastguard Worker #endif  // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
208*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_NACL)
209*635a8641SAndroid Build Coastguard Worker 
210*635a8641SAndroid Build Coastguard Worker }  // namespace
211*635a8641SAndroid Build Coastguard Worker 
212*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL)
213*635a8641SAndroid Build Coastguard Worker #if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
214*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
InitializeICUWithFileDescriptor(PlatformFile data_fd,const MemoryMappedFile::Region & data_region)215*635a8641SAndroid Build Coastguard Worker bool InitializeICUWithFileDescriptor(
216*635a8641SAndroid Build Coastguard Worker     PlatformFile data_fd,
217*635a8641SAndroid Build Coastguard Worker     const MemoryMappedFile::Region& data_region) {
218*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
219*635a8641SAndroid Build Coastguard Worker   DCHECK(!g_check_called_once || !g_called_once);
220*635a8641SAndroid Build Coastguard Worker   g_called_once = true;
221*635a8641SAndroid Build Coastguard Worker #endif
222*635a8641SAndroid Build Coastguard Worker   return InitializeICUWithFileDescriptorInternal(data_fd, data_region);
223*635a8641SAndroid Build Coastguard Worker }
224*635a8641SAndroid Build Coastguard Worker 
GetIcuDataFileHandle(MemoryMappedFile::Region * out_region)225*635a8641SAndroid Build Coastguard Worker PlatformFile GetIcuDataFileHandle(MemoryMappedFile::Region* out_region) {
226*635a8641SAndroid Build Coastguard Worker   CHECK_NE(g_icudtl_pf, kInvalidPlatformFile);
227*635a8641SAndroid Build Coastguard Worker   *out_region = g_icudtl_region;
228*635a8641SAndroid Build Coastguard Worker   return g_icudtl_pf;
229*635a8641SAndroid Build Coastguard Worker }
230*635a8641SAndroid Build Coastguard Worker #endif
231*635a8641SAndroid Build Coastguard Worker 
GetRawIcuMemory()232*635a8641SAndroid Build Coastguard Worker const uint8_t* GetRawIcuMemory() {
233*635a8641SAndroid Build Coastguard Worker   CHECK(g_icudtl_mapped_file);
234*635a8641SAndroid Build Coastguard Worker   return g_icudtl_mapped_file->data();
235*635a8641SAndroid Build Coastguard Worker }
236*635a8641SAndroid Build Coastguard Worker 
InitializeICUFromRawMemory(const uint8_t * raw_memory)237*635a8641SAndroid Build Coastguard Worker bool InitializeICUFromRawMemory(const uint8_t* raw_memory) {
238*635a8641SAndroid Build Coastguard Worker #if !defined(COMPONENT_BUILD)
239*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
240*635a8641SAndroid Build Coastguard Worker   DCHECK(!g_check_called_once || !g_called_once);
241*635a8641SAndroid Build Coastguard Worker   g_called_once = true;
242*635a8641SAndroid Build Coastguard Worker #endif
243*635a8641SAndroid Build Coastguard Worker 
244*635a8641SAndroid Build Coastguard Worker   UErrorCode err = U_ZERO_ERROR;
245*635a8641SAndroid Build Coastguard Worker   udata_setCommonData(const_cast<uint8_t*>(raw_memory), &err);
246*635a8641SAndroid Build Coastguard Worker   // Never try to load ICU data from files.
247*635a8641SAndroid Build Coastguard Worker   udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
248*635a8641SAndroid Build Coastguard Worker   return err == U_ZERO_ERROR;
249*635a8641SAndroid Build Coastguard Worker #else
250*635a8641SAndroid Build Coastguard Worker   return true;
251*635a8641SAndroid Build Coastguard Worker #endif
252*635a8641SAndroid Build Coastguard Worker }
253*635a8641SAndroid Build Coastguard Worker 
254*635a8641SAndroid Build Coastguard Worker #endif  // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
255*635a8641SAndroid Build Coastguard Worker 
InitializeICU()256*635a8641SAndroid Build Coastguard Worker bool InitializeICU() {
257*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
258*635a8641SAndroid Build Coastguard Worker   DCHECK(!g_check_called_once || !g_called_once);
259*635a8641SAndroid Build Coastguard Worker   g_called_once = true;
260*635a8641SAndroid Build Coastguard Worker #endif
261*635a8641SAndroid Build Coastguard Worker 
262*635a8641SAndroid Build Coastguard Worker   bool result;
263*635a8641SAndroid Build Coastguard Worker #if (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED)
264*635a8641SAndroid Build Coastguard Worker   FilePath data_path;
265*635a8641SAndroid Build Coastguard Worker   PathService::Get(DIR_ASSETS, &data_path);
266*635a8641SAndroid Build Coastguard Worker   data_path = data_path.AppendASCII(ICU_UTIL_DATA_SHARED_MODULE_NAME);
267*635a8641SAndroid Build Coastguard Worker 
268*635a8641SAndroid Build Coastguard Worker   HMODULE module = LoadLibrary(data_path.value().c_str());
269*635a8641SAndroid Build Coastguard Worker   if (!module) {
270*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to load " << ICU_UTIL_DATA_SHARED_MODULE_NAME;
271*635a8641SAndroid Build Coastguard Worker     return false;
272*635a8641SAndroid Build Coastguard Worker   }
273*635a8641SAndroid Build Coastguard Worker 
274*635a8641SAndroid Build Coastguard Worker   FARPROC addr = GetProcAddress(module, ICU_UTIL_DATA_SYMBOL);
275*635a8641SAndroid Build Coastguard Worker   if (!addr) {
276*635a8641SAndroid Build Coastguard Worker     LOG(ERROR) << ICU_UTIL_DATA_SYMBOL << ": not found in "
277*635a8641SAndroid Build Coastguard Worker                << ICU_UTIL_DATA_SHARED_MODULE_NAME;
278*635a8641SAndroid Build Coastguard Worker     return false;
279*635a8641SAndroid Build Coastguard Worker   }
280*635a8641SAndroid Build Coastguard Worker 
281*635a8641SAndroid Build Coastguard Worker   UErrorCode err = U_ZERO_ERROR;
282*635a8641SAndroid Build Coastguard Worker   udata_setCommonData(reinterpret_cast<void*>(addr), &err);
283*635a8641SAndroid Build Coastguard Worker   // Never try to load ICU data from files.
284*635a8641SAndroid Build Coastguard Worker   udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
285*635a8641SAndroid Build Coastguard Worker   result = (err == U_ZERO_ERROR);
286*635a8641SAndroid Build Coastguard Worker #elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC)
287*635a8641SAndroid Build Coastguard Worker   // The ICU data is statically linked.
288*635a8641SAndroid Build Coastguard Worker   result = true;
289*635a8641SAndroid Build Coastguard Worker #elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
290*635a8641SAndroid Build Coastguard Worker   // If the ICU data directory is set, ICU won't actually load the data until
291*635a8641SAndroid Build Coastguard Worker   // it is needed.  This can fail if the process is sandboxed at that time.
292*635a8641SAndroid Build Coastguard Worker   // Instead, we map the file in and hand off the data so the sandbox won't
293*635a8641SAndroid Build Coastguard Worker   // cause any problems.
294*635a8641SAndroid Build Coastguard Worker   LazyInitIcuDataFile();
295*635a8641SAndroid Build Coastguard Worker   result =
296*635a8641SAndroid Build Coastguard Worker       InitializeICUWithFileDescriptorInternal(g_icudtl_pf, g_icudtl_region);
297*635a8641SAndroid Build Coastguard Worker #if defined(OS_WIN)
298*635a8641SAndroid Build Coastguard Worker   int debug_icu_load = g_debug_icu_load;
299*635a8641SAndroid Build Coastguard Worker   debug::Alias(&debug_icu_load);
300*635a8641SAndroid Build Coastguard Worker   int debug_icu_last_error = g_debug_icu_last_error;
301*635a8641SAndroid Build Coastguard Worker   debug::Alias(&debug_icu_last_error);
302*635a8641SAndroid Build Coastguard Worker   int debug_icu_pf_last_error = g_debug_icu_pf_last_error;
303*635a8641SAndroid Build Coastguard Worker   debug::Alias(&debug_icu_pf_last_error);
304*635a8641SAndroid Build Coastguard Worker   int debug_icu_pf_error_details = g_debug_icu_pf_error_details;
305*635a8641SAndroid Build Coastguard Worker   debug::Alias(&debug_icu_pf_error_details);
306*635a8641SAndroid Build Coastguard Worker   wchar_t debug_icu_pf_filename[_MAX_PATH] = {0};
307*635a8641SAndroid Build Coastguard Worker   wcscpy_s(debug_icu_pf_filename, g_debug_icu_pf_filename);
308*635a8641SAndroid Build Coastguard Worker   debug::Alias(&debug_icu_pf_filename);
309*635a8641SAndroid Build Coastguard Worker   CHECK(result);  // TODO(brucedawson): http://crbug.com/445616
310*635a8641SAndroid Build Coastguard Worker #endif
311*635a8641SAndroid Build Coastguard Worker #endif
312*635a8641SAndroid Build Coastguard Worker 
313*635a8641SAndroid Build Coastguard Worker // To respond to the timezone change properly, the default timezone
314*635a8641SAndroid Build Coastguard Worker // cache in ICU has to be populated on starting up.
315*635a8641SAndroid Build Coastguard Worker // TODO(jungshik): Some callers do not care about tz at all. If necessary,
316*635a8641SAndroid Build Coastguard Worker // add a boolean argument to this function to init'd the default tz only
317*635a8641SAndroid Build Coastguard Worker // when requested.
318*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
319*635a8641SAndroid Build Coastguard Worker   if (result)
320*635a8641SAndroid Build Coastguard Worker     std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
321*635a8641SAndroid Build Coastguard Worker #endif
322*635a8641SAndroid Build Coastguard Worker   return result;
323*635a8641SAndroid Build Coastguard Worker }
324*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_NACL)
325*635a8641SAndroid Build Coastguard Worker 
AllowMultipleInitializeCallsForTesting()326*635a8641SAndroid Build Coastguard Worker void AllowMultipleInitializeCallsForTesting() {
327*635a8641SAndroid Build Coastguard Worker #if DCHECK_IS_ON() && !defined(OS_NACL)
328*635a8641SAndroid Build Coastguard Worker   g_check_called_once = false;
329*635a8641SAndroid Build Coastguard Worker #endif
330*635a8641SAndroid Build Coastguard Worker }
331*635a8641SAndroid Build Coastguard Worker 
332*635a8641SAndroid Build Coastguard Worker }  // namespace i18n
333*635a8641SAndroid Build Coastguard Worker }  // namespace base
334