Re-landing:
[WebKit-https.git] / Tools / MiniBrowser / mac / WK2BrowserWindowController.m
1 /*
2  * Copyright (C) 2010-2016 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 "WK2BrowserWindowController.h"
27
28 #if WK_API_ENABLED
29
30 #import "AppDelegate.h"
31 #import "SettingsController.h"
32 #import <WebKit/WKFrameInfo.h>
33 #import <WebKit/WKNavigationActionPrivate.h>
34 #import <WebKit/WKNavigationDelegate.h>
35 #import <WebKit/WKPreferencesPrivate.h>
36 #import <WebKit/WKUIDelegate.h>
37 #import <WebKit/WKWebViewConfigurationPrivate.h>
38 #import <WebKit/WKWebViewPrivate.h>
39 #import <WebKit/WKWebsiteDataStorePrivate.h>
40 #import <WebKit/WebNSURLExtras.h>
41 #import <WebKit/_WKIconLoadingDelegate.h>
42 #import <WebKit/_WKLinkIconParameters.h>
43 #import <WebKit/_WKUserInitiatedAction.h>
44
45 static void* keyValueObservingContext = &keyValueObservingContext;
46
47 @interface WK2BrowserWindowController () <WKNavigationDelegate, WKUIDelegate, _WKIconLoadingDelegate>
48 @end
49
50 @implementation WK2BrowserWindowController {
51     WKWebViewConfiguration *_configuration;
52     WKWebView *_webView;
53     BOOL _zoomTextOnly;
54     BOOL _isPrivateBrowsingWindow;
55
56     BOOL _useShrinkToFit;
57 }
58
59 - (void)awakeFromNib
60 {
61     _webView = [[WKWebView alloc] initWithFrame:[containerView bounds] configuration:_configuration];
62     [self didChangeSettings];
63
64     _webView.allowsMagnification = YES;
65     _webView.allowsBackForwardNavigationGestures = YES;
66
67     [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
68     [containerView addSubview:_webView];
69
70     [progressIndicator bind:NSHiddenBinding toObject:_webView withKeyPath:@"loading" options:@{ NSValueTransformerNameBindingOption : NSNegateBooleanTransformerName }];
71     [progressIndicator bind:NSValueBinding toObject:_webView withKeyPath:@"estimatedProgress" options:nil];
72
73     [_webView addObserver:self forKeyPath:@"title" options:0 context:keyValueObservingContext];
74     [_webView addObserver:self forKeyPath:@"URL" options:0 context:keyValueObservingContext];
75
76     _webView.navigationDelegate = self;
77     _webView.UIDelegate = self;
78
79     // This setting installs the new WK2 Icon Loading Delegate and tests that mechanism by
80     // telling WebKit to load every icon referenced by the page.
81     if ([[SettingsController shared] loadsAllSiteIcons])
82         _webView._iconLoadingDelegate = self;
83     
84     _webView._observedRenderingProgressEvents = _WKRenderingProgressEventFirstLayout
85         | _WKRenderingProgressEventFirstVisuallyNonEmptyLayout
86         | _WKRenderingProgressEventFirstPaintWithSignificantArea
87         | _WKRenderingProgressEventFirstLayoutAfterSuppressedIncrementalRendering
88         | _WKRenderingProgressEventFirstPaintAfterSuppressedIncrementalRendering;
89
90     _zoomTextOnly = NO;
91 }
92
93 - (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration
94 {
95     if (!(self = [super initWithWindowNibName:@"BrowserWindow"]))
96         return nil;
97
98     _configuration = [configuration copy];
99     _isPrivateBrowsingWindow = !_configuration.websiteDataStore.isPersistent;
100
101     return self;
102 }
103
104 - (void)dealloc
105 {
106     [_webView removeObserver:self forKeyPath:@"title"];
107     [_webView removeObserver:self forKeyPath:@"URL"];
108     
109     [progressIndicator unbind:NSHiddenBinding];
110     [progressIndicator unbind:NSValueBinding];
111
112     [_webView release];
113     [_configuration release];
114
115     [super dealloc];
116 }
117
118 - (IBAction)fetch:(id)sender
119 {
120     [urlText setStringValue:[self addProtocolIfNecessary:[urlText stringValue]]];
121
122     [_webView loadRequest:[NSURLRequest requestWithURL:[NSURL _webkit_URLWithUserTypedString:[urlText stringValue]]]];
123 }
124
125 - (IBAction)showHideWebView:(id)sender
126 {
127     BOOL hidden = ![_webView isHidden];
128     
129     [_webView setHidden:hidden];
130 }
131
132 - (IBAction)removeReinsertWebView:(id)sender
133 {
134     if ([_webView window]) {
135         [_webView retain];
136         [_webView removeFromSuperview]; 
137     } else {
138         [containerView addSubview:_webView];
139         [_webView release];
140     }
141 }
142
143 - (IBAction)setPageScale:(id)sender
144 {
145     CGFloat scale = [self pageScaleForMenuItemTag:[sender tag]];
146     [_webView _setPageScale:scale withOrigin:CGPointZero];
147 }
148
149 - (CGFloat)viewScaleForMenuItemTag:(NSInteger)tag
150 {
151     if (tag == 1)
152         return 1;
153     if (tag == 2)
154         return 0.75;
155     if (tag == 3)
156         return 0.5;
157     if (tag == 4)
158         return 0.25;
159
160     return 1;
161 }
162
163 - (IBAction)setViewScale:(id)sender
164 {
165     CGFloat scale = [self viewScaleForMenuItemTag:[sender tag]];
166     CGFloat oldScale = [_webView _viewScale];
167
168     if (scale == oldScale)
169         return;
170
171     [_webView _setLayoutMode:_WKLayoutModeDynamicSizeComputedFromViewScale];
172
173     NSRect oldFrame = self.window.frame;
174     NSSize newFrameSize = NSMakeSize(oldFrame.size.width * (scale / oldScale), oldFrame.size.height * (scale / oldScale));
175     [self.window setFrame:NSMakeRect(oldFrame.origin.x, oldFrame.origin.y - (newFrameSize.height - oldFrame.size.height), newFrameSize.width, newFrameSize.height) display:NO animate:NO];
176
177     [_webView _setViewScale:scale];
178 }
179
180 static BOOL areEssentiallyEqual(double a, double b)
181 {
182     double tolerance = 0.001;
183     return (fabs(a - b) <= tolerance);
184 }
185
186 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
187 {
188     SEL action = [menuItem action];
189
190     if (action == @selector(zoomIn:))
191         return [self canZoomIn];
192     if (action == @selector(zoomOut:))
193         return [self canZoomOut];
194     if (action == @selector(resetZoom:))
195         return [self canResetZoom];
196     
197     // Disabled until missing WK2 functionality is exposed via API/SPI.
198     if (action == @selector(dumpSourceToConsole:)
199         || action == @selector(find:)
200         || action == @selector(forceRepaint:))
201         return NO;
202     
203     if (action == @selector(showHideWebView:))
204         [menuItem setTitle:[_webView isHidden] ? @"Show Web View" : @"Hide Web View"];
205     else if (action == @selector(removeReinsertWebView:))
206         [menuItem setTitle:[_webView window] ? @"Remove Web View" : @"Insert Web View"];
207     else if (action == @selector(toggleZoomMode:))
208         [menuItem setState:_zoomTextOnly ? NSOnState : NSOffState];
209
210     if (action == @selector(setPageScale:))
211         [menuItem setState:areEssentiallyEqual([_webView _pageScale], [self pageScaleForMenuItemTag:[menuItem tag]])];
212
213     if (action == @selector(setViewScale:))
214         [menuItem setState:areEssentiallyEqual([_webView _viewScale], [self viewScaleForMenuItemTag:[menuItem tag]])];
215
216     return YES;
217 }
218
219 - (IBAction)reload:(id)sender
220 {
221     [_webView reload];
222 }
223
224 - (IBAction)forceRepaint:(id)sender
225 {
226     // FIXME: This doesn't actually force a repaint.
227     [_webView setNeedsDisplay:YES];
228 }
229
230 - (IBAction)goBack:(id)sender
231 {
232     [_webView goBack];
233 }
234
235 - (IBAction)goForward:(id)sender
236 {
237     [_webView goForward];
238 }
239
240 - (IBAction)toggleZoomMode:(id)sender
241 {
242     if (_zoomTextOnly) {
243         _zoomTextOnly = NO;
244         double currentTextZoom = _webView._textZoomFactor;
245         _webView._textZoomFactor = 1;
246         _webView._pageZoomFactor = currentTextZoom;
247     } else {
248         _zoomTextOnly = YES;
249         double currentPageZoom = _webView._pageZoomFactor;
250         _webView._textZoomFactor = currentPageZoom;
251         _webView._pageZoomFactor = 1;
252     }
253 }
254
255 - (IBAction)resetZoom:(id)sender
256 {
257     if (![self canResetZoom])
258         return;
259
260     if (_zoomTextOnly)
261         _webView._textZoomFactor = 1;
262     else
263         _webView._pageZoomFactor = 1;
264 }
265
266 - (BOOL)canResetZoom
267 {
268     return _zoomTextOnly ? (_webView._textZoomFactor != 1) : (_webView._pageZoomFactor != 1);
269 }
270
271 - (IBAction)toggleShrinkToFit:(id)sender
272 {
273     _useShrinkToFit = !_useShrinkToFit;
274     toggleUseShrinkToFitButton.image = _useShrinkToFit ? [NSImage imageNamed:@"NSExitFullScreenTemplate"] : [NSImage imageNamed:@"NSEnterFullScreenTemplate"];
275     [_webView _setLayoutMode:_useShrinkToFit ? _WKLayoutModeDynamicSizeComputedFromMinimumDocumentSize : _WKLayoutModeViewSize];
276 }
277
278 - (IBAction)dumpSourceToConsole:(id)sender
279 {
280 }
281
282 - (NSURL *)currentURL
283 {
284     return _webView.URL;
285 }
286
287 - (NSView *)mainContentView
288 {
289     return _webView;
290 }
291
292 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
293 {
294     SEL action = item.action;
295
296     if (action == @selector(goBack:) || action == @selector(goForward:))
297         return [_webView validateUserInterfaceItem:item];
298
299     return YES;
300 }
301
302 - (void)validateToolbar
303 {
304     [toolbar validateVisibleItems];
305 }
306
307 - (BOOL)windowShouldClose:(id)sender
308 {
309     return YES;
310 }
311
312 - (void)windowWillClose:(NSNotification *)notification
313 {
314     [(BrowserAppDelegate *)[[NSApplication sharedApplication] delegate] browserWindowWillClose:self.window];
315     [self autorelease];
316 }
317
318 - (void)applicationTerminating
319 {
320 }
321
322 #define DefaultMinimumZoomFactor (.5)
323 #define DefaultMaximumZoomFactor (3.0)
324 #define DefaultZoomFactorRatio (1.2)
325
326 - (CGFloat)currentZoomFactor
327 {
328     return _zoomTextOnly ? _webView._textZoomFactor : _webView._pageZoomFactor;
329 }
330
331 - (void)setCurrentZoomFactor:(CGFloat)factor
332 {
333     if (_zoomTextOnly)
334         _webView._textZoomFactor = factor;
335     else
336         _webView._pageZoomFactor = factor;
337 }
338
339 - (BOOL)canZoomIn
340 {
341     return self.currentZoomFactor * DefaultZoomFactorRatio < DefaultMaximumZoomFactor;
342 }
343
344 - (void)zoomIn:(id)sender
345 {
346     if (!self.canZoomIn)
347         return;
348
349     self.currentZoomFactor *= DefaultZoomFactorRatio;
350 }
351
352 - (BOOL)canZoomOut
353 {
354     return self.currentZoomFactor / DefaultZoomFactorRatio > DefaultMinimumZoomFactor;
355 }
356
357 - (void)zoomOut:(id)sender
358 {
359     if (!self.canZoomIn)
360         return;
361
362     self.currentZoomFactor /= DefaultZoomFactorRatio;
363 }
364
365 - (void)didChangeSettings
366 {
367     SettingsController *settings = [SettingsController shared];
368     WKPreferences *preferences = _webView.configuration.preferences;
369
370     preferences._tiledScrollingIndicatorVisible = settings.tiledScrollingIndicatorVisible;
371     preferences._compositingBordersVisible = settings.layerBordersVisible;
372     preferences._compositingRepaintCountersVisible = settings.layerBordersVisible;
373     preferences._simpleLineLayoutDebugBordersEnabled = settings.simpleLineLayoutDebugBordersEnabled;
374     preferences._acceleratedDrawingEnabled = settings.acceleratedDrawingEnabled;
375     preferences._resourceUsageOverlayVisible = settings.resourceUsageOverlayVisible;
376     preferences._displayListDrawingEnabled = settings.displayListDrawingEnabled;
377     preferences._visualViewportEnabled = settings.visualViewportEnabled;
378     preferences._largeImageAsyncDecodingEnabled = settings.largeImageAsyncDecodingEnabled;
379     preferences._animatedImageAsyncDecodingEnabled = settings.animatedImageAsyncDecodingEnabled;
380
381     _webView.configuration.websiteDataStore._resourceLoadStatisticsEnabled = settings.resourceLoadStatisticsEnabled;
382
383     BOOL useTransparentWindows = settings.useTransparentWindows;
384     if (useTransparentWindows != !_webView._drawsBackground) {
385         [self.window setOpaque:!useTransparentWindows];
386         [self.window setBackgroundColor:[NSColor clearColor]];
387         [self.window setHasShadow:!useTransparentWindows];
388
389         _webView._drawsBackground = !useTransparentWindows;
390
391         [self.window display];
392     }
393
394     BOOL usePaginatedMode = settings.usePaginatedMode;
395     if (usePaginatedMode != (_webView._paginationMode != _WKPaginationModeUnpaginated)) {
396         if (usePaginatedMode) {
397             _webView._paginationMode = _WKPaginationModeLeftToRight;
398             _webView._pageLength = _webView.bounds.size.width / 2;
399             _webView._gapBetweenPages = 10;
400         } else
401             _webView._paginationMode = _WKPaginationModeUnpaginated;
402     }
403     
404     NSUInteger visibleOverlayRegions = 0;
405     if (settings.nonFastScrollableRegionOverlayVisible)
406         visibleOverlayRegions |= _WKNonFastScrollableRegion;
407     if (settings.wheelEventHandlerRegionOverlayVisible)
408         visibleOverlayRegions |= _WKWheelEventHandlerRegion;
409     
410     preferences._visibleDebugOverlayRegions = visibleOverlayRegions;
411 }
412
413 - (void)updateTitle:(NSString *)title
414 {
415     if (!title) {
416         NSURL *url = _webView.URL;
417         title = url.lastPathComponent ?: url._web_userVisibleString;
418     }
419
420     self.window.title = [NSString stringWithFormat:@"%@%@ [WK2 %d]", _isPrivateBrowsingWindow ? @"🙈 " : @"", title, _webView._webProcessIdentifier];
421 }
422
423 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
424 {
425     if (context != keyValueObservingContext || object != _webView)
426         return;
427
428     if ([keyPath isEqualToString:@"title"])
429         [self updateTitle:_webView.title];
430     else if ([keyPath isEqualToString:@"URL"])
431         [self updateTextFieldFromURL:_webView.URL];
432 }
433
434 - (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures
435 {
436     WK2BrowserWindowController *controller = [[WK2BrowserWindowController alloc] initWithConfiguration:configuration];
437     [controller awakeFromNib];
438     [controller.window makeKeyAndOrderFront:self];
439
440     return controller->_webView;
441 }
442
443 - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
444 {
445     NSAlert* alert = [[NSAlert alloc] init];
446
447     [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [frame.request.URL absoluteString]]];
448     [alert setInformativeText:message];
449     [alert addButtonWithTitle:@"OK"];
450
451     [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
452         completionHandler();
453         [alert release];
454     }];
455 }
456
457 - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
458 {
459     NSAlert* alert = [[NSAlert alloc] init];
460
461     [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [frame.request.URL  absoluteString]]];
462     [alert setInformativeText:message];
463     
464     [alert addButtonWithTitle:@"OK"];
465     [alert addButtonWithTitle:@"Cancel"];
466
467     [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
468         completionHandler(response == NSAlertFirstButtonReturn);
469         [alert release];
470     }];
471 }
472
473 - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *result))completionHandler
474 {
475     NSAlert* alert = [[NSAlert alloc] init];
476
477     [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [frame.request.URL absoluteString]]];
478     [alert setInformativeText:prompt];
479     
480     [alert addButtonWithTitle:@"OK"];
481     [alert addButtonWithTitle:@"Cancel"];
482     
483     NSTextField* input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
484     [input setStringValue:defaultText];
485     [alert setAccessoryView:input];
486     
487     [alert beginSheetModalForWindow:self.window completionHandler:^void (NSModalResponse response) {
488         [input validateEditing];
489         completionHandler(response == NSAlertFirstButtonReturn ? [input stringValue] : nil);
490         [alert release];
491     }];
492 }
493
494 #if __has_feature(objc_generics)
495 - (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * URLs))completionHandler
496 #else
497 - (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray *URLs))completionHandler
498 #endif
499 {
500     NSOpenPanel *openPanel = [NSOpenPanel openPanel];
501
502     openPanel.allowsMultipleSelection = parameters.allowsMultipleSelection;
503
504     [openPanel beginSheetModalForWindow:webView.window completionHandler:^(NSInteger result) {
505         if (result == NSFileHandlingPanelOKButton)
506             completionHandler(openPanel.URLs);
507         else
508             completionHandler(nil);
509     }];
510 }
511
512 - (void)updateTextFieldFromURL:(NSURL *)URL
513 {
514     if (!URL)
515         return;
516
517     if (!URL.absoluteString.length)
518         return;
519
520     urlText.stringValue = [URL _web_userVisibleString];
521 }
522
523 - (void)loadURLString:(NSString *)urlString
524 {
525     // FIXME: We shouldn't have to set the url text here.
526     [urlText setStringValue:urlString];
527     [self fetch:nil];
528 }
529
530 - (IBAction)performFindPanelAction:(id)sender
531 {
532     [findPanelWindow makeKeyAndOrderFront:sender];
533 }
534
535 - (IBAction)find:(id)sender
536 {
537 }
538
539 static NSSet *dataTypes()
540 {
541     return [WKWebsiteDataStore allWebsiteDataTypes];
542 }
543
544 - (IBAction)fetchWebsiteData:(id)sender
545 {
546     [_configuration.websiteDataStore _fetchDataRecordsOfTypes:dataTypes() withOptions:_WKWebsiteDataStoreFetchOptionComputeSizes completionHandler:^(NSArray *websiteDataRecords) {
547         NSLog(@"did fetch website data %@.", websiteDataRecords);
548     }];
549 }
550
551 - (IBAction)fetchAndClearWebsiteData:(id)sender
552 {
553     [_configuration.websiteDataStore fetchDataRecordsOfTypes:dataTypes() completionHandler:^(NSArray *websiteDataRecords) {
554         [_configuration.websiteDataStore removeDataOfTypes:dataTypes() forDataRecords:websiteDataRecords completionHandler:^{
555             [_configuration.websiteDataStore fetchDataRecordsOfTypes:dataTypes() completionHandler:^(NSArray *websiteDataRecords) {
556                 NSLog(@"did clear website data, after clearing data is %@.", websiteDataRecords);
557             }];
558         }];
559     }];
560 }
561
562 - (IBAction)clearWebsiteData:(id)sender
563 {
564     [_configuration.websiteDataStore removeDataOfTypes:dataTypes() modifiedSince:[NSDate distantPast] completionHandler:^{
565         NSLog(@"Did clear website data.");
566     }];
567 }
568
569 - (IBAction)printWebView:(id)sender
570 {
571     [[_webView _printOperationWithPrintInfo:[NSPrintInfo sharedPrintInfo]] runOperationModalForWindow:self.window delegate:nil didRunSelector:nil contextInfo:nil];
572 }
573
574 #pragma mark WKNavigationDelegate
575
576 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
577 {
578     LOG(@"decidePolicyForNavigationAction");
579
580     if (navigationAction._canHandleRequest) {
581         decisionHandler(WKNavigationActionPolicyAllow);
582         return;
583     }
584
585     if (navigationAction._userInitiatedAction && !navigationAction._userInitiatedAction.isConsumed) {
586         [navigationAction._userInitiatedAction consume];
587         [[NSWorkspace sharedWorkspace] openURL:navigationAction.request.URL];
588     }
589
590     decisionHandler(WKNavigationActionPolicyCancel);
591 }
592
593 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
594 {
595     LOG(@"decidePolicyForNavigationResponse");
596     decisionHandler(WKNavigationResponsePolicyAllow);
597 }
598
599 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
600 {
601     LOG(@"didStartProvisionalNavigation: %@", navigation);
602 }
603
604 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
605 {
606     LOG(@"didReceiveServerRedirectForProvisionalNavigation: %@", navigation);
607 }
608
609 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error
610 {
611     LOG(@"didFailProvisionalNavigation: %@navigation, error: %@", navigation, error);
612 }
613
614 - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
615 {
616     LOG(@"didCommitNavigation: %@", navigation);
617     [self updateTitle:nil];
618 }
619
620 - (void)webView:(WKWebView *)webView didFinishLoadingNavigation:(WKNavigation *)navigation
621 {
622     LOG(@"didFinishLoadingNavigation: %@", navigation);
623 }
624
625 - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler
626 {
627     LOG(@"didReceiveAuthenticationChallenge: %@", challenge);
628     completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
629 }
630
631 - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
632 {
633     LOG(@"didFailNavigation: %@, error %@", navigation, error);
634 }
635
636 - (void)_webViewWebProcessDidCrash:(WKWebView *)webView
637 {
638     NSLog(@"WebContent process crashed; reloading");
639     [self reload:nil];
640 }
641
642 - (void)_webView:(WKWebView *)webView renderingProgressDidChange:(_WKRenderingProgressEvents)progressEvents
643 {
644     if (progressEvents & _WKRenderingProgressEventFirstLayout)
645         LOG(@"renderingProgressDidChange: %@", @"first layout");
646
647     if (progressEvents & _WKRenderingProgressEventFirstVisuallyNonEmptyLayout)
648         LOG(@"renderingProgressDidChange: %@", @"first visually non-empty layout");
649
650     if (progressEvents & _WKRenderingProgressEventFirstPaintWithSignificantArea)
651         LOG(@"renderingProgressDidChange: %@", @"first paint with significant area");
652
653     if (progressEvents & _WKRenderingProgressEventFirstLayoutAfterSuppressedIncrementalRendering)
654         LOG(@"renderingProgressDidChange: %@", @"first layout after suppressed incremental rendering");
655
656     if (progressEvents & _WKRenderingProgressEventFirstPaintAfterSuppressedIncrementalRendering)
657         LOG(@"renderingProgressDidChange: %@", @"first paint after suppressed incremental rendering");
658 }
659
660 - (void)webView:(WKWebView *)webView shouldLoadIconWithParameters:(_WKLinkIconParameters *)parameters completionHandler:(void (^)(void (^)(NSData*)))completionHandler
661 {
662     completionHandler(^void (NSData *data) {
663         LOG(@"Icon URL %@ received icon data of length %u", parameters.url, (unsigned)data.length);
664     });
665 }
666
667 @end
668
669 #endif // WK_API_ENABLED