1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file defines specific implementation of BrowserDistribution class for
13 #include "base/logging.h"
14 #include "base/scoped_ptr.h"
15 #include "base/string_util.h"
17 #include "installer_util_strings.h"
21 // Gets the language from the OS. If we're unable to get the system language,
23 std::wstring
GetSystemLanguage() {
24 static std::wstring language
;
25 if (!language
.empty())
27 // We don't have ICU at this point, so we use win32 apis.
28 LCID id
= GetThreadLocale();
29 int length
= GetLocaleInfo(id
, LOCALE_SISO639LANGNAME
, 0, 0);
34 length
= GetLocaleInfo(id
, LOCALE_SISO639LANGNAME
,
35 WriteInto(&language
, length
), length
);
36 DCHECK(length
== language
.length() + 1);
37 StringToLowerASCII(&language
);
39 // Add the country if we need it.
41 length
= GetLocaleInfo(id
, LOCALE_SISO3166CTRYNAME
, 0, 0);
43 length
= GetLocaleInfo(id
, LOCALE_SISO3166CTRYNAME
,
44 WriteInto(&country
, length
), length
);
45 DCHECK(length
== country
.length() + 1);
46 StringToLowerASCII(&country
);
47 if (L
"en" == language
) {
48 if (L
"gb" == country
) {
49 language
.append(L
"-gb");
51 language
.append(L
"-us");
53 } else if (L
"es" == language
&& L
"es" != country
) {
54 language
.append(L
"-419");
55 } else if (L
"pt" == language
) {
56 if (L
"br" == country
) {
57 language
.append(L
"-br");
59 language
.append(L
"-pt");
61 } else if (L
"zh" == language
) {
62 if (L
"tw" == country
|| L
"mk" == country
|| L
"hk" == country
) {
63 language
.append(L
"-tw");
65 language
.append(L
"-cn");
76 // This method returns the appropriate language offset given the language as a
77 // string. Note: This method is not thread safe because of how we create
79 int GetLanguageOffset(const std::wstring
& language
) {
80 static std::map
<std::wstring
, int> offset_map
;
81 if (offset_map
.empty()) {
82 #if defined(GOOGLE_CHROME_BUILD)
83 offset_map
[L
"ar"] = IDS_L10N_OFFSET_AR
;
84 offset_map
[L
"bg"] = IDS_L10N_OFFSET_BG
;
85 offset_map
[L
"bn"] = IDS_L10N_OFFSET_BN
;
86 offset_map
[L
"ca"] = IDS_L10N_OFFSET_CA
;
87 offset_map
[L
"cs"] = IDS_L10N_OFFSET_CS
;
88 offset_map
[L
"da"] = IDS_L10N_OFFSET_DA
;
89 offset_map
[L
"de"] = IDS_L10N_OFFSET_DE
;
90 offset_map
[L
"el"] = IDS_L10N_OFFSET_EL
;
91 offset_map
[L
"en-gb"] = IDS_L10N_OFFSET_EN_GB
;
92 offset_map
[L
"en-us"] = IDS_L10N_OFFSET_EN_US
;
93 offset_map
[L
"es"] = IDS_L10N_OFFSET_ES
;
94 offset_map
[L
"es-419"] = IDS_L10N_OFFSET_ES_419
;
95 offset_map
[L
"et"] = IDS_L10N_OFFSET_ET
;
96 offset_map
[L
"fi"] = IDS_L10N_OFFSET_FI
;
97 offset_map
[L
"fil"] = IDS_L10N_OFFSET_FIL
;
98 offset_map
[L
"fr"] = IDS_L10N_OFFSET_FR
;
99 offset_map
[L
"gu"] = IDS_L10N_OFFSET_GU
;
100 offset_map
[L
"he"] = IDS_L10N_OFFSET_HE
;
101 offset_map
[L
"hi"] = IDS_L10N_OFFSET_HI
;
102 offset_map
[L
"hr"] = IDS_L10N_OFFSET_HR
;
103 offset_map
[L
"hu"] = IDS_L10N_OFFSET_HU
;
104 offset_map
[L
"id"] = IDS_L10N_OFFSET_ID
;
105 offset_map
[L
"it"] = IDS_L10N_OFFSET_IT
;
106 // Google web properties use iw for he. Handle both just to be safe.
107 offset_map
[L
"iw"] = IDS_L10N_OFFSET_HE
;
108 offset_map
[L
"ja"] = IDS_L10N_OFFSET_JA
;
109 offset_map
[L
"kn"] = IDS_L10N_OFFSET_KN
;
110 offset_map
[L
"ko"] = IDS_L10N_OFFSET_KO
;
111 offset_map
[L
"lt"] = IDS_L10N_OFFSET_LT
;
112 offset_map
[L
"lv"] = IDS_L10N_OFFSET_LV
;
113 offset_map
[L
"ml"] = IDS_L10N_OFFSET_ML
;
114 offset_map
[L
"mr"] = IDS_L10N_OFFSET_MR
;
115 // Google web properties use no for nb. Handle both just to be safe.
116 offset_map
[L
"nb"] = IDS_L10N_OFFSET_NO
;
117 offset_map
[L
"nl"] = IDS_L10N_OFFSET_NL
;
118 offset_map
[L
"no"] = IDS_L10N_OFFSET_NO
;
119 offset_map
[L
"pl"] = IDS_L10N_OFFSET_PL
;
120 offset_map
[L
"pt-br"] = IDS_L10N_OFFSET_PT_BR
;
121 offset_map
[L
"pt-pt"] = IDS_L10N_OFFSET_PT_PT
;
122 offset_map
[L
"ro"] = IDS_L10N_OFFSET_RO
;
123 offset_map
[L
"ru"] = IDS_L10N_OFFSET_RU
;
124 offset_map
[L
"sk"] = IDS_L10N_OFFSET_SK
;
125 offset_map
[L
"sl"] = IDS_L10N_OFFSET_SL
;
126 offset_map
[L
"sr"] = IDS_L10N_OFFSET_SR
;
127 offset_map
[L
"sv"] = IDS_L10N_OFFSET_SV
;
128 offset_map
[L
"ta"] = IDS_L10N_OFFSET_TA
;
129 offset_map
[L
"te"] = IDS_L10N_OFFSET_TE
;
130 offset_map
[L
"th"] = IDS_L10N_OFFSET_TH
;
131 // Some Google web properties use tl for fil. Handle both just to be safe.
132 // They're not completely identical, but alias it here.
133 offset_map
[L
"tl"] = IDS_L10N_OFFSET_FIL
;
134 offset_map
[L
"tr"] = IDS_L10N_OFFSET_TR
;
135 offset_map
[L
"uk"] = IDS_L10N_OFFSET_UK
;
136 offset_map
[L
"vi"] = IDS_L10N_OFFSET_VI
;
137 offset_map
[L
"zh-cn"] = IDS_L10N_OFFSET_ZH_CN
;
138 offset_map
[L
"zh-tw"] = IDS_L10N_OFFSET_ZH_TW
;
139 #else // GOOGLE_CHROME_BUILD not defined
140 offset_map
[L
"en-us"] = IDS_L10N_OFFSET_EN_US
;
141 #endif // if defined(GOOGLE_CHROME_BUILD)
144 std::map
<std::wstring
, int>::iterator it
= offset_map
.find(
145 StringToLowerASCII(language
));
146 if (it
!= offset_map
.end())
149 #if defined(GOOGLE_CHROME_BUILD)
150 NOTREACHED() << "unknown system language-country";
151 #endif // if defined(GOOGLE_CHROME_BUILD)
153 // Fallback on the en-US offset just in case.
154 return IDS_L10N_OFFSET_EN_US
;
159 namespace installer_util
{
161 std::wstring
GetLocalizedString(int base_message_id
) {
162 std::wstring language
= GetSystemLanguage();
163 std::wstring localized_string
;
165 int message_id
= base_message_id
+ GetLanguageOffset(language
);
166 const ATLSTRINGRESOURCEIMAGE
* image
= AtlGetStringResourceImage(
167 _AtlBaseModule
.GetModuleInstance(), message_id
);
169 localized_string
= std::wstring(image
->achString
, image
->nLength
);
171 NOTREACHED() << "Unable to find resource id " << message_id
;
174 return localized_string
;
177 // Here we generate the url spec with the Microsoft res:// scheme which is
178 // explained here : http://support.microsoft.com/kb/220830
179 std::wstring
GetLocalizedEulaResource() {
180 wchar_t full_exe_path
[MAX_PATH
];
181 int len
= ::GetModuleFileName(NULL
, full_exe_path
, MAX_PATH
);
182 if (len
== 0 || len
== MAX_PATH
)
184 std::wstring language
= GetSystemLanguage();
185 const wchar_t* resource
= L
"IDR_OEMPG_EN.HTML";
187 static std::map
<int, wchar_t*> html_map
;
188 if (html_map
.empty()) {
189 #if defined(GOOGLE_CHROME_BUILD)
190 html_map
[IDS_L10N_OFFSET_AR
] = L
"IDR_OEMPG_AR.HTML";
191 html_map
[IDS_L10N_OFFSET_BG
] = L
"IDR_OEMPG_BG.HTML";
192 html_map
[IDS_L10N_OFFSET_CA
] = L
"IDR_OEMPG_CA.HTML";
193 html_map
[IDS_L10N_OFFSET_CS
] = L
"IDR_OEMPG_CS.HTML";
194 html_map
[IDS_L10N_OFFSET_DA
] = L
"IDR_OEMPG_DA.HTML";
195 html_map
[IDS_L10N_OFFSET_DE
] = L
"IDR_OEMPG_DE.HTML";
196 html_map
[IDS_L10N_OFFSET_EL
] = L
"IDR_OEMPG_EL.HTML";
197 html_map
[IDS_L10N_OFFSET_EN_US
] = L
"IDR_OEMPG_EN.HTML";
198 html_map
[IDS_L10N_OFFSET_EN_GB
] = L
"IDR_OEMPG_EN_GB.HTML";
199 html_map
[IDS_L10N_OFFSET_ES
] = L
"IDR_OEMPG_ES.HTML";
200 html_map
[IDS_L10N_OFFSET_ES_419
] = L
"IDR_OEMPG_ES_419.HTML";
201 html_map
[IDS_L10N_OFFSET_ET
] = L
"IDR_OEMPG_ET.HTML";
202 html_map
[IDS_L10N_OFFSET_FI
] = L
"IDR_OEMPG_FI.HTML";
203 html_map
[IDS_L10N_OFFSET_FIL
] = L
"IDR_OEMPG_FIL.HTML";
204 html_map
[IDS_L10N_OFFSET_FR
] = L
"IDR_OEMPG_FR.HTML";
205 html_map
[IDS_L10N_OFFSET_HI
] = L
"IDR_OEMPG_HI.HTML";
206 html_map
[IDS_L10N_OFFSET_HR
] = L
"IDR_OEMPG_HR.HTML";
207 html_map
[IDS_L10N_OFFSET_HU
] = L
"IDR_OEMPG_HU.HTML";
208 html_map
[IDS_L10N_OFFSET_ID
] = L
"IDR_OEMPG_ID.HTML";
209 html_map
[IDS_L10N_OFFSET_IT
] = L
"IDR_OEMPG_IT.HTML";
210 html_map
[IDS_L10N_OFFSET_JA
] = L
"IDR_OEMPG_JA.HTML";
211 html_map
[IDS_L10N_OFFSET_KO
] = L
"IDR_OEMPG_KO.HTML";
212 html_map
[IDS_L10N_OFFSET_LT
] = L
"IDR_OEMPG_LT.HTML";
213 html_map
[IDS_L10N_OFFSET_LV
] = L
"IDR_OEMPG_LV.HTML";
214 html_map
[IDS_L10N_OFFSET_NL
] = L
"IDR_OEMPG_NL.HTML";
215 html_map
[IDS_L10N_OFFSET_NO
] = L
"IDR_OEMPG_NO.HTML";
216 html_map
[IDS_L10N_OFFSET_PL
] = L
"IDR_OEMPG_PL.HTML";
217 html_map
[IDS_L10N_OFFSET_PT_BR
] = L
"IDR_OEMPG_PT_BR.HTML";
218 html_map
[IDS_L10N_OFFSET_PT_PT
] = L
"IDR_OEMPG_PT_PT.HTML";
219 html_map
[IDS_L10N_OFFSET_RO
] = L
"IDR_OEMPG_RO.HTML";
220 html_map
[IDS_L10N_OFFSET_RU
] = L
"IDR_OEMPG_RU.HTML";
221 html_map
[IDS_L10N_OFFSET_SK
] = L
"IDR_OEMPG_SK.HTML";
222 html_map
[IDS_L10N_OFFSET_SL
] = L
"IDR_OEMPG_SL.HTML";
223 html_map
[IDS_L10N_OFFSET_SR
] = L
"IDR_OEMPG_SR.HTML";
224 html_map
[IDS_L10N_OFFSET_SV
] = L
"IDR_OEMPG_SV.HTML";
225 html_map
[IDS_L10N_OFFSET_TH
] = L
"IDR_OEMPG_TH.HTML";
226 html_map
[IDS_L10N_OFFSET_TR
] = L
"IDR_OEMPG_TR.HTML";
227 html_map
[IDS_L10N_OFFSET_UK
] = L
"IDR_OEMPG_UK.HTML";
228 html_map
[IDS_L10N_OFFSET_VI
] = L
"IDR_OEMPG_VI.HTML";
229 html_map
[IDS_L10N_OFFSET_ZH_CN
] = L
"IDR_OEMPG_ZH_CN.HTML";
230 html_map
[IDS_L10N_OFFSET_ZH_TW
] = L
"IDR_OEMPG_ZH_TW.HTML";
231 #else // GOOGLE_CHROME_BUILD not defined
232 html_map
[IDS_L10N_OFFSET_EN_US
] = L
"IDR_OEMPG_EN.HTML";
233 #endif // if defined(GOOGLE_CHROME_BUILD)
236 std::map
<int, wchar_t*>::iterator it
= html_map
.find(
237 GetLanguageOffset(language
));
238 if (it
!= html_map
.end())
239 resource
= it
->second
;
241 // Spaces and DOS paths must be url encoded.
242 std::wstring url_path
=
243 StringPrintf(L
"res://%ls/#23/%ls", full_exe_path
, resource
);
245 // The cast is safe because url_path has limited length
246 // (see the definition of full_exe_path and resource).
247 DCHECK(kuint32max
> (url_path
.size() * 3));
248 DWORD count
= static_cast<DWORD
>(url_path
.size() * 3);
249 scoped_array
<wchar_t> url_canon(new wchar_t[count
]);
250 HRESULT hr
= ::UrlCanonicalizeW(url_path
.c_str(), url_canon
.get(),
251 &count
, URL_ESCAPE_UNSAFE
);
253 return std::wstring(url_canon
.get());
257 } // namespace installer_util