[iOS] Upstream PLATFORM(IOS) changes to Source/WebKit/
[WebKit-https.git] / Source / WebKit / mac / WebCoreSupport / WebGeolocationClient.mm
1 /*
2  * Copyright (C) 2009, 2012 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 "WebGeolocationClient.h"
27
28 #if ENABLE(GEOLOCATION)
29
30 #import "WebDelegateImplementationCaching.h"
31 #import "WebFrameInternal.h"
32 #import "WebGeolocationPositionInternal.h"
33 #import "WebSecurityOriginInternal.h"
34 #import "WebUIDelegatePrivate.h"
35 #import "WebViewInternal.h"
36 #import <WebCore/BlockExceptions.h>
37 #import <WebCore/Document.h>
38 #import <WebCore/Frame.h>
39 #import <WebCore/Geolocation.h>
40
41 #if PLATFORM(IOS)
42 #import <WebCore/WAKResponder.h>
43 #import <WebKit/WebCoreThreadRun.h>
44 #endif
45
46 using namespace WebCore;
47
48 #if !PLATFORM(IOS)
49 @interface WebGeolocationPolicyListener : NSObject <WebAllowDenyPolicyListener>
50 {
51     RefPtr<Geolocation> _geolocation;
52 }
53 - (id)initWithGeolocation:(Geolocation*)geolocation;
54 @end
55 #else
56 @interface WebGeolocationPolicyListener : NSObject <WebAllowDenyPolicyListener>
57 {
58     RefPtr<Geolocation> _geolocation;
59     RetainPtr<WebView *> _webView;
60     RetainPtr<id<WebGeolocationProvider> > _geolocationProvider;
61 }
62 - (id)initWithGeolocation:(Geolocation*)geolocation forWebView:(WebView*)webView provider:(id<WebGeolocationProvider>)provider;
63 @end
64 #endif
65
66 #if PLATFORM(IOS)
67 @interface WebGeolocationProviderInitializationListener : NSObject <WebGeolocationProviderInitializationListener> {
68 @private
69     RefPtr<Geolocation> m_geolocation;
70 }
71 - (id)initWithGeolocation:(Geolocation*)geolocation;
72 @end
73 #endif
74
75 WebGeolocationClient::WebGeolocationClient(WebView *webView)
76     : m_webView(webView)
77 {
78 }
79
80 void WebGeolocationClient::geolocationDestroyed()
81 {
82     delete this;
83 }
84
85 void WebGeolocationClient::startUpdating()
86 {
87     [[m_webView _geolocationProvider] registerWebView:m_webView];
88 }
89
90 void WebGeolocationClient::stopUpdating()
91 {
92     [[m_webView _geolocationProvider] unregisterWebView:m_webView];
93 }
94
95 #if PLATFORM(IOS)
96 void WebGeolocationClient::setEnableHighAccuracy(bool wantsHighAccuracy)
97 {
98     BEGIN_BLOCK_OBJC_EXCEPTIONS;
99     [[m_webView _geolocationProvider] setEnableHighAccuracy:wantsHighAccuracy];
100     END_BLOCK_OBJC_EXCEPTIONS;
101 }
102 #endif
103
104 void WebGeolocationClient::requestPermission(Geolocation* geolocation)
105 {
106     BEGIN_BLOCK_OBJC_EXCEPTIONS;
107
108     SEL selector = @selector(webView:decidePolicyForGeolocationRequestFromOrigin:frame:listener:);
109     if (![[m_webView UIDelegate] respondsToSelector:selector]) {
110         geolocation->setIsAllowed(false);
111         return;
112     }
113
114 #if !PLATFORM(IOS)
115     Frame *frame = geolocation->frame();
116     WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:frame->document()->securityOrigin()];
117     WebGeolocationPolicyListener* listener = [[WebGeolocationPolicyListener alloc] initWithGeolocation:geolocation];
118
119     CallUIDelegate(m_webView, selector, webOrigin, kit(frame), listener);
120
121     [webOrigin release];
122     [listener release];
123 #else
124     RetainPtr<WebGeolocationProviderInitializationListener> listener = adoptNS([[WebGeolocationProviderInitializationListener alloc] initWithGeolocation:geolocation]);
125     [[m_webView _geolocationProvider] initializeGeolocationForWebView:m_webView listener:listener.get()];
126 #endif
127     END_BLOCK_OBJC_EXCEPTIONS;
128 }
129
130 GeolocationPosition* WebGeolocationClient::lastPosition()
131 {
132     return core([[m_webView _geolocationProvider] lastPosition]);
133 }
134
135 #if !PLATFORM(IOS)
136 @implementation WebGeolocationPolicyListener
137
138 - (id)initWithGeolocation:(Geolocation*)geolocation
139 {
140     if (!(self = [super init]))
141         return nil;
142     _geolocation = geolocation;
143     return self;
144 }
145
146 - (void)allow
147 {
148     _geolocation->setIsAllowed(true);
149 }
150
151 - (void)deny
152 {
153     _geolocation->setIsAllowed(false);
154 }
155
156 @end
157
158 #else
159 @implementation WebGeolocationPolicyListener
160 - (id)initWithGeolocation:(Geolocation*)geolocation forWebView:(WebView*)webView provider:(id<WebGeolocationProvider>)provider
161 {
162     self = [super init];
163     if (!self)
164         return nil;
165     _geolocation = geolocation;
166     _webView = webView;
167     _geolocationProvider = provider;
168     return self;
169 }
170
171 - (void)allow
172 {
173     WebThreadRun(^{
174         _geolocation->setIsAllowed(true);
175     });
176 }
177
178 - (void)deny
179 {
180     WebThreadRun(^{
181         _geolocation->setIsAllowed(false);
182         [_geolocationProvider.get() cancelWarmUpForWebView:_webView.get()];
183     });
184 }
185
186 - (void)denyOnlyThisRequest
187 {
188     WebThreadRun(^{
189         // A soft deny does not prevent subsequent request from the Geolocation object.
190         [self deny];
191         _geolocation->resetAllGeolocationPermission();
192     });
193 }
194
195 - (BOOL)shouldClearCache
196 {
197     // Theoretically, WebView could changes the WebPreferences after we get the pointer.
198     // We lock to be on the safe side.
199     WebThreadLock();
200
201     return [[_webView.get() preferences] _alwaysRequestGeolocationPermission];
202 }
203 @end
204
205 @implementation WebGeolocationProviderInitializationListener
206 - (id)initWithGeolocation:(Geolocation*)geolocation
207 {
208     self = [super init];
209     if (self)
210         m_geolocation = geolocation;
211     return self;
212 }
213
214 - (void)initializationAllowedWebView:(WebView *)webView provider:(id<WebGeolocationProvider>)provider
215 {
216     BEGIN_BLOCK_OBJC_EXCEPTIONS;
217
218     Frame* frame = m_geolocation->frame();
219     if (!frame) {
220         [provider cancelWarmUpForWebView:webView];
221         return;
222     }
223     WebSecurityOrigin *webOrigin = [[WebSecurityOrigin alloc] _initWithWebCoreSecurityOrigin:frame->document()->securityOrigin()];
224     WebGeolocationPolicyListener *listener = [[WebGeolocationPolicyListener alloc] initWithGeolocation:m_geolocation.get() forWebView:webView provider:provider];
225     SEL selector = @selector(webView:decidePolicyForGeolocationRequestFromOrigin:frame:listener:);
226     CallUIDelegate(webView, selector, webOrigin, kit(frame), listener);
227     [webOrigin release];
228     [listener release];
229
230     END_BLOCK_OBJC_EXCEPTIONS;
231 }
232
233 - (void)initializationDeniedWebView:(WebView *)webView provider:(id<WebGeolocationProvider>)provider
234 {
235     m_geolocation->setIsAllowed(false);
236 }
237 @end
238 #endif // PLATFORM(IOS)
239
240 #endif // ENABLE(GEOLOCATION)