Expose a WKWebView API for allowing programmatic focus to trigger node assistance
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / Cocoa / WKWebViewConfiguration.mm
1 /*
2  * Copyright (C) 2014, 2015 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 "WKWebViewConfigurationInternal.h"
28
29 #if WK_API_ENABLED
30
31 #import "APIPageConfiguration.h"
32 #import "WKPreferences.h"
33 #import "WKProcessPool.h"
34 #import "WKUserContentController.h"
35 #import "WKWebViewContentProviderRegistry.h"
36 #import "WeakObjCPtr.h"
37 #import "_WKVisitedLinkProvider.h"
38 #import "_WKWebsiteDataStoreInternal.h"
39 #import <wtf/RetainPtr.h>
40
41 #if PLATFORM(IOS)
42 #import "UIKitSPI.h"
43 #import "WebKitSystemInterfaceIOS.h"
44 #endif
45
46 template<typename T> class LazyInitialized {
47 public:
48     typedef typename WTF::GetPtrHelper<T>::PtrType PtrType;
49
50     template<typename F>
51     PtrType get(F&& f)
52     {
53         if (!m_isInitialized) {
54             m_value = f();
55             m_isInitialized = true;
56         }
57
58         return m_value.get();
59     }
60
61     void set(PtrType t)
62     {
63         m_value = t;
64         m_isInitialized = true;
65     }
66
67     void set(T&& t)
68     {
69         m_value = WTF::move(t);
70         m_isInitialized = true;
71     }
72
73     PtrType peek()
74     {
75         return m_value.get();
76     }
77
78 private:
79     bool m_isInitialized = false;
80     T m_value;
81 };
82
83 @implementation WKWebViewConfiguration {
84     LazyInitialized<RetainPtr<WKProcessPool>> _processPool;
85     LazyInitialized<RetainPtr<WKPreferences>> _preferences;
86     LazyInitialized<RetainPtr<WKUserContentController>> _userContentController;
87     LazyInitialized<RetainPtr<_WKVisitedLinkStore>> _visitedLinkStore;
88     LazyInitialized<RetainPtr<WKWebsiteDataStore>> _websiteDataStore;
89     WebKit::WeakObjCPtr<WKWebView> _relatedWebView;
90     WebKit::WeakObjCPtr<WKWebView> _alternateWebViewForNavigationGestures;
91     BOOL _treatsSHA1SignedCertificatesAsInsecure;
92     RetainPtr<NSString> _groupIdentifier;
93     LazyInitialized<RetainPtr<NSString>> _applicationNameForUserAgent;
94
95 #if PLATFORM(IOS)
96     LazyInitialized<RetainPtr<WKWebViewContentProviderRegistry>> _contentProviderRegistry;
97     BOOL _alwaysRunsAtForegroundPriority;
98     BOOL _allowsInlineMediaPlayback;
99     BOOL _inlineMediaPlaybackRequiresPlaysInlineAttribute;
100     BOOL _mediaDataLoadsAutomatically;
101 #endif
102 }
103
104 - (instancetype)init
105 {
106     if (!(self = [super init]))
107         return nil;
108     
109 #if PLATFORM(IOS)
110     _requiresUserActionForMediaPlayback = YES;
111     _allowsPictureInPictureMediaPlayback = YES;
112     _allowsInlineMediaPlayback = WKGetDeviceClass() == WKDeviceClassiPad;
113     _inlineMediaPlaybackRequiresPlaysInlineAttribute = !_allowsInlineMediaPlayback;
114     _mediaDataLoadsAutomatically = NO;
115     _canAssistOnProgrammaticFocus = NO;
116 #endif
117
118 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
119     _allowsAirPlayForMediaPlayback = YES;
120 #endif
121
122     return self;
123 }
124
125 - (NSString *)description
126 {
127     return [NSString stringWithFormat:@"<%@: %p; processPool = %@; preferences = %@>", NSStringFromClass(self.class), self, self.processPool, self.preferences];
128 }
129
130 - (id)copyWithZone:(NSZone *)zone
131 {
132     WKWebViewConfiguration *configuration = [(WKWebViewConfiguration *)[[self class] allocWithZone:zone] init];
133
134     configuration.processPool = self.processPool;
135     configuration.preferences = self.preferences;
136     configuration.userContentController = self.userContentController;
137     configuration.websiteDataStore = self.websiteDataStore;
138     configuration._visitedLinkStore = self._visitedLinkStore;
139     configuration._relatedWebView = _relatedWebView.get().get();
140     configuration._alternateWebViewForNavigationGestures = _alternateWebViewForNavigationGestures.get().get();
141     configuration->_treatsSHA1SignedCertificatesAsInsecure = _treatsSHA1SignedCertificatesAsInsecure;
142 #if PLATFORM(IOS)
143     configuration._contentProviderRegistry = self._contentProviderRegistry;
144 #endif
145
146     configuration->_suppressesIncrementalRendering = self->_suppressesIncrementalRendering;
147     configuration.applicationNameForUserAgent = self.applicationNameForUserAgent;
148
149 #if PLATFORM(IOS)
150     configuration->_allowsInlineMediaPlayback = self->_allowsInlineMediaPlayback;
151     configuration->_inlineMediaPlaybackRequiresPlaysInlineAttribute = self->_inlineMediaPlaybackRequiresPlaysInlineAttribute;
152     configuration->_mediaDataLoadsAutomatically = self->_mediaDataLoadsAutomatically;
153     configuration->_allowsPictureInPictureMediaPlayback = self->_allowsPictureInPictureMediaPlayback;
154     configuration->_alwaysRunsAtForegroundPriority = _alwaysRunsAtForegroundPriority;
155     configuration->_requiresUserActionForMediaPlayback = self->_requiresUserActionForMediaPlayback;
156     configuration->_selectionGranularity = self->_selectionGranularity;
157 #endif
158 #if ENABLE(WIRELESS_TARGET_PLAYBACK)
159     configuration->_allowsAirPlayForMediaPlayback = self->_allowsAirPlayForMediaPlayback;
160 #endif
161
162     return configuration;
163 }
164
165 - (WKProcessPool *)processPool
166 {
167     return _processPool.get([] { return adoptNS([[WKProcessPool alloc] init]); });
168 }
169
170 - (void)setProcessPool:(WKProcessPool *)processPool
171 {
172     _processPool.set(processPool);
173 }
174
175 - (WKPreferences *)preferences
176 {
177     return _preferences.get([] { return adoptNS([[WKPreferences alloc] init]); });
178 }
179
180 - (void)setPreferences:(WKPreferences *)preferences
181 {
182     _preferences.set(preferences);
183 }
184
185 - (WKUserContentController *)userContentController
186 {
187     return _userContentController.get([] { return adoptNS([[WKUserContentController alloc] init]); });
188 }
189
190 - (void)setUserContentController:(WKUserContentController *)userContentController
191 {
192     _userContentController.set(userContentController);
193 }
194
195 - (WKWebsiteDataStore *)websiteDataStore
196 {
197     return _websiteDataStore.get([] { return [WKWebsiteDataStore defaultDataStore]; });
198 }
199
200 - (void)setWebsiteDataStore:(WKWebsiteDataStore *)websiteDataStore
201 {
202     _websiteDataStore.set(websiteDataStore);
203 }
204
205 static NSString *defaultApplicationNameForUserAgent()
206 {
207 #if PLATFORM(IOS)
208     return [@"Mobile/" stringByAppendingString:[UIDevice currentDevice].buildVersion];
209 #else
210     return nil;
211 #endif
212 }
213
214 - (NSString *)applicationNameForUserAgent
215 {
216     return _applicationNameForUserAgent.get([] { return defaultApplicationNameForUserAgent(); });
217 }
218
219 - (void)setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
220 {
221     _applicationNameForUserAgent.set(adoptNS([applicationNameForUserAgent copy]));
222 }
223
224 - (_WKVisitedLinkStore *)_visitedLinkStore
225 {
226     return _visitedLinkStore.get([] { return adoptNS([[_WKVisitedLinkStore alloc] init]); });
227 }
228
229 - (void)_setVisitedLinkStore:(_WKVisitedLinkStore *)visitedLinkStore
230 {
231     _visitedLinkStore.set(visitedLinkStore);
232 }
233
234 #pragma clang diagnostic push
235 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
236
237 - (_WKWebsiteDataStore *)_websiteDataStore
238 {
239     return self.websiteDataStore ? adoptNS([[_WKWebsiteDataStore alloc] initWithDataStore:self.websiteDataStore]).autorelease() : nullptr;
240 }
241
242 - (void)_setWebsiteDataStore:(_WKWebsiteDataStore *)websiteDataStore
243 {
244     self.websiteDataStore = websiteDataStore ? websiteDataStore->_dataStore.get() : nullptr;
245 }
246
247 -(_WKVisitedLinkProvider *)_visitedLinkProvider
248 {
249     return (_WKVisitedLinkProvider *)self._visitedLinkStore;
250 }
251
252 - (void)_setVisitedLinkProvider:(_WKVisitedLinkProvider *)_visitedLinkProvider
253 {
254     self._visitedLinkStore = _visitedLinkProvider;
255 }
256
257 #pragma clang diagnostic pop
258
259 #if PLATFORM(IOS)
260 - (WKWebViewContentProviderRegistry *)_contentProviderRegistry
261 {
262     return _contentProviderRegistry.get([] { return adoptNS([[WKWebViewContentProviderRegistry alloc] init]); });
263 }
264
265 - (void)_setContentProviderRegistry:(WKWebViewContentProviderRegistry *)registry
266 {
267     _contentProviderRegistry.set(registry);
268 }
269 #endif
270
271 - (void)_validate
272 {
273     if (!self.processPool)
274         [NSException raise:NSInvalidArgumentException format:@"configuration.processPool is nil"];
275
276     if (!self.preferences)
277         [NSException raise:NSInvalidArgumentException format:@"configuration.preferences is nil"];
278
279     if (!self.userContentController)
280         [NSException raise:NSInvalidArgumentException format:@"configuration.userContentController is nil"];
281
282     if (!self.websiteDataStore)
283         [NSException raise:NSInvalidArgumentException format:@"configuration.websiteDataStore is nil"];
284
285     if (!self._visitedLinkStore)
286         [NSException raise:NSInvalidArgumentException format:@"configuration._visitedLinkStore is nil"];
287
288 #if PLATFORM(IOS)
289     if (!self._contentProviderRegistry)
290         [NSException raise:NSInvalidArgumentException format:@"configuration._contentProviderRegistry is nil"];
291 #endif
292 }
293
294 @end
295
296 @implementation WKWebViewConfiguration (WKPrivate)
297
298 - (WKWebView *)_relatedWebView
299 {
300     return _relatedWebView.getAutoreleased();
301 }
302
303 - (void)_setRelatedWebView:(WKWebView *)relatedWebView
304 {
305     _relatedWebView = relatedWebView;
306 }
307
308 - (WKWebView *)_alternateWebViewForNavigationGestures
309 {
310     return _alternateWebViewForNavigationGestures.getAutoreleased();
311 }
312
313 - (void)_setAlternateWebViewForNavigationGestures:(WKWebView *)alternateView
314 {
315     _alternateWebViewForNavigationGestures = alternateView;
316 }
317
318 - (NSString *)_groupIdentifier
319 {
320     return _groupIdentifier.get();
321 }
322
323 - (void)_setGroupIdentifier:(NSString *)groupIdentifier
324 {
325     _groupIdentifier = groupIdentifier;
326 }
327
328 - (BOOL)_treatsSHA1SignedCertificatesAsInsecure
329 {
330     return _treatsSHA1SignedCertificatesAsInsecure;
331 }
332
333 - (void)_setTreatsSHA1SignedCertificatesAsInsecure:(BOOL)insecure
334 {
335     _treatsSHA1SignedCertificatesAsInsecure = insecure;
336 }
337
338 #if PLATFORM(IOS)
339 - (BOOL)_alwaysRunsAtForegroundPriority
340 {
341     return _alwaysRunsAtForegroundPriority;
342 }
343
344 - (void)_setAlwaysRunsAtForegroundPriority:(BOOL)alwaysRunsAtForegroundPriority
345 {
346     _alwaysRunsAtForegroundPriority = alwaysRunsAtForegroundPriority;
347 }
348
349 - (BOOL)_inlineMediaPlaybackRequiresPlaysInlineAttribute
350 {
351     return _inlineMediaPlaybackRequiresPlaysInlineAttribute;
352 }
353
354 - (void)_setInlineMediaPlaybackRequiresPlaysInlineAttribute:(BOOL)requires
355 {
356     _inlineMediaPlaybackRequiresPlaysInlineAttribute = requires;
357 }
358
359 - (BOOL)_mediaDataLoadsAutomatically
360 {
361     return _mediaDataLoadsAutomatically;
362 }
363
364 - (void)_setMediaDataLoadsAutomatically:(BOOL)mediaDataLoadsAutomatically
365 {
366     _mediaDataLoadsAutomatically = mediaDataLoadsAutomatically;
367 }
368
369 - (BOOL)_canAssistOnProgrammaticFocus
370 {
371     return _canAssistOnProgrammaticFocus;
372 }
373
374 - (void)_setCanAssistOnProgrammaticFocus:(BOOL)canAssistOnProgrammaticFocus
375 {
376     _canAssistOnProgrammaticFocus = canAssistOnProgrammaticFocus;
377 }
378 #endif
379
380 @end
381
382 @implementation WKWebViewConfiguration (WKDeprecated)
383
384 #if PLATFORM(IOS)
385 - (BOOL)mediaPlaybackAllowsAirPlay
386 {
387     return self.allowsAirPlayForMediaPlayback;
388 }
389
390 - (void)setMediaPlaybackAllowsAirPlay:(BOOL)allowed
391 {
392     self.allowsAirPlayForMediaPlayback = allowed;
393 }
394
395 - (BOOL)mediaPlaybackRequiresUserAction
396 {
397     return self.requiresUserActionForMediaPlayback;
398 }
399
400 - (void)setMediaPlaybackRequiresUserAction:(BOOL)required
401 {
402     self.requiresUserActionForMediaPlayback = required;
403 }
404 #endif // PLATFORM(IOS)
405
406 @end
407
408 #endif // WK_API_ENABLED