2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #import "BrowserWindowController.h"
28 #import <WebKit2/WKPagePrivate.h>
29 #import <WebKit2/WKStringCF.h>
30 #import <WebKit2/WKURLCF.h>
32 @interface BrowserWindowController ()
33 - (void)didStartProgress;
34 - (void)didChangeProgress:(double)value;
35 - (void)didFinishProgress;
36 - (void)didStartProvisionalLoadForFrame:(WKFrameRef)frame;
37 - (void)didCommitLoadForFrame:(WKFrameRef)frame;
38 - (void)didReceiveServerRedirectForProvisionalLoadForFrame:(WKFrameRef)frame;
39 - (void)didFailProvisionalLoadWithErrorForFrame:(WKFrameRef)frame;
40 - (void)didFailLoadWithErrorForFrame:(WKFrameRef)frame;
41 - (void)didSameDocumentNavigationForFrame:(WKFrameRef)frame;
44 @implementation BrowserWindowController
46 - (id)initWithContext:(WKContextRef)context
48 if ((self = [super initWithWindowNibName:@"BrowserWindow"])) {
49 _context = WKRetain(context);
62 - (IBAction)fetch:(id)sender
64 CFURLRef cfURL = CFURLCreateWithString(0, (CFStringRef)[urlText stringValue], 0);
68 WKURLRef url = WKURLCreateWithCFURL(cfURL);
71 WKPageLoadURL(_webView.pageRef, url);
75 - (IBAction)showHideWebView:(id)sender
77 BOOL hidden = ![_webView isHidden];
79 [_webView setHidden:hidden];
82 - (IBAction)removeReinsertWebView:(id)sender
84 if ([_webView window]) {
86 [_webView removeFromSuperview];
88 [containerView addSubview:_webView];
93 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
95 SEL action = [menuItem action];
97 if (action == @selector(zoomIn:))
98 return [self canZoomIn];
99 if (action == @selector(zoomOut:))
100 return [self canZoomOut];
101 if (action == @selector(resetZoom:))
102 return [self canResetZoom];
104 if (action == @selector(showHideWebView:))
105 [menuItem setTitle:[_webView isHidden] ? @"Show Web View" : @"Hide Web View"];
106 else if (action == @selector(removeReinsertWebView:))
107 [menuItem setTitle:[_webView window] ? @"Remove Web View" : @"Insert Web View"];
108 else if (action == @selector(toggleZoomMode:))
109 [menuItem setState:_zoomTextOnly ? NSOnState : NSOffState];
113 - (IBAction)reload:(id)sender
115 WKPageReload(_webView.pageRef);
118 - (IBAction)forceRepaint:(id)sender
120 [_webView setNeedsDisplay:YES];
123 - (IBAction)goBack:(id)sender
125 WKPageGoBack(_webView.pageRef);
128 - (IBAction)goForward:(id)sender
130 WKPageGoForward(_webView.pageRef);
133 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
135 SEL action = [item action];
137 if (action == @selector(goBack:))
138 return _webView && WKPageCanGoBack(_webView.pageRef);
140 if (action == @selector(goForward:))
141 return _webView && WKPageCanGoForward(_webView.pageRef);
146 - (void)validateToolbar
148 [toolbar validateVisibleItems];
151 - (BOOL)windowShouldClose:(id)sender
153 LOG(@"windowShouldClose");
154 BOOL canCloseImmediately = WKPageTryClose(_webView.pageRef);
155 return canCloseImmediately;
158 - (void)windowWillClose:(NSNotification *)notification
164 - (void)applicationTerminating
166 WKPageClose(_webView.pageRef);
167 WKRelease(_webView.pageRef);
170 #define DefaultMinimumZoomFactor (.5)
171 #define DefaultMaximumZoomFactor (3.0)
172 #define DefaultZoomFactorRatio (1.2)
174 - (double)currentZoomFactor
176 return _zoomTextOnly ? WKPageGetTextZoomFactor(_webView.pageRef) : WKPageGetPageZoomFactor(_webView.pageRef);
179 - (void)setCurrentZoomFactor:(double)factor
181 _zoomTextOnly ? WKPageSetTextZoomFactor(_webView.pageRef, factor) : WKPageSetPageZoomFactor(_webView.pageRef, factor);
186 return [self currentZoomFactor] * DefaultZoomFactorRatio < DefaultMaximumZoomFactor;
189 - (void)zoomIn:(id)sender
191 if (![self canZoomIn])
194 double factor = [self currentZoomFactor] * DefaultZoomFactorRatio;
195 [self setCurrentZoomFactor:factor];
200 return [self currentZoomFactor] / DefaultZoomFactorRatio > DefaultMinimumZoomFactor;
203 - (void)zoomOut:(id)sender
205 if (![self canZoomIn])
208 double factor = [self currentZoomFactor] / DefaultZoomFactorRatio;
209 [self setCurrentZoomFactor:factor];
214 return _zoomTextOnly ? (WKPageGetTextZoomFactor(_webView.pageRef) != 1) : (WKPageGetPageZoomFactor(_webView.pageRef) != 1);
217 - (void)resetZoom:(id)sender
219 if (![self canResetZoom])
223 WKPageSetTextZoomFactor(_webView.pageRef, 1);
225 WKPageSetPageZoomFactor(_webView.pageRef, 1);
228 - (IBAction)toggleZoomMode:(id)sender
232 double currentTextZoom = WKPageGetTextZoomFactor(_webView.pageRef);
233 WKPageSetPageAndTextZoomFactors(_webView.pageRef, currentTextZoom, 1);
236 double currentPageZoom = WKPageGetPageZoomFactor(_webView.pageRef);
237 WKPageSetPageAndTextZoomFactors(_webView.pageRef, 1, currentPageZoom);
241 - (IBAction)dumpSourceToConsole:(id)sender
243 WKPageGetSourceForFrame_b(_webView.pageRef, WKPageGetMainFrame(_webView.pageRef), ^(WKStringRef result, WKErrorRef error) {
244 CFStringRef cfResult = WKStringCopyCFString(0, result);
245 LOG(@"Main frame source\n \"%@\"", (NSString *)cfResult);
250 // MARK: Loader Client Callbacks
252 static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
254 [(BrowserWindowController *)clientInfo didStartProvisionalLoadForFrame:frame];
257 static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
259 [(BrowserWindowController *)clientInfo didReceiveServerRedirectForProvisionalLoadForFrame:frame];
262 static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo)
264 [(BrowserWindowController *)clientInfo didFailProvisionalLoadWithErrorForFrame:frame];
267 static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
269 [(BrowserWindowController *)clientInfo didCommitLoadForFrame:frame];
272 static void didFinishDocumentLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
274 LOG(@"didFinishDocumentLoadForFrame");
277 static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
279 LOG(@"didFinishLoadForFrame");
282 static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo)
284 [(BrowserWindowController *)clientInfo didFailLoadWithErrorForFrame:frame];
287 static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
289 [(BrowserWindowController *)clientInfo didSameDocumentNavigationForFrame:frame];
292 static void didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
294 CFStringRef cfTitle = WKStringCopyCFString(0, title);
295 LOG(@"didReceiveTitleForFrame \"%@\"", (NSString *)cfTitle);
299 static void didFirstLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
301 LOG(@"didFirstLayoutForFrame");
304 static void didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
306 LOG(@"didFirstVisuallyNonEmptyLayoutForFrame");
309 static void didRemoveFrameFromHierarchy(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
311 LOG(@"didRemoveFrameFromHierarchy");
314 static void didDisplayInsecureContentForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
316 LOG(@"didDisplayInsecureContentForFrame");
319 static void didRunInsecureContentForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
321 LOG(@"didRunInsecureContentForFrame");
324 static void didStartProgress(WKPageRef page, const void *clientInfo)
326 [(BrowserWindowController *)clientInfo didStartProgress];
329 static void didChangeProgress(WKPageRef page, const void *clientInfo)
331 [(BrowserWindowController *)clientInfo didChangeProgress:WKPageGetEstimatedProgress(page)];
334 static void didFinishProgress(WKPageRef page, const void *clientInfo)
336 [(BrowserWindowController *)clientInfo didFinishProgress];
339 static void didBecomeUnresponsive(WKPageRef page, const void *clientInfo)
341 LOG(@"didBecomeUnresponsive");
344 static void didBecomeResponsive(WKPageRef page, const void *clientInfo)
346 LOG(@"didBecomeResponsive");
349 static void processDidExit(WKPageRef page, const void *clientInfo)
351 LOG(@"processDidExit");
354 static void didChangeBackForwardList(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void *clientInfo)
356 [(BrowserWindowController *)clientInfo validateToolbar];
359 // MARK: Policy Client Callbacks
361 static void decidePolicyForNavigationAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
363 LOG(@"decidePolicyForNavigationAction");
364 WKFramePolicyListenerUse(listener);
367 static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKStringRef frameName, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
369 LOG(@"decidePolicyForNewWindowAction");
370 WKFramePolicyListenerUse(listener);
373 static void decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
375 WKFramePolicyListenerUse(listener);
378 // MARK: UI Client Callbacks
380 static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef request, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton button, const void* clientInfo)
382 LOG(@"createNewPage");
383 BrowserWindowController *controller = [[BrowserWindowController alloc] initWithContext:WKPageGetContext(page)];
384 [controller loadWindow];
386 return controller->_webView.pageRef;
389 static void showPage(WKPageRef page, const void *clientInfo)
392 [[(BrowserWindowController *)clientInfo window] orderFront:nil];
395 static void closePage(WKPageRef page, const void *clientInfo)
399 [[(BrowserWindowController *)clientInfo window] close];
403 static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
405 NSAlert* alert = [[NSAlert alloc] init];
407 WKURLRef wkURL = WKFrameCopyURL(frame);
408 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
411 [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [(NSURL *)cfURL absoluteString]]];
414 CFStringRef cfMessage = WKStringCopyCFString(0, message);
415 [alert setInformativeText:(NSString *)cfMessage];
416 CFRelease(cfMessage);
418 [alert addButtonWithTitle:@"OK"];
424 static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
426 NSAlert* alert = [[NSAlert alloc] init];
428 WKURLRef wkURL = WKFrameCopyURL(frame);
429 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
432 [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
435 CFStringRef cfMessage = WKStringCopyCFString(0, message);
436 [alert setInformativeText:(NSString *)cfMessage];
437 CFRelease(cfMessage);
439 [alert addButtonWithTitle:@"OK"];
440 [alert addButtonWithTitle:@"Cancel"];
442 NSInteger button = [alert runModal];
445 return button == NSAlertFirstButtonReturn;
448 static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, const void* clientInfo)
450 NSAlert* alert = [[NSAlert alloc] init];
452 WKURLRef wkURL = WKFrameCopyURL(frame);
453 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
456 [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [(NSURL *)cfURL absoluteString]]];
459 CFStringRef cfMessage = WKStringCopyCFString(0, message);
460 [alert setInformativeText:(NSString *)cfMessage];
461 CFRelease(cfMessage);
463 [alert addButtonWithTitle:@"OK"];
464 [alert addButtonWithTitle:@"Cancel"];
466 NSTextField* input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
467 CFStringRef cfDefaultValue = WKStringCopyCFString(0, defaultValue);
468 [input setStringValue:(NSString *)cfDefaultValue];
469 CFRelease(cfDefaultValue);
471 [alert setAccessoryView:input];
473 NSInteger button = [alert runModal];
475 NSString* result = nil;
476 if (button == NSAlertFirstButtonReturn) {
477 [input validateEditing];
478 result = [input stringValue];
485 return WKStringCreateWithCFString((CFStringRef)result);
488 static void setStatusText(WKPageRef page, WKStringRef text, const void* clientInfo)
490 LOG(@"setStatusText");
493 static void mouseDidMoveOverElement(WKPageRef page, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo)
495 LOG(@"mouseDidMoveOverElement");
498 static WKRect getWindowFrame(WKPageRef page, const void* clientInfo)
500 NSRect rect = [[(BrowserWindowController *)clientInfo window] frame];
502 wkRect.origin.x = rect.origin.x;
503 wkRect.origin.y = rect.origin.y;
504 wkRect.size.width = rect.size.width;
505 wkRect.size.height = rect.size.height;
509 static void setWindowFrame(WKPageRef page, WKRect rect, const void* clientInfo)
511 [[(BrowserWindowController *)clientInfo window] setFrame:NSMakeRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height) display:YES];
514 static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
516 NSAlert *alert = [[NSAlert alloc] init];
518 WKURLRef wkURL = WKFrameCopyURL(frame);
519 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
522 [alert setMessageText:[NSString stringWithFormat:@"BeforeUnload confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
525 CFStringRef cfMessage = WKStringCopyCFString(0, message);
526 [alert setInformativeText:(NSString *)cfMessage];
527 CFRelease(cfMessage);
529 [alert addButtonWithTitle:@"OK"];
530 [alert addButtonWithTitle:@"Cancel"];
532 NSInteger button = [alert runModal];
535 return button == NSAlertFirstButtonReturn;
538 static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void* clientInfo)
540 NSOpenPanel *openPanel = [NSOpenPanel openPanel];
541 [openPanel setAllowsMultipleSelection:WKOpenPanelParametersGetAllowsMultipleFiles(parameters)];
545 [openPanel beginSheetModalForWindow:[(BrowserWindowController *)clientInfo window] completionHandler:^(NSInteger result) {
546 if (result == NSFileHandlingPanelOKButton) {
547 WKMutableArrayRef fileURLs = WKMutableArrayCreate();
550 for (nsURL in [openPanel URLs]) {
551 WKURLRef wkURL = WKURLCreateWithCFURL((CFURLRef)nsURL);
552 WKArrayAppendItem(fileURLs, wkURL);
556 WKOpenPanelResultListenerChooseFiles(listener, fileURLs);
560 WKOpenPanelResultListenerCancel(listener);
568 _webView = [[WKView alloc] initWithFrame:[containerView frame] contextRef:_context];
570 [containerView addSubview:_webView];
571 [_webView setFrame:[containerView frame]];
573 [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
575 WKPageLoaderClient loadClient = {
576 kWKPageLoaderClientCurrentVersion,
577 self, /* clientInfo */
578 didStartProvisionalLoadForFrame,
579 didReceiveServerRedirectForProvisionalLoadForFrame,
580 didFailProvisionalLoadWithErrorForFrame,
581 didCommitLoadForFrame,
582 didFinishDocumentLoadForFrame,
583 didFinishLoadForFrame,
584 didFailLoadWithErrorForFrame,
585 didSameDocumentNavigationForFrame,
586 didReceiveTitleForFrame,
587 didFirstLayoutForFrame,
588 didFirstVisuallyNonEmptyLayoutForFrame,
589 didRemoveFrameFromHierarchy,
590 didDisplayInsecureContentForFrame,
591 didRunInsecureContentForFrame,
592 0, // canAuthenticateAgainstProtectionSpaceInFrame
593 0, // didReceiveAuthenticationChallengeInFrame
597 didBecomeUnresponsive,
600 didChangeBackForwardList,
601 0, // shouldGoToBackForwardItem
602 0 // didFailToInitializePlugin
604 WKPageSetPageLoaderClient(_webView.pageRef, &loadClient);
606 WKPagePolicyClient policyClient = {
607 kWKPagePolicyClientCurrentVersion,
608 self, /* clientInfo */
609 decidePolicyForNavigationAction,
610 decidePolicyForNewWindowAction,
611 decidePolicyForResponse,
612 0 /* unableToImplementPolicy */
614 WKPageSetPagePolicyClient(_webView.pageRef, &policyClient);
616 WKPageUIClient uiClient = {
617 kWKPageUIClientCurrentVersion,
618 self, /* clientInfo */
619 0, /* createNewPage_deprecatedForUseWithV0 */
626 runJavaScriptConfirm,
629 mouseDidMoveOverElement,
630 0, /* missingPluginButtonClicked */
631 0, /* didNotHandleKeyEvent */
632 0, /* didNotHandleWheelEvent */
633 0, /* toolbarsAreVisible */
634 0, /* setToolbarsAreVisible */
635 0, /* menuBarIsVisible */
636 0, /* setMenuBarIsVisible */
637 0, /* statusBarIsVisible */
638 0, /* setStatusBarIsVisible */
640 0, /* setIsResizable */
643 runBeforeUnloadConfirmPanel,
645 0, /* pageDidScroll */
646 0, /* exceededDatabaseQuota */
648 0, /* decidePolicyForGeolocationPermissionRequest */
655 0, // didCompleteRubberBandForMainFrame
656 0, // saveDataToFileInDownloadsFolder
657 0, // shouldInterruptJavaScript
660 WKPageSetPageUIClient(_webView.pageRef, &uiClient);
663 - (void)didStartProgress
665 [progressIndicator setDoubleValue:0.0];
666 [progressIndicator setHidden:NO];
669 - (void)didChangeProgress:(double)value
671 [progressIndicator setDoubleValue:value];
674 - (void)didFinishProgress
676 [progressIndicator setHidden:YES];
677 [progressIndicator setDoubleValue:1.0];
680 - (void)updateProvisionalURLForFrame:(WKFrameRef)frame
682 static WKURLRef emptyURL = 0;
684 emptyURL = WKURLCreateWithUTF8CString("");
686 WKURLRef url = WKFrameCopyProvisionalURL(frame);
691 if (WKURLIsEqual(url, emptyURL)) {
696 CFURLRef cfSourceURL = WKURLCopyCFURL(0, url);
699 [urlText setStringValue:(NSString*)CFURLGetString(cfSourceURL)];
700 CFRelease(cfSourceURL);
703 - (void)didStartProvisionalLoadForFrame:(WKFrameRef)frame
705 if (!WKFrameIsMainFrame(frame))
708 [self updateProvisionalURLForFrame:frame];
711 - (void)didReceiveServerRedirectForProvisionalLoadForFrame:(WKFrameRef)frame
713 if (!WKFrameIsMainFrame(frame))
716 [self updateProvisionalURLForFrame:frame];
719 - (void)didFailProvisionalLoadWithErrorForFrame:(WKFrameRef)frame
721 if (!WKFrameIsMainFrame(frame))
724 [self updateProvisionalURLForFrame:frame];
727 - (void)didFailLoadWithErrorForFrame:(WKFrameRef)frame
729 if (!WKFrameIsMainFrame(frame))
732 [self updateProvisionalURLForFrame:frame];
735 - (void)didSameDocumentNavigationForFrame:(WKFrameRef)frame
739 - (void)didCommitLoadForFrame:(WKFrameRef)frame
743 - (void)loadURLString:(NSString *)urlString
745 // FIXME: We shouldn't have to set the url text here.
746 [urlText setStringValue:urlString];
750 - (IBAction)performFindPanelAction:(id)sender
752 [findPanelWindow makeKeyAndOrderFront:sender];
755 - (IBAction)find:(id)sender
757 WKStringRef string = WKStringCreateWithCFString((CFStringRef)[sender stringValue]);
759 WKPageFindString(_webView.pageRef, string, kWKFindOptionsCaseInsensitive | kWKFindOptionsWrapAround | kWKFindOptionsShowFindIndicator | kWKFindOptionsShowOverlay, 100);