1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#import "config.h"
27#import "WebErrors.h"
28
29#import "WKError.h"
30#import "WebError.h"
31#import <WebCore/LocalizedStrings.h>
32#import <WebCore/ResourceRequest.h>
33#import <WebCore/ResourceResponse.h>
34#import <pthread.h>
35
36using namespace WebCore;
37using namespace WebKit;
38
39// FIXME: We probably don't need to use NSErrors here.
40
41static NSString * const WebKitErrorMIMETypeKey =               @"WebKitErrorMIMETypeKey";
42static NSString * const WebKitErrorPlugInNameKey =             @"WebKitErrorPlugInNameKey";
43static NSString * const WebKitErrorPlugInPageURLStringKey =    @"WebKitErrorPlugInPageURLStringKey";
44
45// Policy errors
46#define WebKitErrorDescriptionCannotShowMIMEType WEB_UI_STRING("Content with specified MIME type canât be shown", "WebKitErrorCannotShowMIMEType description")
47#define WebKitErrorDescriptionCannotShowURL WEB_UI_STRING("The URL canât be shown", "WebKitErrorCannotShowURL description")
48#define WebKitErrorDescriptionFrameLoadInterruptedByPolicyChange WEB_UI_STRING("Frame load interrupted", "WebKitErrorFrameLoadInterruptedByPolicyChange description")
49#define WebKitErrorDescriptionCannotUseRestrictedPort WEB_UI_STRING("Not allowed to use restricted network port", "WebKitErrorCannotUseRestrictedPort description")
50
51// Plug-in and java errors
52#define WebKitErrorDescriptionCannotFindPlugin WEB_UI_STRING("The plug-in canât be found", "WebKitErrorCannotFindPlugin description")
53#define WebKitErrorDescriptionCannotLoadPlugin WEB_UI_STRING("The plug-in canât be loaded", "WebKitErrorCannotLoadPlugin description")
54#define WebKitErrorDescriptionJavaUnavailable WEB_UI_STRING("Java is unavailable", "WebKitErrorJavaUnavailable description")
55#define WebKitErrorDescriptionPlugInCancelledConnection WEB_UI_STRING("Plug-in cancelled", "WebKitErrorPlugInCancelledConnection description")
56#define WebKitErrorDescriptionPlugInWillHandleLoad WEB_UI_STRING("Plug-in handled load", "WebKitErrorPlugInWillHandleLoad description")
57
58static pthread_once_t registerErrorsControl = PTHREAD_ONCE_INIT;
59static void registerErrors(void);
60
61@interface NSError (WebKitExtras)
62+ (NSError *)_webKitErrorWithDomain:(NSString *)domain code:(int)code URL:(NSURL *)URL;
63@end
64
65@implementation NSError (WebKitExtras)
66
67static NSMutableDictionary *descriptions = nil;
68
69+ (void)_registerWebKitErrors
70{
71    pthread_once(&registerErrorsControl, registerErrors);
72}
73
74-(id)_webkit_initWithDomain:(NSString *)domain code:(int)code URL:(NSURL *)URL
75{
76    NSDictionary *descriptionsDict;
77    NSString *localizedDesc;
78    NSDictionary *dict;
79    // insert a localized string here for those folks not savvy to our category methods
80    descriptionsDict = [descriptions objectForKey:domain];
81    localizedDesc = descriptionsDict ? [descriptionsDict objectForKey:[NSNumber numberWithInt:code]] : nil;
82    dict = [NSDictionary dictionaryWithObjectsAndKeys:
83        URL, @"NSErrorFailingURLKey",
84        [URL absoluteString], @"NSErrorFailingURLStringKey",
85        localizedDesc, NSLocalizedDescriptionKey,
86        nil];
87    return [self initWithDomain:domain code:code userInfo:dict];
88}
89
90+(id)_webkit_errorWithDomain:(NSString *)domain code:(int)code URL:(NSURL *)URL
91{
92    return [[[self alloc] _webkit_initWithDomain:domain code:code URL:URL] autorelease];
93}
94
95+ (NSError *)_webKitErrorWithDomain:(NSString *)domain code:(int)code URL:(NSURL *)URL
96{
97    [self _registerWebKitErrors];
98    return [self _webkit_errorWithDomain:domain code:code URL:URL];
99}
100
101+ (NSError *)_webKitErrorWithCode:(int)code failingURL:(NSString *)URLString
102{
103    return [self _webKitErrorWithDomain:WebError::webKitErrorDomain() code:code URL:[NSURL URLWithString:URLString]];
104}
105
106+ (void)_webkit_addErrorsWithCodesAndDescriptions:(NSDictionary *)dictionary inDomain:(NSString *)domain
107{
108    if (!descriptions)
109        descriptions = [[NSMutableDictionary alloc] init];
110
111    [descriptions setObject:dictionary forKey:domain];
112}
113
114static void registerErrors()
115{
116    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
117
118    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
119        // Policy errors
120        (NSString *)WebKitErrorDescriptionCannotShowMIMEType,                   [NSNumber numberWithInt: kWKErrorCodeCannotShowMIMEType],
121        (NSString *)WebKitErrorDescriptionCannotShowURL,                        [NSNumber numberWithInt: kWKErrorCodeCannotShowURL],
122        (NSString *)WebKitErrorDescriptionFrameLoadInterruptedByPolicyChange,   [NSNumber numberWithInt: kWKErrorCodeFrameLoadInterruptedByPolicyChange],
123        (NSString *)WebKitErrorDescriptionCannotUseRestrictedPort,              [NSNumber numberWithInt: kWKErrorCodeCannotUseRestrictedPort],
124
125        // Plug-in and java errors
126        (NSString *)WebKitErrorDescriptionCannotFindPlugin,                     [NSNumber numberWithInt: kWKErrorCodeCannotFindPlugIn],
127        (NSString *)WebKitErrorDescriptionCannotLoadPlugin,                     [NSNumber numberWithInt: kWKErrorCodeCannotLoadPlugIn],
128        (NSString *)WebKitErrorDescriptionJavaUnavailable,                      [NSNumber numberWithInt: kWKErrorCodeJavaUnavailable],
129        (NSString *)WebKitErrorDescriptionPlugInCancelledConnection,            [NSNumber numberWithInt: kWKErrorCodePlugInCancelledConnection],
130        (NSString *)WebKitErrorDescriptionPlugInWillHandleLoad,                 [NSNumber numberWithInt: kWKErrorCodePlugInWillHandleLoad],
131        nil];
132
133    [NSError _webkit_addErrorsWithCodesAndDescriptions:dict inDomain:WebError::webKitErrorDomain()];
134
135    [pool drain];
136}
137
138@end
139
140namespace WebKit {
141
142ResourceError cancelledError(const ResourceRequest& request)
143{
144    return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()];
145}
146
147ResourceError blockedError(const ResourceRequest& request)
148{
149    return [NSError _webKitErrorWithDomain:WebError::webKitErrorDomain() code:kWKErrorCodeCannotUseRestrictedPort URL:request.url()];
150}
151
152ResourceError cannotShowURLError(const ResourceRequest& request)
153{
154    return [NSError _webKitErrorWithDomain:WebError::webKitErrorDomain() code:kWKErrorCodeCannotShowURL URL:request.url()];
155}
156
157ResourceError interruptForPolicyChangeError(const ResourceRequest& request)
158{
159    return [NSError _webKitErrorWithDomain:WebError::webKitErrorDomain() code:kWKErrorCodeFrameLoadInterruptedByPolicyChange URL:request.url()];
160}
161
162ResourceError cannotShowMIMETypeError(const ResourceResponse& response)
163{
164    return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:kWKErrorCodeCannotShowMIMEType URL:response.url()];
165}
166
167ResourceError fileDoesNotExistError(const ResourceResponse& response)
168{
169    return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()];
170}
171
172ResourceError pluginWillHandleLoadError(const ResourceResponse& response)
173{
174    return [NSError _webKitErrorWithDomain:WebError::webKitErrorDomain() code:kWKErrorCodePlugInWillHandleLoad URL:response.url()];
175}
176
177} // namespace WebKit
178