Rename WKProcessClass to WKProcessPool
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / Cocoa / WKWebView.mm
1 /*
2  * Copyright (C) 2014 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 "WKWebViewInternal.h"
28
29 #if WK_API_ENABLED
30
31 #import "NavigationState.h"
32 #import "RemoteLayerTreeTransaction.h"
33 #import "RemoteObjectRegistry.h"
34 #import "RemoteObjectRegistryMessages.h"
35 #import "UIClient.h"
36 #import "ViewGestureController.h"
37 #import "WKBackForwardListInternal.h"
38 #import "WKBackForwardListItemInternal.h"
39 #import "WKBrowsingContextHandleInternal.h"
40 #import "WKHistoryDelegatePrivate.h"
41 #import "WKNSData.h"
42 #import "WKNavigationDelegate.h"
43 #import "WKNavigationInternal.h"
44 #import "WKPreferencesInternal.h"
45 #import "WKProcessPoolInternal.h"
46 #import "WKRemoteObjectRegistryInternal.h"
47 #import "WKUIDelegate.h"
48 #import "WKWebViewConfigurationPrivate.h"
49 #import "WebCertificateInfo.h"
50 #import "WebContext.h"
51 #import "WebBackForwardList.h"
52 #import "WebPageProxy.h"
53 #import "WebProcessProxy.h"
54 #import "WKNSURLExtras.h"
55 #import <wtf/RetainPtr.h>
56
57 #if PLATFORM(IOS)
58 #import "WKScrollView.h"
59 #import <UIKit/UIPeripheralHost_Private.h>
60
61 @interface UIScrollView (UIScrollViewInternal)
62 - (void)_adjustForAutomaticKeyboardInfo:(NSDictionary*)info animated:(BOOL)animated lastAdjustment:(CGFloat*)lastAdjustment;
63 @end
64
65 #endif
66
67 #if PLATFORM(MAC)
68 #import "WKViewInternal.h"
69 #endif
70
71 @implementation WKWebView {
72     RetainPtr<WKWebViewConfiguration> _configuration;
73     std::unique_ptr<WebKit::NavigationState> _navigationState;
74
75     RetainPtr<WKRemoteObjectRegistry> _remoteObjectRegistry;
76     _WKRenderingProgressEvents _observedRenderingProgressEvents;
77
78 #if PLATFORM(IOS)
79     RetainPtr<WKScrollView> _scrollView;
80     RetainPtr<WKContentView> _contentView;
81
82     BOOL _isWaitingForNewLayerTreeAfterDidCommitLoad;
83     BOOL _hasStaticMinimumLayoutSize;
84     CGSize _minimumLayoutSizeOverride;
85
86     UIEdgeInsets _obscuredInsets;
87     bool _isChangingObscuredInsetsInteractively;
88     CGFloat _lastAdjustmentForScroller;
89
90     std::unique_ptr<WebKit::ViewGestureController> _gestureController;
91     BOOL _allowsBackForwardNavigationGestures;
92 #endif
93 #if PLATFORM(MAC)
94     RetainPtr<WKView> _wkView;
95 #endif
96 }
97
98 - (instancetype)initWithFrame:(CGRect)frame
99 {
100     return [self initWithFrame:frame configuration:adoptNS([[WKWebViewConfiguration alloc] init]).get()];
101 }
102
103 - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
104 {
105     if (!(self = [super initWithFrame:frame]))
106         return nil;
107
108     _configuration = adoptNS([configuration copy]);
109
110     if (WKWebView *relatedWebView = [_configuration _relatedWebView]) {
111         WKProcessPool *processPool = [_configuration processPool];
112         WKProcessPool *relatedWebViewProcessPool = [relatedWebView->_configuration processPool];
113         if (processPool && processPool != relatedWebViewProcessPool)
114             [NSException raise:NSInvalidArgumentException format:@"Related web view %@ has process pool %@ but configuration specifies a different process pool %@", relatedWebView, relatedWebViewProcessPool, configuration.processPool];
115
116         [_configuration setProcessPool:relatedWebViewProcessPool];
117     }
118
119     if (![_configuration processPool])
120         [_configuration setProcessPool:adoptNS([[WKProcessPool alloc] init]).get()];
121
122     if (![_configuration preferences])
123         [_configuration setPreferences:adoptNS([[WKPreferences alloc] init]).get()];
124
125     CGRect bounds = self.bounds;
126
127     WebKit::WebContext& context = *[_configuration processPool]->_context;
128
129     WebKit::WebPageConfiguration webPageConfiguration;
130     webPageConfiguration.preferences = [_configuration preferences]->_preferences.get();
131     if (WKWebView *relatedWebView = [_configuration _relatedWebView])
132         webPageConfiguration.relatedPage = relatedWebView->_page.get();
133
134 #if PLATFORM(IOS)
135     _scrollView = adoptNS([[WKScrollView alloc] initWithFrame:bounds]);
136     [_scrollView setInternalDelegate:self];
137     [_scrollView setBouncesZoom:YES];
138
139     [self addSubview:_scrollView.get()];
140
141     _contentView = adoptNS([[WKContentView alloc] initWithFrame:bounds context:context configuration:std::move(webPageConfiguration)]);
142     _page = _contentView->_page;
143     [_contentView setDelegate:self];
144     [_contentView layer].anchorPoint = CGPointZero;
145     [_contentView setFrame:bounds];
146     [_scrollView addSubview:_contentView.get()];
147
148     [self _frameOrBoundsChanged];
149
150     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
151     [center addObserver:self selector:@selector(_keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
152     [center addObserver:self selector:@selector(_keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil];
153     [center addObserver:self selector:@selector(_keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
154     [center addObserver:self selector:@selector(_keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
155 #endif
156
157 #if PLATFORM(MAC)
158     _wkView = [[WKView alloc] initWithFrame:bounds context:context configuration:std::move(webPageConfiguration)];
159     [self addSubview:_wkView.get()];
160     _page = WebKit::toImpl([_wkView pageRef]);
161 #endif
162
163     _navigationState = std::make_unique<WebKit::NavigationState>(self);
164     _page->setPolicyClient(_navigationState->createPolicyClient());
165     _page->setLoaderClient(_navigationState->createLoaderClient());
166
167     _page->setUIClient(std::make_unique<WebKit::UIClient>(self));
168
169     return self;
170 }
171
172 - (void)dealloc
173 {
174     [_remoteObjectRegistry _invalidate];
175 #if PLATFORM(IOS)
176     [[NSNotificationCenter defaultCenter] removeObserver:self];
177 #endif
178
179     [super dealloc];
180 }
181
182 - (WKWebViewConfiguration *)configuration
183 {
184     return [[_configuration copy] autorelease];
185 }
186
187 - (WKBackForwardList *)backForwardList
188 {
189     return wrapper(_page->backForwardList());
190 }
191
192 - (id <WKNavigationDelegate>)navigationDelegate
193 {
194     return [_navigationState->navigationDelegate().leakRef() autorelease];
195 }
196
197 - (void)setNavigationDelegate:(id <WKNavigationDelegate>)navigationDelegate
198 {
199     _navigationState->setNavigationDelegate(navigationDelegate);
200 }
201
202 - (id <WKUIDelegate>)UIDelegate
203 {
204     return [static_cast<WebKit::UIClient&>(_page->uiClient()).delegate().leakRef() autorelease];
205 }
206
207 - (void)setUIDelegate:(id<WKUIDelegate>)UIDelegate
208 {
209     static_cast<WebKit::UIClient&>(_page->uiClient()).setDelegate(UIDelegate);
210 }
211
212 - (WKNavigation *)loadRequest:(NSURLRequest *)request
213 {
214     uint64_t navigationID = _page->loadRequest(request);
215     auto navigation = _navigationState->createLoadRequestNavigation(navigationID, request);
216
217     return [navigation.leakRef() autorelease];
218 }
219
220 - (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item
221 {
222     _page->goToBackForwardItem(&item._item);
223
224     // FIXME: return a WKNavigation object.
225     return nil;
226 }
227
228 - (IBAction)stopLoading:(id)sender
229 {
230     _page->stopLoading();
231 }
232
233 - (NSString *)title
234 {
235     return _page->pageLoadState().title();
236 }
237
238 - (NSURL *)activeURL
239 {
240     return [NSURL _web_URLWithWTFString:_page->pageLoadState().activeURL()];
241 }
242
243 - (BOOL)isLoading
244 {
245     return _page->pageLoadState().isLoading();
246 }
247
248 - (double)estimatedProgress
249 {
250     return _page->pageLoadState().estimatedProgress();
251 }
252
253 - (BOOL)hasOnlySecureContent
254 {
255     return _page->pageLoadState().hasOnlySecureContent();
256 }
257
258 // FIXME: This should be KVO compliant.
259 - (BOOL)canGoBack
260 {
261     return !!_page->backForwardList().backItem();
262 }
263
264 // FIXME: This should be KVO compliant.
265 - (BOOL)canGoForward
266 {
267     return !!_page->backForwardList().forwardItem();
268 }
269
270 // FIXME: This should return a WKNavigation object.
271 - (void)goBack
272 {
273     _page->goBack();
274 }
275
276 // FIXME: This should return a WKNavigation object.
277 - (void)goForward
278 {
279     _page->goForward();
280 }
281
282 #pragma mark iOS-specific methods
283
284 #if PLATFORM(IOS)
285 - (void)setFrame:(CGRect)frame
286 {
287     CGRect oldFrame = self.frame;
288     [super setFrame:frame];
289
290     if (!CGSizeEqualToSize(oldFrame.size, frame.size))
291         [self _frameOrBoundsChanged];
292 }
293
294 - (void)setBounds:(CGRect)bounds
295 {
296     CGRect oldBounds = self.bounds;
297     [super setBounds:bounds];
298
299     if (!CGSizeEqualToSize(oldBounds.size, bounds.size))
300         [self _frameOrBoundsChanged];
301 }
302
303 - (UIScrollView *)scrollView
304 {
305     return _scrollView.get();
306 }
307
308 - (WKBrowsingContextController *)browsingContextController
309 {
310     return [_contentView browsingContextController];
311 }
312
313 #pragma mark WKContentViewDelegate
314
315 - (void)contentViewDidCommitLoadForMainFrame:(WKContentView *)contentView
316 {
317     _isWaitingForNewLayerTreeAfterDidCommitLoad = YES;
318 }
319
320 - (void)contentView:(WKContentView *)contentView didCommitLayerTree:(const WebKit::RemoteLayerTreeTransaction&)layerTreeTransaction
321 {
322     [_scrollView setMinimumZoomScale:layerTreeTransaction.minimumScaleFactor()];
323     [_scrollView setMaximumZoomScale:layerTreeTransaction.maximumScaleFactor()];
324     [_scrollView setZoomEnabled:layerTreeTransaction.allowsUserScaling()];
325     if (![_scrollView isZooming] && ![_scrollView isZoomBouncing])
326         [_scrollView setZoomScale:layerTreeTransaction.pageScaleFactor()];
327
328     if (_gestureController)
329         _gestureController->setRenderTreeSize(layerTreeTransaction.renderTreeSize());
330
331     if (_isWaitingForNewLayerTreeAfterDidCommitLoad) {
332         UIEdgeInsets inset = [_scrollView contentInset];
333         [_scrollView setContentOffset:CGPointMake(-inset.left, -inset.top)];
334         _isWaitingForNewLayerTreeAfterDidCommitLoad = NO;
335     }
336     
337 }
338
339 - (RetainPtr<CGImageRef>)takeViewSnapshotForContentView:(WKContentView *)contentView
340 {
341     // FIXME: We should be able to use acquire an IOSurface directly, instead of going to CGImage here and back in ViewSnapshotStore.
342     UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, self.window.screen.scale);
343     [self drawViewHierarchyInRect:[self bounds] afterScreenUpdates:NO];
344     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
345     UIGraphicsEndImageContext();
346     return image.CGImage;
347 }
348
349 #pragma mark - UIScrollViewDelegate
350
351 - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
352 {
353     ASSERT(_scrollView == scrollView);
354     return _contentView.get();
355 }
356
357 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
358 {
359     if (scrollView.pinchGestureRecognizer.state == UIGestureRecognizerStateBegan)
360         [_contentView willStartUserTriggeredZoom];
361     [_contentView willStartZoomOrScroll];
362 }
363
364 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
365 {
366     if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan)
367         [_contentView willStartUserTriggeredScroll];
368     [_contentView willStartZoomOrScroll];
369 }
370
371 - (void)_didFinishScrolling
372 {
373     [self _updateVisibleContentRects];
374     [_contentView didFinishScrolling];
375 }
376
377 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
378 {
379     // If we're decelerating, scroll offset will be updated when scrollViewDidFinishDecelerating: is called.
380     if (!decelerate)
381         [self _didFinishScrolling];
382 }
383
384 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
385 {
386     [self _didFinishScrolling];
387 }
388
389 - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
390 {
391     [self _didFinishScrolling];
392 }
393
394 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
395 {
396     [self _updateVisibleContentRects];
397 }
398
399 - (void)scrollViewDidZoom:(UIScrollView *)scrollView
400 {
401     [self _updateVisibleContentRects];
402 }
403
404 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
405 {
406     ASSERT(scrollView == _scrollView);
407     [self _updateVisibleContentRects];
408     [_contentView didZoomToScale:scale];
409 }
410
411 - (void)_frameOrBoundsChanged
412 {
413     CGRect bounds = self.bounds;
414
415     if (!_hasStaticMinimumLayoutSize)
416         [_contentView setMinimumLayoutSize:bounds.size];
417     [_scrollView setFrame:bounds];
418     [_contentView setMinimumSize:bounds.size];
419     [self _updateVisibleContentRects];
420 }
421
422 - (void)_updateVisibleContentRects
423 {
424     CGRect fullViewRect = self.bounds;
425     CGRect visibleRectInContentCoordinates = [self convertRect:fullViewRect toView:_contentView.get()];
426
427     CGRect unobscuredRect = UIEdgeInsetsInsetRect(fullViewRect, _obscuredInsets);
428     CGRect unobscuredRectInContentCoordinates = [self convertRect:unobscuredRect toView:_contentView.get()];
429
430     CGFloat scaleFactor = [_scrollView zoomScale];
431
432     [_contentView didUpdateVisibleRect:visibleRectInContentCoordinates unobscuredRect:unobscuredRectInContentCoordinates scale:scaleFactor];
433 }
434
435 - (void)_keyboardChangedWithInfo:(NSDictionary *)keyboardInfo adjustScrollView:(BOOL)adjustScrollView
436 {
437     // FIXME: We will also need to adjust the unobscured rect by taking into account the keyboard rect and the obscured insets.
438     if (adjustScrollView)
439         [_scrollView _adjustForAutomaticKeyboardInfo:keyboardInfo animated:YES lastAdjustment:&_lastAdjustmentForScroller];
440 }
441
442 - (void)_keyboardWillChangeFrame:(NSNotification *)notification
443 {
444     if ([_contentView isAssistingNode])
445         [self _keyboardChangedWithInfo:notification.userInfo adjustScrollView:YES];
446 }
447
448 - (void)_keyboardDidChangeFrame:(NSNotification *)notification
449 {
450     [self _keyboardChangedWithInfo:notification.userInfo adjustScrollView:NO];
451 }
452
453 - (void)_keyboardWillShow:(NSNotification *)notification
454 {
455     if ([_contentView isAssistingNode])
456         [self _keyboardChangedWithInfo:notification.userInfo adjustScrollView:YES];
457 }
458
459 - (void)_keyboardWillHide:(NSNotification *)notification
460 {
461     // Ignore keyboard will hide notifications sent during rotation. They're just there for
462     // backwards compatibility reasons and processing the will hide notification would
463     // temporarily screw up the the unobscured view area.
464     if ([[UIPeripheralHost sharedInstance] rotationState])
465         return;
466
467     [self _keyboardChangedWithInfo:notification.userInfo adjustScrollView:YES];
468 }
469
470 - (void)setAllowsBackForwardNavigationGestures:(BOOL)allowsBackForwardNavigationGestures
471 {
472     if (_allowsBackForwardNavigationGestures == allowsBackForwardNavigationGestures)
473         return;
474
475     _allowsBackForwardNavigationGestures = allowsBackForwardNavigationGestures;
476
477     if (allowsBackForwardNavigationGestures) {
478         if (!_gestureController) {
479             _gestureController = std::make_unique<WebKit::ViewGestureController>(*_page);
480             _gestureController->installSwipeHandler(self, [self scrollView]);
481         }
482     } else
483         _gestureController = nullptr;
484
485     _page->setShouldRecordNavigationSnapshots(allowsBackForwardNavigationGestures);
486 }
487
488 - (BOOL)allowsBackForwardNavigationGestures
489 {
490     return _allowsBackForwardNavigationGestures;
491 }
492
493 #endif
494
495 #pragma mark OS X-specific methods
496
497 #if PLATFORM(MAC)
498
499 - (void)resizeSubviewsWithOldSize:(NSSize)oldSize
500 {
501     [_wkView setFrame:self.bounds];
502 }
503
504 - (void)setAllowsBackForwardNavigationGestures:(BOOL)allowsBackForwardNavigationGestures
505 {
506     [_wkView setAllowsBackForwardNavigationGestures:allowsBackForwardNavigationGestures];
507 }
508
509 - (BOOL)allowsBackForwardNavigationGestures
510 {
511     return [_wkView allowsBackForwardNavigationGestures];
512 }
513
514 - (void)setAllowsMagnification:(BOOL)allowsMagnification
515 {
516     [_wkView setAllowsMagnification:allowsMagnification];
517 }
518
519 - (BOOL)allowsMagnification
520 {
521     return [_wkView allowsMagnification];
522 }
523
524 - (void)setMagnification:(CGFloat)magnification
525 {
526     [_wkView setMagnification:magnification];
527 }
528
529 - (CGFloat)magnification
530 {
531     return [_wkView magnification];
532 }
533
534 - (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point
535 {
536     [_wkView setMagnification:magnification centeredAtPoint:NSPointFromCGPoint(point)];
537 }
538
539 #endif
540
541 @end
542
543 @implementation WKWebView (WKPrivate)
544
545 - (WKRemoteObjectRegistry *)_remoteObjectRegistry
546 {
547     if (!_remoteObjectRegistry) {
548         _remoteObjectRegistry = adoptNS([[WKRemoteObjectRegistry alloc] _initWithMessageSender:*_page]);
549         _page->process().context().addMessageReceiver(Messages::RemoteObjectRegistry::messageReceiverName(), _page->pageID(), [_remoteObjectRegistry remoteObjectRegistry]);
550     }
551
552     return _remoteObjectRegistry.get();
553 }
554
555 - (WKBrowsingContextHandle *)_handle
556 {
557     return [[[WKBrowsingContextHandle alloc] _initWithPageID:_page->pageID()] autorelease];
558 }
559
560 - (_WKRenderingProgressEvents)_observedRenderingProgressEvents
561 {
562     return _observedRenderingProgressEvents;
563 }
564
565 - (id <WKHistoryDelegatePrivate>)_historyDelegate
566 {
567     return [_navigationState->historyDelegate().leakRef() autorelease];
568 }
569
570 - (void)_setHistoryDelegate:(id <WKHistoryDelegatePrivate>)historyDelegate
571 {
572     _navigationState->setHistoryDelegate(historyDelegate);
573 }
574
575 - (NSURL *)_unreachableURL
576 {
577     return [NSURL _web_URLWithWTFString:_page->pageLoadState().unreachableURL()];
578 }
579
580 - (void)_loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
581 {
582     _page->loadAlternateHTMLString(string, [baseURL _web_originalDataAsWTFString], [unreachableURL _web_originalDataAsWTFString]);
583 }
584
585 - (WKNavigation *)_reload
586 {
587     _page->reload(false);
588
589     // FIXME: return a WKNavigation object.
590     return nil;
591 }
592
593 - (NSArray *)_certificateChain
594 {
595     if (WebKit::WebFrameProxy* mainFrame = _page->mainFrame())
596         return mainFrame->certificateInfo() ? (NSArray *)mainFrame->certificateInfo()->certificateInfo().certificateChain() : nil;
597
598     return nil;
599 }
600
601 - (NSURL *)_committedURL
602 {
603     return [NSURL _web_URLWithWTFString:_page->pageLoadState().url()];
604 }
605
606 - (NSString *)_applicationNameForUserAgent
607 {
608     return _page->applicationNameForUserAgent();
609 }
610
611 - (void)_setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
612 {
613     _page->setApplicationNameForUserAgent(applicationNameForUserAgent);
614 }
615
616 - (pid_t)_webProcessIdentifier
617 {
618     return _page->processIdentifier();
619 }
620
621 - (NSData *)_sessionState
622 {
623     return [wrapper(*_page->sessionStateData(nullptr, nullptr).leakRef()) autorelease];
624 }
625
626 static void releaseNSData(unsigned char*, const void* data)
627 {
628     [(NSData *)data release];
629 }
630
631 - (void)_restoreFromSessionState:(NSData *)sessionState
632 {
633     [sessionState retain];
634     _page->restoreFromSessionStateData(API::Data::createWithoutCopying((const unsigned char*)sessionState.bytes, sessionState.length, releaseNSData, sessionState).get());
635 }
636
637 - (BOOL)_privateBrowsingEnabled
638 {
639     return [_configuration preferences]->_preferences->privateBrowsingEnabled();
640 }
641
642 - (void)_setPrivateBrowsingEnabled:(BOOL)privateBrowsingEnabled
643 {
644     [_configuration preferences]->_preferences->setPrivateBrowsingEnabled(privateBrowsingEnabled);
645 }
646
647 static inline WebCore::LayoutMilestones layoutMilestones(_WKRenderingProgressEvents events)
648 {
649     WebCore::LayoutMilestones milestones = 0;
650
651     if (events & _WKRenderingProgressEventFirstLayout)
652         milestones |= WebCore::DidFirstLayout;
653
654     if (events & _WKRenderingProgressEventFirstPaintWithSignificantArea)
655         milestones |= WebCore::DidHitRelevantRepaintedObjectsAreaThreshold;
656
657     return milestones;
658 }
659
660 - (void)_setObservedRenderingProgressEvents:(_WKRenderingProgressEvents)observedRenderingProgressEvents
661 {
662     _observedRenderingProgressEvents = observedRenderingProgressEvents;
663     _page->listenForLayoutMilestones(layoutMilestones(observedRenderingProgressEvents));
664 }
665
666 #pragma mark iOS-specific methods
667
668 #if PLATFORM(IOS)
669
670 - (CGSize)_minimumLayoutSizeOverride
671 {
672     ASSERT(_hasStaticMinimumLayoutSize);
673     return _minimumLayoutSizeOverride;
674 }
675
676 - (void)_setMinimumLayoutSizeOverride:(CGSize)minimumLayoutSizeOverride
677 {
678     _hasStaticMinimumLayoutSize = YES;
679     _minimumLayoutSizeOverride = minimumLayoutSizeOverride;
680     [_contentView setMinimumLayoutSize:minimumLayoutSizeOverride];
681 }
682
683 - (UIEdgeInsets)_obscuredInsets
684 {
685     return _obscuredInsets;
686 }
687
688 - (void)_setObscuredInsets:(UIEdgeInsets)obscuredInsets
689 {
690     ASSERT(obscuredInsets.top >= 0);
691     ASSERT(obscuredInsets.left >= 0);
692     ASSERT(obscuredInsets.bottom >= 0);
693     ASSERT(obscuredInsets.right >= 0);
694     _obscuredInsets = obscuredInsets;
695     [self _updateVisibleContentRects];
696 }
697
698 - (UIColor *)_pageExtendedBackgroundColor
699 {
700     WebCore::Color color = _page->pageExtendedBackgroundColor();
701     if (!color.isValid())
702         return nil;
703
704     return [UIColor colorWithRed:(color.red() / 255.0) green:(color.green() / 255.0) blue:(color.blue() / 255.0) alpha:(color.alpha() / 255.0)];
705 }
706
707 - (void)_setBackgroundExtendsBeyondPage:(BOOL)backgroundExtends
708 {
709     _page->setBackgroundExtendsBeyondPage(backgroundExtends);
710 }
711
712 - (BOOL)_backgroundExtendsBeyondPage
713 {
714     return _page->backgroundExtendsBeyondPage();
715 }
716
717 - (void)_beginInteractiveObscuredInsetsChange
718 {
719     ASSERT(!_isChangingObscuredInsetsInteractively);
720     _isChangingObscuredInsetsInteractively = YES;
721 }
722
723 - (void)_endInteractiveObscuredInsetsChange
724 {
725     ASSERT(_isChangingObscuredInsetsInteractively);
726     _isChangingObscuredInsetsInteractively = NO;
727 }
728
729 #endif
730
731 @end
732
733 #endif // WK_API_ENABLED