OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 #import "ios/web/web_state/error_translation_util.h" | |
6 | |
7 #include <CFNetwork/CFNetwork.h> | |
8 | |
9 #include "base/mac/scoped_nsobject.h" | |
10 #include "net/base/net_errors.h" | |
11 | |
12 namespace web { | |
13 | |
14 namespace { | |
15 // Translates an iOS error to a net error using |net_error_code| as an | |
16 // out-parameter. Returns true if a valid translation was found. | |
17 bool GetNetErrorFromIOSErrorCode(NSInteger ios_error_code, | |
18 NSInteger* net_error_code) { | |
19 DCHECK(net_error_code); | |
20 bool translation_success = true; | |
21 switch (ios_error_code) { | |
22 case kCFURLErrorBackgroundSessionInUseByAnotherProcess: | |
23 *net_error_code = net::ERR_ACCESS_DENIED; | |
24 break; | |
25 case kCFURLErrorBackgroundSessionWasDisconnected: | |
26 *net_error_code = net::ERR_CONNECTION_ABORTED; | |
27 break; | |
28 case kCFURLErrorUnknown: | |
29 *net_error_code = net::ERR_FAILED; | |
30 break; | |
31 case kCFURLErrorCancelled: | |
32 *net_error_code = net::ERR_ABORTED; | |
33 break; | |
34 case kCFURLErrorBadURL: | |
35 *net_error_code = net::ERR_INVALID_URL; | |
36 break; | |
37 case kCFURLErrorTimedOut: | |
38 *net_error_code = net::ERR_CONNECTION_TIMED_OUT; | |
39 break; | |
40 case kCFURLErrorUnsupportedURL: | |
41 *net_error_code = net::ERR_UNKNOWN_URL_SCHEME; | |
42 break; | |
43 case kCFURLErrorCannotFindHost: | |
44 *net_error_code = net::ERR_NAME_NOT_RESOLVED; | |
45 break; | |
46 case kCFURLErrorCannotConnectToHost: | |
47 *net_error_code = net::ERR_CONNECTION_FAILED; | |
48 break; | |
49 case kCFURLErrorNetworkConnectionLost: | |
50 *net_error_code = net::ERR_INTERNET_DISCONNECTED; | |
51 break; | |
52 case kCFURLErrorDNSLookupFailed: | |
53 *net_error_code = net::ERR_NAME_RESOLUTION_FAILED; | |
54 break; | |
55 case kCFURLErrorHTTPTooManyRedirects: | |
56 *net_error_code = net::ERR_TOO_MANY_REDIRECTS; | |
57 break; | |
58 case kCFURLErrorResourceUnavailable: | |
59 *net_error_code = net::ERR_INSUFFICIENT_RESOURCES; | |
60 break; | |
61 case kCFURLErrorNotConnectedToInternet: | |
62 *net_error_code = net::ERR_INTERNET_DISCONNECTED; | |
63 break; | |
64 case kCFURLErrorRedirectToNonExistentLocation: | |
65 *net_error_code = net::ERR_NAME_NOT_RESOLVED; | |
66 break; | |
67 case kCFURLErrorBadServerResponse: | |
68 *net_error_code = net::ERR_INVALID_RESPONSE; | |
69 break; | |
70 case kCFURLErrorUserCancelledAuthentication: | |
71 *net_error_code = net::ERR_ABORTED; | |
72 break; | |
73 case kCFURLErrorUserAuthenticationRequired: | |
74 // TODO(kkhorimoto): ERR_SSL_RENEGOTIATION_REQUESTED is more specific than | |
75 // the kCFURLErrorUserAuthenticationRequired. Consider adding a new net | |
76 // error for this scenario. | |
77 *net_error_code = net::ERR_SSL_RENEGOTIATION_REQUESTED; | |
78 break; | |
79 case kCFURLErrorZeroByteResource: | |
80 *net_error_code = net::ERR_EMPTY_RESPONSE; | |
81 break; | |
82 case kCFURLErrorCannotDecodeRawData: | |
83 *net_error_code = net::ERR_CONTENT_DECODING_FAILED; | |
84 break; | |
85 case kCFURLErrorCannotDecodeContentData: | |
86 *net_error_code = net::ERR_CONTENT_DECODING_FAILED; | |
87 break; | |
88 case kCFURLErrorCannotParseResponse: | |
89 *net_error_code = net::ERR_INVALID_RESPONSE; | |
90 break; | |
91 case kCFURLErrorInternationalRoamingOff: | |
92 // TODO(kkhorimoto): Create new net error for disabled intl roaming. | |
93 *net_error_code = net::ERR_INTERNET_DISCONNECTED; | |
94 break; | |
95 case kCFURLErrorCallIsActive: | |
96 *net_error_code = net::ERR_CONNECTION_FAILED; | |
97 break; | |
98 case kCFURLErrorDataNotAllowed: | |
99 // TODO(kkhorimoto): Create new net error for disabled data usage. | |
100 *net_error_code = net::ERR_INTERNET_DISCONNECTED; | |
101 break; | |
102 case kCFURLErrorRequestBodyStreamExhausted: | |
103 *net_error_code = net::ERR_CONTENT_LENGTH_MISMATCH; | |
104 break; | |
105 case kCFURLErrorFileDoesNotExist: | |
106 *net_error_code = net::ERR_FILE_NOT_FOUND; | |
107 break; | |
108 case kCFURLErrorFileIsDirectory: | |
109 *net_error_code = net::ERR_INVALID_HANDLE; | |
110 break; | |
111 case kCFURLErrorNoPermissionsToReadFile: | |
112 *net_error_code = net::ERR_ACCESS_DENIED; | |
113 break; | |
114 case kCFURLErrorDataLengthExceedsMaximum: | |
115 *net_error_code = net::ERR_FILE_TOO_BIG; | |
116 break; | |
117 default: | |
118 translation_success = false; | |
119 break; | |
120 } | |
121 return translation_success; | |
122 } | |
123 } // namespace | |
124 | |
125 NSError* NetErrorFromError(NSError* error) { | |
126 NSError* underlying_error = error.userInfo[NSUnderlyingErrorKey]; | |
127 NSString* net_error_domain = | |
128 [NSString stringWithUTF8String:net::kErrorDomain]; | |
129 NSError* translated_error = error; | |
130 if (underlying_error) { | |
131 // If |error| already has an underlying error, it should be from the net | |
132 // stack and should already have the correct domain. | |
133 DCHECK([underlying_error.domain isEqualToString:net_error_domain]); | |
134 } else if ([error.domain isEqualToString:NSURLErrorDomain] || | |
135 [error.domain isEqualToString:static_cast<NSString*>( | |
136 kCFErrorDomainCFNetwork)]) { | |
137 // Attempt to translate NSURL and CFNetwork error codes into their | |
138 // corresponding net error codes. | |
139 NSInteger net_error_code = net::OK; | |
140 if (GetNetErrorFromIOSErrorCode(error.code, &net_error_code)) { | |
141 base::scoped_nsobject<NSMutableDictionary> user_info( | |
142 [error.userInfo mutableCopy]); | |
143 [user_info setObject:[NSError errorWithDomain:net_error_domain | |
144 code:net_error_code | |
145 userInfo:nil] | |
146 forKey:NSUnderlyingErrorKey]; | |
147 translated_error = [NSError errorWithDomain:error.domain | |
148 code:error.code | |
149 userInfo:user_info]; | |
150 } | |
151 } | |
152 return translated_error; | |
153 } | |
154 } | |
OLD | NEW |