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.
5 #import "ios/web/web_state/error_translation_util.h"
7 #include <CFNetwork/CFNetwork.h>
9 #import "base/ios/ns_error_util.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "net/base/net_errors.h"
16 // Translates an iOS error to a net error using |net_error_code| as an
17 // out-parameter. Returns true if a valid translation was found.
18 bool GetNetErrorFromIOSErrorCode(NSInteger ios_error_code,
19 NSInteger* net_error_code) {
20 DCHECK(net_error_code);
21 bool translation_success = true;
22 switch (ios_error_code) {
23 case kCFURLErrorBackgroundSessionInUseByAnotherProcess:
24 *net_error_code = net::ERR_ACCESS_DENIED;
26 case kCFURLErrorBackgroundSessionWasDisconnected:
27 *net_error_code = net::ERR_CONNECTION_ABORTED;
29 case kCFURLErrorUnknown:
30 *net_error_code = net::ERR_FAILED;
32 case kCFURLErrorCancelled:
33 *net_error_code = net::ERR_ABORTED;
35 case kCFURLErrorBadURL:
36 *net_error_code = net::ERR_INVALID_URL;
38 case kCFURLErrorTimedOut:
39 *net_error_code = net::ERR_CONNECTION_TIMED_OUT;
41 case kCFURLErrorUnsupportedURL:
42 *net_error_code = net::ERR_UNKNOWN_URL_SCHEME;
44 case kCFURLErrorCannotFindHost:
45 *net_error_code = net::ERR_NAME_NOT_RESOLVED;
47 case kCFURLErrorCannotConnectToHost:
48 *net_error_code = net::ERR_CONNECTION_FAILED;
50 case kCFURLErrorNetworkConnectionLost:
51 *net_error_code = net::ERR_INTERNET_DISCONNECTED;
53 case kCFURLErrorDNSLookupFailed:
54 *net_error_code = net::ERR_NAME_RESOLUTION_FAILED;
56 case kCFURLErrorHTTPTooManyRedirects:
57 *net_error_code = net::ERR_TOO_MANY_REDIRECTS;
59 case kCFURLErrorResourceUnavailable:
60 *net_error_code = net::ERR_INSUFFICIENT_RESOURCES;
62 case kCFURLErrorNotConnectedToInternet:
63 *net_error_code = net::ERR_INTERNET_DISCONNECTED;
65 case kCFURLErrorRedirectToNonExistentLocation:
66 *net_error_code = net::ERR_NAME_NOT_RESOLVED;
68 case kCFURLErrorBadServerResponse:
69 *net_error_code = net::ERR_INVALID_RESPONSE;
71 case kCFURLErrorUserCancelledAuthentication:
72 *net_error_code = net::ERR_ABORTED;
74 case kCFURLErrorUserAuthenticationRequired:
75 // TODO(kkhorimoto): ERR_SSL_RENEGOTIATION_REQUESTED is more specific than
76 // the kCFURLErrorUserAuthenticationRequired. Consider adding a new net
77 // error for this scenario.
78 *net_error_code = net::ERR_SSL_RENEGOTIATION_REQUESTED;
80 case kCFURLErrorZeroByteResource:
81 *net_error_code = net::ERR_EMPTY_RESPONSE;
83 case kCFURLErrorCannotDecodeRawData:
84 *net_error_code = net::ERR_CONTENT_DECODING_FAILED;
86 case kCFURLErrorCannotDecodeContentData:
87 *net_error_code = net::ERR_CONTENT_DECODING_FAILED;
89 case kCFURLErrorCannotParseResponse:
90 *net_error_code = net::ERR_INVALID_RESPONSE;
92 case kCFURLErrorInternationalRoamingOff:
93 // TODO(kkhorimoto): Create new net error for disabled intl roaming.
94 *net_error_code = net::ERR_INTERNET_DISCONNECTED;
96 case kCFURLErrorCallIsActive:
97 *net_error_code = net::ERR_CONNECTION_FAILED;
99 case kCFURLErrorDataNotAllowed:
100 // TODO(kkhorimoto): Create new net error for disabled data usage.
101 *net_error_code = net::ERR_INTERNET_DISCONNECTED;
103 case kCFURLErrorRequestBodyStreamExhausted:
104 *net_error_code = net::ERR_CONTENT_LENGTH_MISMATCH;
106 case kCFURLErrorFileDoesNotExist:
107 *net_error_code = net::ERR_FILE_NOT_FOUND;
109 case kCFURLErrorFileIsDirectory:
110 *net_error_code = net::ERR_INVALID_HANDLE;
112 case kCFURLErrorNoPermissionsToReadFile:
113 *net_error_code = net::ERR_ACCESS_DENIED;
115 case kCFURLErrorDataLengthExceedsMaximum:
116 *net_error_code = net::ERR_FILE_TOO_BIG;
119 translation_success = false;
122 return translation_success;
126 NSError* NetErrorFromError(NSError* error) {
128 NSError* underlying_error =
129 base::ios::GetFinalUnderlyingErrorFromError(error);
130 NSError* translated_error = error;
131 if ([underlying_error.domain isEqualToString:NSURLErrorDomain] ||
132 [underlying_error.domain
133 isEqualToString:static_cast<NSString*>(kCFErrorDomainCFNetwork)]) {
134 // Attempt to translate NSURL and CFNetwork error codes into their
135 // corresponding net error codes.
136 NSInteger net_error_code = net::OK;
137 if (GetNetErrorFromIOSErrorCode(underlying_error.code, &net_error_code)) {
138 NSString* net_error_domain =
139 [NSString stringWithUTF8String:net::kErrorDomain];
140 NSError* net_error = [NSError errorWithDomain:net_error_domain
144 base::ios::ErrorWithAppendedUnderlyingError(error, net_error);
147 return translated_error;