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