OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "chrome/renderer/localized_error.h" | |
6 | |
7 #include "base/i18n/rtl.h" | |
8 #include "base/logging.h" | |
9 #include "base/string16.h" | |
10 #include "base/string_number_conversions.h" | |
11 #include "base/utf_string_conversions.h" | |
12 #include "base/values.h" | |
13 #include "chrome/common/extensions/extension_icon_set.h" | |
14 #include "chrome/common/extensions/extension_set.h" | |
15 #include "content/public/renderer/render_thread.h" | |
16 #include "googleurl/src/gurl.h" | |
17 #include "grit/chromium_strings.h" | |
18 #include "grit/generated_resources.h" | |
19 #include "net/base/escape.h" | |
20 #include "net/base/net_errors.h" | |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLError.
h" | |
22 #include "ui/base/l10n/l10n_util.h" | |
23 #include "webkit/glue/webkit_glue.h" | |
24 | |
25 #if defined(OS_WIN) | |
26 #include "base/win/windows_version.h" | |
27 #endif | |
28 | |
29 using WebKit::WebURLError; | |
30 using content::RenderThread; | |
31 | |
32 namespace { | |
33 | |
34 static const char kRedirectLoopLearnMoreUrl[] = | |
35 "https://www.google.com/support/chrome/bin/answer.py?answer=95626"; | |
36 static const char kWeakDHKeyLearnMoreUrl[] = | |
37 "http://sites.google.com/a/chromium.org/dev/" | |
38 "err_ssl_weak_server_ephemeral_dh_key"; | |
39 static const char kESETLearnMoreUrl[] = | |
40 "http://kb.eset.com/esetkb/index?page=content&id=SOLN2588"; | |
41 #if defined(OS_CHROMEOS) | |
42 static const char kAppWarningLearnMoreUrl[] = | |
43 "chrome-extension://honijodknafkokifofgiaalefdiedpko/main.html" | |
44 "?answer=1721911"; | |
45 #endif // defined(OS_CHROMEOS) | |
46 | |
47 enum NAV_SUGGESTIONS { | |
48 SUGGEST_NONE = 0, | |
49 SUGGEST_RELOAD = 1 << 0, | |
50 SUGGEST_HOSTNAME = 1 << 1, | |
51 SUGGEST_CHECK_CONNECTION = 1 << 2, | |
52 SUGGEST_DNS_CONFIG = 1 << 3, | |
53 SUGGEST_FIREWALL_CONFIG = 1 << 4, | |
54 SUGGEST_PROXY_CONFIG = 1 << 5, | |
55 SUGGEST_DISABLE_EXTENSION = 1 << 6, | |
56 SUGGEST_LEARNMORE = 1 << 7, | |
57 }; | |
58 | |
59 struct LocalizedErrorMap { | |
60 int error_code; | |
61 unsigned int title_resource_id; | |
62 unsigned int heading_resource_id; | |
63 unsigned int summary_resource_id; | |
64 unsigned int details_resource_id; | |
65 int suggestions; // Bitmap of SUGGEST_* values. | |
66 }; | |
67 | |
68 const LocalizedErrorMap net_error_options[] = { | |
69 {net::ERR_TIMED_OUT, | |
70 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
71 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
72 IDS_ERRORPAGES_SUMMARY_TIMED_OUT, | |
73 IDS_ERRORPAGES_DETAILS_TIMED_OUT, | |
74 SUGGEST_RELOAD | SUGGEST_CHECK_CONNECTION | SUGGEST_FIREWALL_CONFIG | | |
75 SUGGEST_PROXY_CONFIG, | |
76 }, | |
77 {net::ERR_CONNECTION_TIMED_OUT, | |
78 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
79 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
80 IDS_ERRORPAGES_SUMMARY_TIMED_OUT, | |
81 IDS_ERRORPAGES_DETAILS_TIMED_OUT, | |
82 SUGGEST_RELOAD | SUGGEST_CHECK_CONNECTION | SUGGEST_FIREWALL_CONFIG | | |
83 SUGGEST_PROXY_CONFIG, | |
84 }, | |
85 {net::ERR_CONNECTION_CLOSED, | |
86 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
87 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
88 IDS_ERRORPAGES_SUMMARY_NOT_AVAILABLE, | |
89 IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED, | |
90 SUGGEST_RELOAD, | |
91 }, | |
92 {net::ERR_CONNECTION_RESET, | |
93 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
94 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
95 IDS_ERRORPAGES_SUMMARY_CONNECTION_RESET, | |
96 IDS_ERRORPAGES_DETAILS_CONNECTION_RESET, | |
97 SUGGEST_RELOAD | SUGGEST_CHECK_CONNECTION | SUGGEST_FIREWALL_CONFIG | | |
98 SUGGEST_PROXY_CONFIG, | |
99 }, | |
100 {net::ERR_CONNECTION_REFUSED, | |
101 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
102 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
103 IDS_ERRORPAGES_SUMMARY_CONNECTION_REFUSED, | |
104 IDS_ERRORPAGES_DETAILS_CONNECTION_REFUSED, | |
105 SUGGEST_RELOAD | SUGGEST_CHECK_CONNECTION | SUGGEST_FIREWALL_CONFIG | | |
106 SUGGEST_PROXY_CONFIG, | |
107 }, | |
108 {net::ERR_CONNECTION_FAILED, | |
109 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
110 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
111 IDS_ERRORPAGES_SUMMARY_NOT_AVAILABLE, | |
112 IDS_ERRORPAGES_DETAILS_CONNECTION_FAILED, | |
113 SUGGEST_RELOAD, | |
114 }, | |
115 {net::ERR_NAME_NOT_RESOLVED, | |
116 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
117 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
118 IDS_ERRORPAGES_SUMMARY_NAME_NOT_RESOLVED, | |
119 IDS_ERRORPAGES_DETAILS_NAME_NOT_RESOLVED, | |
120 SUGGEST_RELOAD | SUGGEST_CHECK_CONNECTION | SUGGEST_DNS_CONFIG | | |
121 SUGGEST_FIREWALL_CONFIG | SUGGEST_PROXY_CONFIG, | |
122 }, | |
123 {net::ERR_ADDRESS_UNREACHABLE, | |
124 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
125 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
126 IDS_ERRORPAGES_SUMMARY_ADDRESS_UNREACHABLE, | |
127 IDS_ERRORPAGES_DETAILS_ADDRESS_UNREACHABLE, | |
128 SUGGEST_RELOAD | SUGGEST_FIREWALL_CONFIG | SUGGEST_PROXY_CONFIG, | |
129 }, | |
130 {net::ERR_NETWORK_ACCESS_DENIED, | |
131 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
132 IDS_ERRORPAGES_HEADING_NETWORK_ACCESS_DENIED, | |
133 IDS_ERRORPAGES_SUMMARY_NETWORK_ACCESS_DENIED, | |
134 IDS_ERRORPAGES_DETAILS_NETWORK_ACCESS_DENIED, | |
135 SUGGEST_FIREWALL_CONFIG, | |
136 }, | |
137 {net::ERR_PROXY_CONNECTION_FAILED, | |
138 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
139 IDS_ERRORPAGES_HEADING_PROXY_CONNECTION_FAILED, | |
140 IDS_ERRORPAGES_SUMMARY_PROXY_CONNECTION_FAILED, | |
141 IDS_ERRORPAGES_DETAILS_PROXY_CONNECTION_FAILED, | |
142 SUGGEST_PROXY_CONFIG, | |
143 }, | |
144 {net::ERR_INTERNET_DISCONNECTED, | |
145 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
146 IDS_ERRORPAGES_HEADING_INTERNET_DISCONNECTED, | |
147 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED, | |
148 IDS_ERRORPAGES_DETAILS_INTERNET_DISCONNECTED, | |
149 SUGGEST_NONE, | |
150 }, | |
151 {net::ERR_FILE_NOT_FOUND, | |
152 IDS_ERRORPAGES_TITLE_NOT_FOUND, | |
153 IDS_ERRORPAGES_HEADING_NOT_FOUND, | |
154 IDS_ERRORPAGES_SUMMARY_NOT_FOUND, | |
155 IDS_ERRORPAGES_DETAILS_FILE_NOT_FOUND, | |
156 SUGGEST_NONE, | |
157 }, | |
158 {net::ERR_CACHE_MISS, | |
159 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
160 IDS_ERRORPAGES_HEADING_CACHE_MISS, | |
161 IDS_ERRORPAGES_SUMMARY_CACHE_MISS, | |
162 IDS_ERRORPAGES_DETAILS_CACHE_MISS, | |
163 SUGGEST_RELOAD, | |
164 }, | |
165 {net::ERR_CACHE_READ_FAILURE, | |
166 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
167 IDS_ERRORPAGES_HEADING_CACHE_READ_FAILURE, | |
168 IDS_ERRORPAGES_SUMMARY_CACHE_READ_FAILURE, | |
169 IDS_ERRORPAGES_DETAILS_CACHE_READ_FAILURE, | |
170 SUGGEST_RELOAD, | |
171 }, | |
172 {net::ERR_NETWORK_IO_SUSPENDED, | |
173 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
174 IDS_ERRORPAGES_HEADING_NETWORK_IO_SUSPENDED, | |
175 IDS_ERRORPAGES_SUMMARY_NETWORK_IO_SUSPENDED, | |
176 IDS_ERRORPAGES_DETAILS_NETWORK_IO_SUSPENDED, | |
177 SUGGEST_RELOAD, | |
178 }, | |
179 {net::ERR_TOO_MANY_REDIRECTS, | |
180 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
181 IDS_ERRORPAGES_HEADING_TOO_MANY_REDIRECTS, | |
182 IDS_ERRORPAGES_SUMMARY_TOO_MANY_REDIRECTS, | |
183 IDS_ERRORPAGES_DETAILS_TOO_MANY_REDIRECTS, | |
184 SUGGEST_RELOAD | SUGGEST_LEARNMORE, | |
185 }, | |
186 {net::ERR_EMPTY_RESPONSE, | |
187 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
188 IDS_ERRORPAGES_HEADING_EMPTY_RESPONSE, | |
189 IDS_ERRORPAGES_SUMMARY_EMPTY_RESPONSE, | |
190 IDS_ERRORPAGES_DETAILS_EMPTY_RESPONSE, | |
191 SUGGEST_RELOAD, | |
192 }, | |
193 {net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, | |
194 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
195 IDS_ERRORPAGES_HEADING_DUPLICATE_HEADERS, | |
196 IDS_ERRORPAGES_SUMMARY_DUPLICATE_HEADERS, | |
197 IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, | |
198 SUGGEST_NONE, | |
199 }, | |
200 {net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, | |
201 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
202 IDS_ERRORPAGES_HEADING_DUPLICATE_HEADERS, | |
203 IDS_ERRORPAGES_SUMMARY_DUPLICATE_HEADERS, | |
204 IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, | |
205 SUGGEST_NONE, | |
206 }, | |
207 {net::ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, | |
208 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
209 IDS_ERRORPAGES_HEADING_DUPLICATE_HEADERS, | |
210 IDS_ERRORPAGES_SUMMARY_DUPLICATE_HEADERS, | |
211 IDS_ERRORPAGES_DETAILS_RESPONSE_HEADERS_MULTIPLE_LOCATION, | |
212 SUGGEST_NONE, | |
213 }, | |
214 {net::ERR_CONTENT_LENGTH_MISMATCH, | |
215 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
216 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
217 IDS_ERRORPAGES_SUMMARY_NOT_AVAILABLE, | |
218 IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED, | |
219 SUGGEST_RELOAD, | |
220 }, | |
221 {net::ERR_INCOMPLETE_CHUNKED_ENCODING, | |
222 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
223 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
224 IDS_ERRORPAGES_SUMMARY_NOT_AVAILABLE, | |
225 IDS_ERRORPAGES_DETAILS_CONNECTION_CLOSED, | |
226 SUGGEST_RELOAD, | |
227 }, | |
228 {net::ERR_SSL_PROTOCOL_ERROR, | |
229 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
230 IDS_ERRORPAGES_HEADING_SSL_PROTOCOL_ERROR, | |
231 IDS_ERRORPAGES_SUMMARY_SSL_PROTOCOL_ERROR, | |
232 IDS_ERRORPAGES_DETAILS_SSL_PROTOCOL_ERROR, | |
233 SUGGEST_NONE, | |
234 }, | |
235 {net::ERR_SSL_UNSAFE_NEGOTIATION, | |
236 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
237 IDS_ERRORPAGES_HEADING_SSL_PROTOCOL_ERROR, | |
238 IDS_ERRORPAGES_SUMMARY_SSL_PROTOCOL_ERROR, | |
239 IDS_ERRORPAGES_DETAILS_SSL_UNSAFE_NEGOTIATION, | |
240 SUGGEST_NONE, | |
241 }, | |
242 {net::ERR_BAD_SSL_CLIENT_AUTH_CERT, | |
243 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
244 IDS_ERRORPAGES_HEADING_BAD_SSL_CLIENT_AUTH_CERT, | |
245 IDS_ERRORPAGES_SUMMARY_BAD_SSL_CLIENT_AUTH_CERT, | |
246 IDS_ERRORPAGES_DETAILS_BAD_SSL_CLIENT_AUTH_CERT, | |
247 SUGGEST_NONE, | |
248 }, | |
249 {net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY, | |
250 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
251 IDS_ERRORPAGES_HEADING_WEAK_SERVER_EPHEMERAL_DH_KEY, | |
252 IDS_ERRORPAGES_SUMMARY_WEAK_SERVER_EPHEMERAL_DH_KEY, | |
253 IDS_ERRORPAGES_DETAILS_SSL_PROTOCOL_ERROR, | |
254 SUGGEST_LEARNMORE, | |
255 }, | |
256 {net::ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION, | |
257 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
258 IDS_ERRORPAGES_HEADING_ESET_ANTI_VIRUS_SSL_INTERCEPTION, | |
259 IDS_ERRORPAGES_SUMMARY_ESET_ANTI_VIRUS_SSL_INTERCEPTION, | |
260 IDS_ERRORPAGES_DETAILS_SSL_PROTOCOL_ERROR, | |
261 SUGGEST_LEARNMORE, | |
262 }, | |
263 {net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN, | |
264 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
265 IDS_ERRORPAGES_HEADING_PINNING_FAILURE, | |
266 IDS_ERRORPAGES_SUMMARY_PINNING_FAILURE, | |
267 IDS_ERRORPAGES_DETAILS_PINNING_FAILURE, | |
268 SUGGEST_NONE, | |
269 }, | |
270 {net::ERR_TEMPORARILY_THROTTLED, | |
271 IDS_ERRORPAGES_TITLE_ACCESS_DENIED, | |
272 IDS_ERRORPAGES_HEADING_ACCESS_DENIED, | |
273 IDS_ERRORPAGES_SUMMARY_TEMPORARILY_THROTTLED, | |
274 IDS_ERRORPAGES_DETAILS_TEMPORARILY_THROTTLED, | |
275 SUGGEST_NONE, | |
276 }, | |
277 {net::ERR_BLOCKED_BY_CLIENT, | |
278 IDS_ERRORPAGES_TITLE_BLOCKED, | |
279 IDS_ERRORPAGES_HEADING_BLOCKED, | |
280 IDS_ERRORPAGES_SUMMARY_BLOCKED, | |
281 IDS_ERRORPAGES_DETAILS_BLOCKED, | |
282 SUGGEST_DISABLE_EXTENSION, | |
283 }, | |
284 }; | |
285 | |
286 const LocalizedErrorMap http_error_options[] = { | |
287 {403, | |
288 IDS_ERRORPAGES_TITLE_ACCESS_DENIED, | |
289 IDS_ERRORPAGES_HEADING_ACCESS_DENIED, | |
290 IDS_ERRORPAGES_SUMMARY_FORBIDDEN, | |
291 IDS_ERRORPAGES_DETAILS_FORBIDDEN, | |
292 SUGGEST_NONE, | |
293 }, | |
294 {410, | |
295 IDS_ERRORPAGES_TITLE_NOT_FOUND, | |
296 IDS_ERRORPAGES_HEADING_NOT_FOUND, | |
297 IDS_ERRORPAGES_SUMMARY_GONE, | |
298 IDS_ERRORPAGES_DETAILS_GONE, | |
299 SUGGEST_NONE, | |
300 }, | |
301 | |
302 {500, | |
303 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
304 IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, | |
305 IDS_ERRORPAGES_SUMMARY_INTERNAL_SERVER_ERROR, | |
306 IDS_ERRORPAGES_DETAILS_INTERNAL_SERVER_ERROR, | |
307 SUGGEST_RELOAD, | |
308 }, | |
309 {501, | |
310 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
311 IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, | |
312 IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE, | |
313 IDS_ERRORPAGES_DETAILS_NOT_IMPLEMENTED, | |
314 SUGGEST_NONE, | |
315 }, | |
316 {502, | |
317 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
318 IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, | |
319 IDS_ERRORPAGES_SUMMARY_BAD_GATEWAY, | |
320 IDS_ERRORPAGES_DETAILS_BAD_GATEWAY, | |
321 SUGGEST_RELOAD, | |
322 }, | |
323 {503, | |
324 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
325 IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, | |
326 IDS_ERRORPAGES_SUMMARY_SERVICE_UNAVAILABLE, | |
327 IDS_ERRORPAGES_DETAILS_SERVICE_UNAVAILABLE, | |
328 SUGGEST_RELOAD, | |
329 }, | |
330 {504, | |
331 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
332 IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, | |
333 IDS_ERRORPAGES_SUMMARY_GATEWAY_TIMEOUT, | |
334 IDS_ERRORPAGES_DETAILS_GATEWAY_TIMEOUT, | |
335 SUGGEST_RELOAD, | |
336 }, | |
337 {505, | |
338 IDS_ERRORPAGES_TITLE_LOAD_FAILED, | |
339 IDS_ERRORPAGES_HEADING_HTTP_SERVER_ERROR, | |
340 IDS_ERRORPAGES_SUMMARY_WEBSITE_CANNOT_HANDLE, | |
341 IDS_ERRORPAGES_DETAILS_HTTP_VERSION_NOT_SUPPORTED, | |
342 SUGGEST_NONE, | |
343 }, | |
344 }; | |
345 | |
346 const char* HttpErrorToString(int status_code) { | |
347 switch (status_code) { | |
348 case 403: | |
349 return "Forbidden"; | |
350 case 410: | |
351 return "Gone"; | |
352 case 500: | |
353 return "Internal Server Error"; | |
354 case 501: | |
355 return "Not Implemented"; | |
356 case 502: | |
357 return "Bad Gateway"; | |
358 case 503: | |
359 return "Service Unavailable"; | |
360 case 504: | |
361 return "Gateway Timeout"; | |
362 case 505: | |
363 return "HTTP Version Not Supported"; | |
364 default: | |
365 return ""; | |
366 } | |
367 } | |
368 | |
369 string16 GetErrorDetailsString(const std::string& error_domain, | |
370 int error_code, | |
371 const string16& details) { | |
372 int error_page_template; | |
373 const char* error_string; | |
374 if (error_domain == net::kErrorDomain) { | |
375 error_page_template = IDS_ERRORPAGES_DETAILS_TEMPLATE; | |
376 error_string = net::ErrorToString(error_code); | |
377 DCHECK(error_code < 0); // Net error codes are negative. | |
378 error_code = -error_code; | |
379 } else if (error_domain == LocalizedError::kHttpErrorDomain) { | |
380 error_page_template = IDS_ERRORPAGES_HTTP_DETAILS_TEMPLATE; | |
381 error_string = HttpErrorToString(error_code); | |
382 } else { | |
383 NOTREACHED(); | |
384 return string16(); | |
385 } | |
386 return l10n_util::GetStringFUTF16( | |
387 error_page_template, | |
388 base::IntToString16(error_code), | |
389 ASCIIToUTF16(error_string), | |
390 details); | |
391 } | |
392 | |
393 const LocalizedErrorMap* FindErrorMapInArray(const LocalizedErrorMap* maps, | |
394 size_t num_maps, | |
395 int error_code) { | |
396 for (size_t i = 0; i < num_maps; ++i) { | |
397 if (maps[i].error_code == error_code) | |
398 return &maps[i]; | |
399 } | |
400 return NULL; | |
401 } | |
402 | |
403 const LocalizedErrorMap* LookupErrorMap(const std::string& error_domain, | |
404 int error_code) { | |
405 if (error_domain == net::kErrorDomain) { | |
406 return FindErrorMapInArray(net_error_options, | |
407 arraysize(net_error_options), | |
408 error_code); | |
409 } else if (error_domain == LocalizedError::kHttpErrorDomain) { | |
410 return FindErrorMapInArray(http_error_options, | |
411 arraysize(http_error_options), | |
412 error_code); | |
413 } else { | |
414 NOTREACHED(); | |
415 return NULL; | |
416 } | |
417 } | |
418 | |
419 bool LocaleIsRTL() { | |
420 #if defined(TOOLKIT_GTK) | |
421 // base::i18n::IsRTL() uses the GTK text direction, which doesn't work within | |
422 // the renderer sandbox. | |
423 return base::i18n::ICUIsRTL(); | |
424 #else | |
425 return base::i18n::IsRTL(); | |
426 #endif | |
427 } | |
428 | |
429 // Returns a dictionary containing the strings for the settings menu under the | |
430 // wrench, and the advanced settings button. | |
431 DictionaryValue* GetStandardMenuItemsText() { | |
432 DictionaryValue* standard_menu_items_text = new DictionaryValue(); | |
433 standard_menu_items_text->SetString("settingsTitle", | |
434 l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE)); | |
435 standard_menu_items_text->SetString("advancedTitle", | |
436 l10n_util::GetStringUTF16(IDS_SETTINGS_SHOW_ADVANCED_SETTINGS)); | |
437 return standard_menu_items_text; | |
438 } | |
439 | |
440 } // namespace | |
441 | |
442 const char LocalizedError::kHttpErrorDomain[] = "http"; | |
443 | |
444 void LocalizedError::GetStrings(const WebKit::WebURLError& error, | |
445 DictionaryValue* error_strings) { | |
446 bool rtl = LocaleIsRTL(); | |
447 error_strings->SetString("textdirection", rtl ? "rtl" : "ltr"); | |
448 | |
449 // Grab the strings and settings that depend on the error type. Init | |
450 // options with default values. | |
451 LocalizedErrorMap options = { | |
452 0, | |
453 IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
454 IDS_ERRORPAGES_HEADING_NOT_AVAILABLE, | |
455 IDS_ERRORPAGES_SUMMARY_NOT_AVAILABLE, | |
456 IDS_ERRORPAGES_DETAILS_UNKNOWN, | |
457 SUGGEST_NONE, | |
458 }; | |
459 | |
460 const std::string error_domain = error.domain.utf8(); | |
461 int error_code = error.reason; | |
462 const LocalizedErrorMap* error_map = | |
463 LookupErrorMap(error_domain, error_code); | |
464 if (error_map) | |
465 options = *error_map; | |
466 | |
467 if (options.suggestions != SUGGEST_NONE) { | |
468 error_strings->SetString( | |
469 "suggestionsHeading", | |
470 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_HEADING)); | |
471 } | |
472 | |
473 const GURL failed_url = error.unreachableURL; | |
474 | |
475 // If we got "access denied" but the url was a file URL, then we say it was a | |
476 // file instead of just using the "not available" default message. Just adding | |
477 // ERR_ACCESS_DENIED to the map isn't sufficient, since that message may be | |
478 // generated by some OSs when the operation doesn't involve a file URL. | |
479 if (error_domain == net::kErrorDomain && | |
480 error_code == net::ERR_ACCESS_DENIED && | |
481 failed_url.scheme() == "file") { | |
482 options.title_resource_id = IDS_ERRORPAGES_TITLE_ACCESS_DENIED; | |
483 options.heading_resource_id = IDS_ERRORPAGES_HEADING_FILE_ACCESS_DENIED; | |
484 options.summary_resource_id = IDS_ERRORPAGES_SUMMARY_FILE_ACCESS_DENIED; | |
485 options.details_resource_id = IDS_ERRORPAGES_DETAILS_FILE_ACCESS_DENIED; | |
486 options.suggestions = SUGGEST_NONE; | |
487 } | |
488 | |
489 string16 failed_url_string(ASCIIToUTF16(failed_url.spec())); | |
490 // URLs are always LTR. | |
491 if (rtl) | |
492 base::i18n::WrapStringWithLTRFormatting(&failed_url_string); | |
493 error_strings->SetString("title", | |
494 l10n_util::GetStringFUTF16(options.title_resource_id, failed_url_string)); | |
495 error_strings->SetString("heading", | |
496 l10n_util::GetStringUTF16(options.heading_resource_id)); | |
497 | |
498 DictionaryValue* summary = new DictionaryValue; | |
499 summary->SetString("msg", | |
500 l10n_util::GetStringUTF16(options.summary_resource_id)); | |
501 // TODO(tc): We want the unicode url and host here since they're being | |
502 // displayed. | |
503 summary->SetString("failedUrl", failed_url_string); | |
504 summary->SetString("hostName", failed_url.host()); | |
505 summary->SetString("productName", | |
506 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | |
507 error_strings->Set("summary", summary); | |
508 | |
509 string16 details = l10n_util::GetStringUTF16(options.details_resource_id); | |
510 error_strings->SetString("details", | |
511 GetErrorDetailsString(error_domain, error_code, details)); | |
512 | |
513 // Platform specific instructions for diagnosing network issues on OSX and | |
514 // Windows. | |
515 #if defined(OS_MACOSX) || defined(OS_WIN) | |
516 if (error_domain == net::kErrorDomain && | |
517 error_code == net::ERR_INTERNET_DISCONNECTED) { | |
518 int platform_string_id = | |
519 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_PLATFORM; | |
520 #if defined(OS_WIN) | |
521 // Different versions of Windows have different instructions. | |
522 base::win::Version windows_version = base::win::GetVersion(); | |
523 if (windows_version < base::win::VERSION_VISTA) { | |
524 // XP, XP64, and Server 2003. | |
525 platform_string_id = | |
526 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_PLATFORM_XP; | |
527 } else if (windows_version == base::win::VERSION_VISTA) { | |
528 // Vista | |
529 platform_string_id = | |
530 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_PLATFORM_VISTA; | |
531 } | |
532 #endif // defined(OS_WIN) | |
533 // Lead with the general error description, and suffix with the platform | |
534 // dependent portion of the summary section. | |
535 summary->SetString("msg", | |
536 l10n_util::GetStringFUTF16( | |
537 IDS_ERRORPAGES_SUMMARY_INTERNET_DISCONNECTED_INSTRUCTIONS_TEMPLATE, | |
538 l10n_util::GetStringUTF16(options.summary_resource_id), | |
539 l10n_util::GetStringUTF16(platform_string_id))); | |
540 } | |
541 #endif // defined(OS_MACOSX) || defined(OS_WIN) | |
542 | |
543 if (options.suggestions & SUGGEST_RELOAD) { | |
544 DictionaryValue* suggest_reload = new DictionaryValue; | |
545 suggest_reload->SetString("msg", | |
546 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_RELOAD)); | |
547 suggest_reload->SetString("reloadUrl", failed_url_string); | |
548 error_strings->Set("suggestionsReload", suggest_reload); | |
549 } | |
550 | |
551 if (options.suggestions & SUGGEST_HOSTNAME) { | |
552 // Only show the "Go to hostname" suggestion if the failed_url has a path. | |
553 if (std::string() == failed_url.path()) { | |
554 DictionaryValue* suggest_home_page = new DictionaryValue; | |
555 suggest_home_page->SetString("suggestionsHomepageMsg", | |
556 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_HOMEPAGE)); | |
557 string16 homepage(ASCIIToUTF16(failed_url.GetWithEmptyPath().spec())); | |
558 // URLs are always LTR. | |
559 if (rtl) | |
560 base::i18n::WrapStringWithLTRFormatting(&homepage); | |
561 suggest_home_page->SetString("homePage", homepage); | |
562 // TODO(tc): we actually want the unicode hostname | |
563 suggest_home_page->SetString("hostName", failed_url.host()); | |
564 error_strings->Set("suggestionsHomepage", suggest_home_page); | |
565 } | |
566 } | |
567 | |
568 if (options.suggestions & SUGGEST_CHECK_CONNECTION) { | |
569 DictionaryValue* suggest_check_connection = new DictionaryValue; | |
570 suggest_check_connection->SetString("msg", | |
571 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_CHECK_CONNECTION)); | |
572 error_strings->Set("suggestionsCheckConnection", suggest_check_connection); | |
573 } | |
574 | |
575 if (options.suggestions & SUGGEST_DNS_CONFIG) { | |
576 DictionaryValue* suggest_dns_config = new DictionaryValue; | |
577 suggest_dns_config->SetString("msg", | |
578 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_DNS_CONFIG)); | |
579 error_strings->Set("suggestionsDNSConfig", suggest_dns_config); | |
580 | |
581 DictionaryValue* suggest_network_prediction = GetStandardMenuItemsText(); | |
582 suggest_network_prediction->SetString("msg", | |
583 l10n_util::GetStringUTF16( | |
584 IDS_ERRORPAGES_SUGGESTION_NETWORK_PREDICTION)); | |
585 suggest_network_prediction->SetString( | |
586 "noNetworkPredictionTitle", | |
587 l10n_util::GetStringUTF16( | |
588 IDS_NETWORK_PREDICTION_ENABLED_DESCRIPTION)); | |
589 error_strings->Set("suggestionsDisableNetworkPrediction", | |
590 suggest_network_prediction); | |
591 } | |
592 | |
593 if (options.suggestions & SUGGEST_FIREWALL_CONFIG) { | |
594 DictionaryValue* suggest_firewall_config = new DictionaryValue; | |
595 suggest_firewall_config->SetString("msg", | |
596 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_FIREWALL_CONFIG)); | |
597 suggest_firewall_config->SetString("productName", | |
598 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | |
599 error_strings->Set("suggestionsFirewallConfig", suggest_firewall_config); | |
600 } | |
601 | |
602 if (options.suggestions & SUGGEST_PROXY_CONFIG) { | |
603 #if defined(OS_CHROMEOS) | |
604 DictionaryValue* suggest_proxy_config = new DictionaryValue(); | |
605 #else | |
606 DictionaryValue* suggest_proxy_config = GetStandardMenuItemsText(); | |
607 #endif // defined(OS_CHROMEOS) | |
608 suggest_proxy_config->SetString("msg", | |
609 l10n_util::GetStringFUTF16(IDS_ERRORPAGES_SUGGESTION_PROXY_CONFIG, | |
610 l10n_util::GetStringUTF16( | |
611 IDS_ERRORPAGES_SUGGESTION_PROXY_DISABLE_PLATFORM))); | |
612 #if defined(OS_CHROMEOS) | |
613 suggest_proxy_config->SetString("settingsTitle", | |
614 l10n_util::GetStringUTF16(IDS_SETTINGS_TITLE)); | |
615 suggest_proxy_config->SetString("internetTitle", | |
616 l10n_util::GetStringUTF16(IDS_OPTIONS_INTERNET_TAB_LABEL)); | |
617 suggest_proxy_config->SetString("optionsButton", | |
618 l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OPTIONS)); | |
619 suggest_proxy_config->SetString("networkTab", | |
620 l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_INTERNET_TAB_NETWORK)); | |
621 suggest_proxy_config->SetString("proxyButton", | |
622 l10n_util::GetStringUTF16( | |
623 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CHANGE_PROXY_BUTTON)); | |
624 #else | |
625 suggest_proxy_config->SetString("proxyTitle", | |
626 l10n_util::GetStringUTF16(IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON)); | |
627 #endif // defined(OS_CHROMEOS) | |
628 error_strings->Set("suggestionsProxyConfig", suggest_proxy_config); | |
629 } | |
630 | |
631 if (options.suggestions & SUGGEST_DISABLE_EXTENSION) { | |
632 DictionaryValue* suggestion = new DictionaryValue; | |
633 suggestion->SetString("msg", | |
634 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_DISABLE_EXTENSION)); | |
635 suggestion->SetString("reloadUrl", failed_url_string); | |
636 error_strings->Set("suggestionsDisableExtension", suggestion); | |
637 } | |
638 | |
639 if (options.suggestions & SUGGEST_LEARNMORE) { | |
640 GURL learn_more_url; | |
641 switch (options.error_code) { | |
642 case net::ERR_TOO_MANY_REDIRECTS: | |
643 learn_more_url = GURL(kRedirectLoopLearnMoreUrl); | |
644 break; | |
645 case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: | |
646 learn_more_url = GURL(kWeakDHKeyLearnMoreUrl); | |
647 break; | |
648 case net::ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION: | |
649 learn_more_url = GURL(kESETLearnMoreUrl); | |
650 break; | |
651 default: | |
652 break; | |
653 } | |
654 | |
655 if (learn_more_url.is_valid()) { | |
656 // Add the language parameter to the URL. | |
657 std::string query = learn_more_url.query() + "&hl=" + | |
658 RenderThread::Get()->GetLocale(); | |
659 | |
660 GURL::Replacements repl; | |
661 repl.SetQueryStr(query); | |
662 learn_more_url = learn_more_url.ReplaceComponents(repl); | |
663 | |
664 DictionaryValue* suggest_learn_more = new DictionaryValue; | |
665 suggest_learn_more->SetString("msg", | |
666 l10n_util::GetStringUTF16(IDS_ERRORPAGES_SUGGESTION_LEARNMORE)); | |
667 suggest_learn_more->SetString("learnMoreUrl", learn_more_url.spec()); | |
668 error_strings->Set("suggestionsLearnMore", suggest_learn_more); | |
669 } | |
670 } | |
671 } | |
672 | |
673 string16 LocalizedError::GetErrorDetails(const WebKit::WebURLError& error) { | |
674 const LocalizedErrorMap* error_map = | |
675 LookupErrorMap(error.domain.utf8(), error.reason); | |
676 if (error_map) | |
677 return l10n_util::GetStringUTF16(error_map->details_resource_id); | |
678 else | |
679 return l10n_util::GetStringUTF16(IDS_ERRORPAGES_DETAILS_UNKNOWN); | |
680 } | |
681 | |
682 bool LocalizedError::HasStrings(const std::string& error_domain, | |
683 int error_code) { | |
684 return LookupErrorMap(error_domain, error_code) != NULL; | |
685 } | |
686 | |
687 void LocalizedError::GetFormRepostStrings(const GURL& display_url, | |
688 DictionaryValue* error_strings) { | |
689 bool rtl = LocaleIsRTL(); | |
690 error_strings->SetString("textdirection", rtl ? "rtl" : "ltr"); | |
691 | |
692 string16 failed_url(ASCIIToUTF16(display_url.spec())); | |
693 // URLs are always LTR. | |
694 if (rtl) | |
695 base::i18n::WrapStringWithLTRFormatting(&failed_url); | |
696 error_strings->SetString( | |
697 "title", l10n_util::GetStringFUTF16(IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
698 failed_url)); | |
699 error_strings->SetString( | |
700 "heading", l10n_util::GetStringUTF16(IDS_HTTP_POST_WARNING_TITLE)); | |
701 DictionaryValue* summary = new DictionaryValue; | |
702 summary->SetString( | |
703 "msg", l10n_util::GetStringUTF16(IDS_ERRORPAGES_HTTP_POST_WARNING)); | |
704 error_strings->Set("summary", summary); | |
705 } | |
706 | |
707 void LocalizedError::GetAppErrorStrings( | |
708 const WebURLError& error, | |
709 const GURL& display_url, | |
710 const extensions::Extension* app, | |
711 DictionaryValue* error_strings) { | |
712 DCHECK(app); | |
713 | |
714 bool rtl = LocaleIsRTL(); | |
715 error_strings->SetString("textdirection", rtl ? "rtl" : "ltr"); | |
716 | |
717 string16 failed_url(ASCIIToUTF16(display_url.spec())); | |
718 // URLs are always LTR. | |
719 if (rtl) | |
720 base::i18n::WrapStringWithLTRFormatting(&failed_url); | |
721 error_strings->SetString( | |
722 "url", l10n_util::GetStringFUTF16(IDS_ERRORPAGES_TITLE_NOT_AVAILABLE, | |
723 failed_url.c_str())); | |
724 | |
725 error_strings->SetString("title", app->name()); | |
726 error_strings->SetString("icon", | |
727 app->GetIconURL(ExtensionIconSet::EXTENSION_ICON_GIGANTOR, | |
728 ExtensionIconSet::MATCH_SMALLER).spec()); | |
729 error_strings->SetString("name", app->name()); | |
730 error_strings->SetString("msg", | |
731 l10n_util::GetStringUTF16(IDS_ERRORPAGES_APP_WARNING)); | |
732 | |
733 #if defined(OS_CHROMEOS) | |
734 GURL learn_more_url(kAppWarningLearnMoreUrl); | |
735 DictionaryValue* suggest_learn_more = new DictionaryValue(); | |
736 suggest_learn_more->SetString("msg", | |
737 l10n_util::GetStringUTF16( | |
738 IDS_ERRORPAGES_SUGGESTION_LEARNMORE)); | |
739 suggest_learn_more->SetString("learnMoreUrl", learn_more_url.spec()); | |
740 error_strings->Set("suggestionsLearnMore", suggest_learn_more); | |
741 #endif // defined(OS_CHROMEOS) | |
742 } | |
OLD | NEW |