Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (C) 2010 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 "BrowserWindowController.h"
     27 
     28 #import <WebKit2/WKPagePrivate.h>
     29 #import <WebKit2/WKStringCF.h>
     30 #import <WebKit2/WKURLCF.h>
     31 
     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;
     42 @end
     43 
     44 @implementation BrowserWindowController
     45 
     46 - (id)initWithContext:(WKContextRef)context
     47 {
     48     if ((self = [super initWithWindowNibName:@"BrowserWindow"])) {
     49         _context = WKRetain(context);
     50         _zoomTextOnly = NO;
     51     }
     52 
     53     return self;
     54 }
     55 
     56 - (void)dealloc
     57 {
     58     assert(!_context);
     59     [super dealloc];
     60 }
     61 
     62 - (IBAction)fetch:(id)sender
     63 {
     64     CFURLRef cfURL = CFURLCreateWithString(0, (CFStringRef)[urlText stringValue], 0);
     65     if (!cfURL)
     66         return;
     67 
     68     WKURLRef url = WKURLCreateWithCFURL(cfURL);
     69     CFRelease(cfURL);
     70 
     71     WKPageLoadURL(_webView.pageRef, url);
     72     WKRelease(url);
     73 }
     74 
     75 - (IBAction)showHideWebView:(id)sender
     76 {
     77     BOOL hidden = ![_webView isHidden];
     78 
     79     [_webView setHidden:hidden];
     80 }
     81 
     82 - (IBAction)removeReinsertWebView:(id)sender
     83 {
     84     if ([_webView window]) {
     85         [_webView retain];
     86         [_webView removeFromSuperview];
     87     } else {
     88         [containerView addSubview:_webView];
     89         [_webView release];
     90     }
     91 }
     92 
     93 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
     94 {
     95     SEL action = [menuItem action];
     96 
     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];
    103 
    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];
    110     return YES;
    111 }
    112 
    113 - (IBAction)reload:(id)sender
    114 {
    115     WKPageReload(_webView.pageRef);
    116 }
    117 
    118 - (IBAction)forceRepaint:(id)sender
    119 {
    120     [_webView setNeedsDisplay:YES];
    121 }
    122 
    123 - (IBAction)goBack:(id)sender
    124 {
    125     WKPageGoBack(_webView.pageRef);
    126 }
    127 
    128 - (IBAction)goForward:(id)sender
    129 {
    130     WKPageGoForward(_webView.pageRef);
    131 }
    132 
    133 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
    134 {
    135     SEL action = [item action];
    136 
    137     if (action == @selector(goBack:))
    138         return _webView && WKPageCanGoBack(_webView.pageRef);
    139 
    140     if (action == @selector(goForward:))
    141         return _webView && WKPageCanGoForward(_webView.pageRef);
    142 
    143     return YES;
    144 }
    145 
    146 - (void)validateToolbar
    147 {
    148     [toolbar validateVisibleItems];
    149 }
    150 
    151 - (BOOL)windowShouldClose:(id)sender
    152 {
    153     LOG(@"windowShouldClose");
    154     BOOL canCloseImmediately = WKPageTryClose(_webView.pageRef);
    155     return canCloseImmediately;
    156 }
    157 
    158 - (void)windowWillClose:(NSNotification *)notification
    159 {
    160     WKRelease(_context);
    161     _context = 0;
    162 }
    163 
    164 - (void)applicationTerminating
    165 {
    166     WKPageClose(_webView.pageRef);
    167     WKRelease(_webView.pageRef);
    168 }
    169 
    170 #define DefaultMinimumZoomFactor (.5)
    171 #define DefaultMaximumZoomFactor (3.0)
    172 #define DefaultZoomFactorRatio (1.2)
    173 
    174 - (double)currentZoomFactor
    175 {
    176     return _zoomTextOnly ? WKPageGetTextZoomFactor(_webView.pageRef) : WKPageGetPageZoomFactor(_webView.pageRef);
    177 }
    178 
    179 - (void)setCurrentZoomFactor:(double)factor
    180 {
    181     _zoomTextOnly ? WKPageSetTextZoomFactor(_webView.pageRef, factor) : WKPageSetPageZoomFactor(_webView.pageRef, factor);
    182 }
    183 
    184 - (BOOL)canZoomIn
    185 {
    186     return [self currentZoomFactor] * DefaultZoomFactorRatio < DefaultMaximumZoomFactor;
    187 }
    188 
    189 - (void)zoomIn:(id)sender
    190 {
    191     if (![self canZoomIn])
    192         return;
    193 
    194     double factor = [self currentZoomFactor] * DefaultZoomFactorRatio;
    195     [self setCurrentZoomFactor:factor];
    196 }
    197 
    198 - (BOOL)canZoomOut
    199 {
    200     return [self currentZoomFactor] / DefaultZoomFactorRatio > DefaultMinimumZoomFactor;
    201 }
    202 
    203 - (void)zoomOut:(id)sender
    204 {
    205     if (![self canZoomIn])
    206         return;
    207 
    208     double factor = [self currentZoomFactor] / DefaultZoomFactorRatio;
    209     [self setCurrentZoomFactor:factor];
    210 }
    211 
    212 - (BOOL)canResetZoom
    213 {
    214     return _zoomTextOnly ? (WKPageGetTextZoomFactor(_webView.pageRef) != 1) : (WKPageGetPageZoomFactor(_webView.pageRef) != 1);
    215 }
    216 
    217 - (void)resetZoom:(id)sender
    218 {
    219     if (![self canResetZoom])
    220         return;
    221 
    222     if (_zoomTextOnly)
    223         WKPageSetTextZoomFactor(_webView.pageRef, 1);
    224     else
    225         WKPageSetPageZoomFactor(_webView.pageRef, 1);
    226 }
    227 
    228 - (IBAction)toggleZoomMode:(id)sender
    229 {
    230     if (_zoomTextOnly) {
    231         _zoomTextOnly = NO;
    232         double currentTextZoom = WKPageGetTextZoomFactor(_webView.pageRef);
    233         WKPageSetPageAndTextZoomFactors(_webView.pageRef, currentTextZoom, 1);
    234     } else {
    235         _zoomTextOnly = YES;
    236         double currentPageZoom = WKPageGetPageZoomFactor(_webView.pageRef);
    237         WKPageSetPageAndTextZoomFactors(_webView.pageRef, 1, currentPageZoom);
    238     }
    239 }
    240 
    241 - (IBAction)dumpSourceToConsole:(id)sender
    242 {
    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);
    246         CFRelease(cfResult);
    247     });
    248 }
    249 
    250 // MARK: Loader Client Callbacks
    251 
    252 static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    253 {
    254     [(BrowserWindowController *)clientInfo didStartProvisionalLoadForFrame:frame];
    255 }
    256 
    257 static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    258 {
    259     [(BrowserWindowController *)clientInfo didReceiveServerRedirectForProvisionalLoadForFrame:frame];
    260 }
    261 
    262 static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo)
    263 {
    264     [(BrowserWindowController *)clientInfo didFailProvisionalLoadWithErrorForFrame:frame];
    265 }
    266 
    267 static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    268 {
    269     [(BrowserWindowController *)clientInfo didCommitLoadForFrame:frame];
    270 }
    271 
    272 static void didFinishDocumentLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    273 {
    274     LOG(@"didFinishDocumentLoadForFrame");
    275 }
    276 
    277 static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    278 {
    279     LOG(@"didFinishLoadForFrame");
    280 }
    281 
    282 static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo)
    283 {
    284     [(BrowserWindowController *)clientInfo didFailLoadWithErrorForFrame:frame];
    285 }
    286 
    287 static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
    288 {
    289     [(BrowserWindowController *)clientInfo didSameDocumentNavigationForFrame:frame];
    290 }
    291 
    292 static void didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    293 {
    294     CFStringRef cfTitle = WKStringCopyCFString(0, title);
    295     LOG(@"didReceiveTitleForFrame \"%@\"", (NSString *)cfTitle);
    296     CFRelease(cfTitle);
    297 }
    298 
    299 static void didFirstLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    300 {
    301     LOG(@"didFirstLayoutForFrame");
    302 }
    303 
    304 static void didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    305 {
    306     LOG(@"didFirstVisuallyNonEmptyLayoutForFrame");
    307 }
    308 
    309 static void didRemoveFrameFromHierarchy(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    310 {
    311     LOG(@"didRemoveFrameFromHierarchy");
    312 }
    313 
    314 static void didDisplayInsecureContentForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    315 {
    316     LOG(@"didDisplayInsecureContentForFrame");
    317 }
    318 
    319 static void didRunInsecureContentForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
    320 {
    321     LOG(@"didRunInsecureContentForFrame");
    322 }
    323 
    324 static void didStartProgress(WKPageRef page, const void *clientInfo)
    325 {
    326     [(BrowserWindowController *)clientInfo didStartProgress];
    327 }
    328 
    329 static void didChangeProgress(WKPageRef page, const void *clientInfo)
    330 {
    331     [(BrowserWindowController *)clientInfo didChangeProgress:WKPageGetEstimatedProgress(page)];
    332 }
    333 
    334 static void didFinishProgress(WKPageRef page, const void *clientInfo)
    335 {
    336     [(BrowserWindowController *)clientInfo didFinishProgress];
    337 }
    338 
    339 static void didBecomeUnresponsive(WKPageRef page, const void *clientInfo)
    340 {
    341     LOG(@"didBecomeUnresponsive");
    342 }
    343 
    344 static void didBecomeResponsive(WKPageRef page, const void *clientInfo)
    345 {
    346     LOG(@"didBecomeResponsive");
    347 }
    348 
    349 static void processDidExit(WKPageRef page, const void *clientInfo)
    350 {
    351     LOG(@"processDidExit");
    352 }
    353 
    354 static void didChangeBackForwardList(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void *clientInfo)
    355 {
    356     [(BrowserWindowController *)clientInfo validateToolbar];
    357 }
    358 
    359 // MARK: Policy Client Callbacks
    360 
    361 static void decidePolicyForNavigationAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
    362 {
    363     LOG(@"decidePolicyForNavigationAction");
    364     WKFramePolicyListenerUse(listener);
    365 }
    366 
    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)
    368 {
    369     LOG(@"decidePolicyForNewWindowAction");
    370     WKFramePolicyListenerUse(listener);
    371 }
    372 
    373 static void decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
    374 {
    375     WKFramePolicyListenerUse(listener);
    376 }
    377 
    378 // MARK: UI Client Callbacks
    379 
    380 static WKPageRef createNewPage(WKPageRef page, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton button, const void* clientInfo)
    381 {
    382     LOG(@"createNewPage");
    383     BrowserWindowController *controller = [[BrowserWindowController alloc] initWithContext:WKPageGetContext(page)];
    384     [controller loadWindow];
    385 
    386     return controller->_webView.pageRef;
    387 }
    388 
    389 static void showPage(WKPageRef page, const void *clientInfo)
    390 {
    391     LOG(@"showPage");
    392     [[(BrowserWindowController *)clientInfo window] orderFront:nil];
    393 }
    394 
    395 static void closePage(WKPageRef page, const void *clientInfo)
    396 {
    397     LOG(@"closePage");
    398     WKPageClose(page);
    399     [[(BrowserWindowController *)clientInfo window] close];
    400     WKRelease(page);
    401 }
    402 
    403 static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
    404 {
    405     NSAlert* alert = [[NSAlert alloc] init];
    406 
    407     WKURLRef wkURL = WKFrameCopyURL(frame);
    408     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
    409     WKRelease(wkURL);
    410 
    411     [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [(NSURL *)cfURL absoluteString]]];
    412     CFRelease(cfURL);
    413 
    414     CFStringRef cfMessage = WKStringCopyCFString(0, message);
    415     [alert setInformativeText:(NSString *)cfMessage];
    416     CFRelease(cfMessage);
    417 
    418     [alert addButtonWithTitle:@"OK"];
    419 
    420     [alert runModal];
    421     [alert release];
    422 }
    423 
    424 static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
    425 {
    426     NSAlert* alert = [[NSAlert alloc] init];
    427 
    428     WKURLRef wkURL = WKFrameCopyURL(frame);
    429     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
    430     WKRelease(wkURL);
    431 
    432     [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
    433     CFRelease(cfURL);
    434 
    435     CFStringRef cfMessage = WKStringCopyCFString(0, message);
    436     [alert setInformativeText:(NSString *)cfMessage];
    437     CFRelease(cfMessage);
    438 
    439     [alert addButtonWithTitle:@"OK"];
    440     [alert addButtonWithTitle:@"Cancel"];
    441 
    442     NSInteger button = [alert runModal];
    443     [alert release];
    444 
    445     return button == NSAlertFirstButtonReturn;
    446 }
    447 
    448 static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, const void* clientInfo)
    449 {
    450     NSAlert* alert = [[NSAlert alloc] init];
    451 
    452     WKURLRef wkURL = WKFrameCopyURL(frame);
    453     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
    454     WKRelease(wkURL);
    455 
    456     [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [(NSURL *)cfURL absoluteString]]];
    457     CFRelease(cfURL);
    458 
    459     CFStringRef cfMessage = WKStringCopyCFString(0, message);
    460     [alert setInformativeText:(NSString *)cfMessage];
    461     CFRelease(cfMessage);
    462 
    463     [alert addButtonWithTitle:@"OK"];
    464     [alert addButtonWithTitle:@"Cancel"];
    465 
    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);
    470 
    471     [alert setAccessoryView:input];
    472 
    473     NSInteger button = [alert runModal];
    474 
    475     NSString* result = nil;
    476     if (button == NSAlertFirstButtonReturn) {
    477         [input validateEditing];
    478         result = [input stringValue];
    479     }
    480 
    481     [alert release];
    482 
    483     if (!result)
    484         return 0;
    485     return WKStringCreateWithCFString((CFStringRef)result);
    486 }
    487 
    488 static void setStatusText(WKPageRef page, WKStringRef text, const void* clientInfo)
    489 {
    490     LOG(@"setStatusText");
    491 }
    492 
    493 static void mouseDidMoveOverElement(WKPageRef page, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo)
    494 {
    495     LOG(@"mouseDidMoveOverElement");
    496 }
    497 
    498 static WKRect getWindowFrame(WKPageRef page, const void* clientInfo)
    499 {
    500     NSRect rect = [[(BrowserWindowController *)clientInfo window] frame];
    501     WKRect wkRect;
    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;
    506     return wkRect;
    507 }
    508 
    509 static void setWindowFrame(WKPageRef page, WKRect rect, const void* clientInfo)
    510 {
    511     [[(BrowserWindowController *)clientInfo window] setFrame:NSMakeRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height) display:YES];
    512 }
    513 
    514 static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
    515 {
    516     NSAlert *alert = [[NSAlert alloc] init];
    517 
    518     WKURLRef wkURL = WKFrameCopyURL(frame);
    519     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
    520     WKRelease(wkURL);
    521 
    522     [alert setMessageText:[NSString stringWithFormat:@"BeforeUnload confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
    523     CFRelease(cfURL);
    524 
    525     CFStringRef cfMessage = WKStringCopyCFString(0, message);
    526     [alert setInformativeText:(NSString *)cfMessage];
    527     CFRelease(cfMessage);
    528 
    529     [alert addButtonWithTitle:@"OK"];
    530     [alert addButtonWithTitle:@"Cancel"];
    531 
    532     NSInteger button = [alert runModal];
    533     [alert release];
    534 
    535     return button == NSAlertFirstButtonReturn;
    536 }
    537 
    538 static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void* clientInfo)
    539 {
    540     NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    541     [openPanel setAllowsMultipleSelection:WKOpenPanelParametersGetAllowsMultipleFiles(parameters)];
    542 
    543     WKRetain(listener);
    544 
    545     [openPanel beginSheetModalForWindow:[(BrowserWindowController *)clientInfo window] completionHandler:^(NSInteger result) {
    546         if (result == NSFileHandlingPanelOKButton) {
    547             WKMutableArrayRef fileURLs = WKMutableArrayCreate();
    548 
    549             NSURL *nsURL;
    550             for (nsURL in [openPanel URLs]) {
    551                 WKURLRef wkURL = WKURLCreateWithCFURL((CFURLRef)nsURL);
    552                 WKArrayAppendItem(fileURLs, wkURL);
    553                 WKRelease(wkURL);
    554             }
    555 
    556             WKOpenPanelResultListenerChooseFiles(listener, fileURLs);
    557 
    558             WKRelease(fileURLs);
    559         } else
    560             WKOpenPanelResultListenerCancel(listener);
    561 
    562         WKRelease(listener);
    563     }];
    564 }
    565 
    566 - (void)awakeFromNib
    567 {
    568     _webView = [[WKView alloc] initWithFrame:[containerView frame] contextRef:_context];
    569 
    570     [containerView addSubview:_webView];
    571     [_webView setFrame:[containerView frame]];
    572 
    573     [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
    574 
    575     WKPageLoaderClient loadClient = {
    576         0,      /* version */
    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
    594         didStartProgress,
    595         didChangeProgress,
    596         didFinishProgress,
    597         didBecomeUnresponsive,
    598         didBecomeResponsive,
    599         processDidExit,
    600         didChangeBackForwardList,
    601         0 // shouldGoToBackForwardItem
    602     };
    603     WKPageSetPageLoaderClient(_webView.pageRef, &loadClient);
    604 
    605     WKPagePolicyClient policyClient = {
    606         0,          /* version */
    607         self,       /* clientInfo */
    608         decidePolicyForNavigationAction,
    609         decidePolicyForNewWindowAction,
    610         decidePolicyForResponse,
    611         0           /* unableToImplementPolicy */
    612     };
    613     WKPageSetPagePolicyClient(_webView.pageRef, &policyClient);
    614 
    615     WKPageUIClient uiClient = {
    616         0,          /* version */
    617         self,       /* clientInfo */
    618         createNewPage,
    619         showPage,
    620         closePage,
    621         0,          /* takeFocus */
    622         0,          /* focus */
    623         0,          /* unfocus */
    624         runJavaScriptAlert,
    625         runJavaScriptConfirm,
    626         runJavaScriptPrompt,
    627         setStatusText,
    628         mouseDidMoveOverElement,
    629         0,          /* missingPluginButtonClicked */
    630         0,          /* didNotHandleKeyEvent */
    631         0,          /* toolbarsAreVisible */
    632         0,          /* setToolbarsAreVisible */
    633         0,          /* menuBarIsVisible */
    634         0,          /* setMenuBarIsVisible */
    635         0,          /* statusBarIsVisible */
    636         0,          /* setStatusBarIsVisible */
    637         0,          /* isResizable */
    638         0,          /* setIsResizable */
    639         getWindowFrame,
    640         setWindowFrame,
    641         runBeforeUnloadConfirmPanel,
    642         0,          /* didDraw */
    643         0,          /* pageDidScroll */
    644         0,          /* exceededDatabaseQuota */
    645         runOpenPanel,
    646         0,          /* decidePolicyForGeolocationPermissionRequest */
    647         0, // headerHeight
    648         0, // footerHeight
    649         0, // drawHeader
    650         0, // drawFooter
    651         0, // printFrame
    652         0, // showModal
    653         0, // didCompleteRubberBandForMainFrame
    654         0, // saveDataToFileInDownloadsFolder
    655     };
    656     WKPageSetPageUIClient(_webView.pageRef, &uiClient);
    657 }
    658 
    659 - (void)didStartProgress
    660 {
    661     [progressIndicator setDoubleValue:0.0];
    662     [progressIndicator setHidden:NO];
    663 }
    664 
    665 - (void)didChangeProgress:(double)value
    666 {
    667     [progressIndicator setDoubleValue:value];
    668 }
    669 
    670 - (void)didFinishProgress
    671 {
    672     [progressIndicator setHidden:YES];
    673     [progressIndicator setDoubleValue:1.0];
    674 }
    675 
    676 - (void)updateProvisionalURLForFrame:(WKFrameRef)frame
    677 {
    678     static WKURLRef emptyURL = 0;
    679     if (!emptyURL)
    680         emptyURL = WKURLCreateWithUTF8CString("");
    681 
    682     WKURLRef url = WKFrameCopyProvisionalURL(frame);
    683     if (WKURLIsEqual(url, emptyURL)) {
    684         WKRelease(url);
    685         return;
    686     }
    687 
    688     CFURLRef cfSourceURL = WKURLCopyCFURL(0, url);
    689     WKRelease(url);
    690 
    691     [urlText setStringValue:(NSString*)CFURLGetString(cfSourceURL)];
    692     CFRelease(cfSourceURL);
    693 }
    694 
    695 - (void)didStartProvisionalLoadForFrame:(WKFrameRef)frame
    696 {
    697     if (!WKFrameIsMainFrame(frame))
    698         return;
    699 
    700     [self updateProvisionalURLForFrame:frame];
    701 }
    702 
    703 - (void)didReceiveServerRedirectForProvisionalLoadForFrame:(WKFrameRef)frame
    704 {
    705     if (!WKFrameIsMainFrame(frame))
    706         return;
    707 
    708     [self updateProvisionalURLForFrame:frame];
    709 }
    710 
    711 - (void)didFailProvisionalLoadWithErrorForFrame:(WKFrameRef)frame
    712 {
    713     if (!WKFrameIsMainFrame(frame))
    714         return;
    715 
    716     [self updateProvisionalURLForFrame:frame];
    717 }
    718 
    719 - (void)didFailLoadWithErrorForFrame:(WKFrameRef)frame
    720 {
    721     if (!WKFrameIsMainFrame(frame))
    722         return;
    723 
    724     [self updateProvisionalURLForFrame:frame];
    725 }
    726 
    727 - (void)didSameDocumentNavigationForFrame:(WKFrameRef)frame
    728 {
    729 }
    730 
    731 - (void)didCommitLoadForFrame:(WKFrameRef)frame
    732 {
    733 }
    734 
    735 - (void)loadURLString:(NSString *)urlString
    736 {
    737     // FIXME: We shouldn't have to set the url text here.
    738     [urlText setStringValue:urlString];
    739     [self fetch:nil];
    740 }
    741 
    742 - (IBAction)performFindPanelAction:(id)sender
    743 {
    744     [findPanelWindow makeKeyAndOrderFront:sender];
    745 }
    746 
    747 - (IBAction)find:(id)sender
    748 {
    749     WKStringRef string = WKStringCreateWithCFString((CFStringRef)[sender stringValue]);
    750 
    751     WKPageFindString(_webView.pageRef, string, kWKFindOptionsCaseInsensitive | kWKFindOptionsWrapAround | kWKFindOptionsShowFindIndicator | kWKFindOptionsShowOverlay, 100);
    752 }
    753 
    754 @end
    755