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;
43 @implementation BrowserWindowController
45 - (id)initWithPageNamespace:(WKPageNamespaceRef)pageNamespace
47 if ((self = [super initWithWindowNibName:@"BrowserWindow"])) {
48 _pageNamespace = WKRetain(pageNamespace);
57 assert(!_pageNamespace);
61 - (IBAction)fetch:(id)sender
63 CFURLRef cfURL = CFURLCreateWithString(0, (CFStringRef)[urlText stringValue], 0);
64 WKURLRef url = WKURLCreateWithCFURL(cfURL);
67 WKPageLoadURL(_webView.pageRef, url);
71 - (IBAction)showHideWebView:(id)sender
73 BOOL hidden = ![_webView isHidden];
75 [_webView setHidden:hidden];
78 - (IBAction)removeReinsertWebView:(id)sender
80 if ([_webView window]) {
82 [_webView removeFromSuperview];
84 [containerView addSubview:_webView];
89 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
91 SEL action = [menuItem action];
93 if (action == @selector(zoomIn:))
94 return [self canZoomIn];
95 if (action == @selector(zoomOut:))
96 return [self canZoomOut];
97 if (action == @selector(resetZoom:))
98 return [self canResetZoom];
100 if (action == @selector(showHideWebView:))
101 [menuItem setTitle:[_webView isHidden] ? @"Show Web View" : @"Hide Web View"];
102 else if (action == @selector(removeReinsertWebView:))
103 [menuItem setTitle:[_webView window] ? @"Remove Web View" : @"Insert Web View"];
104 else if (action == @selector(toggleZoomMode:))
105 [menuItem setState:_zoomTextOnly ? NSOnState : NSOffState];
109 - (IBAction)reload:(id)sender
111 WKPageReload(_webView.pageRef);
114 - (IBAction)forceRepaint:(id)sender
116 [_webView setNeedsDisplay:YES];
119 - (IBAction)goBack:(id)sender
121 WKPageGoBack(_webView.pageRef);
124 - (IBAction)goForward:(id)sender
126 WKPageGoForward(_webView.pageRef);
129 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
131 SEL action = [item action];
133 if (action == @selector(goBack:))
134 return _webView && WKPageCanGoBack(_webView.pageRef);
136 if (action == @selector(goForward:))
137 return _webView && WKPageCanGoForward(_webView.pageRef);
142 - (void)validateToolbar
144 [toolbar validateVisibleItems];
147 - (BOOL)windowShouldClose:(id)sender
149 LOG(@"windowShouldClose");
150 BOOL canCloseImmediately = WKPageTryClose(_webView.pageRef);
151 return canCloseImmediately;
154 - (void)windowWillClose:(NSNotification *)notification
156 WKRelease(_pageNamespace);
160 - (void)applicationTerminating
162 WKPageClose(_webView.pageRef);
163 WKRelease(_webView.pageRef);
166 #define DefaultMinimumZoomFactor (.5)
167 #define DefaultMaximumZoomFactor (3.0)
168 #define DefaultZoomFactorRatio (1.2)
170 - (double)currentZoomFactor
172 return _zoomTextOnly ? WKPageGetTextZoomFactor(_webView.pageRef) : WKPageGetPageZoomFactor(_webView.pageRef);
175 - (void)setCurrentZoomFactor:(double)factor
177 _zoomTextOnly ? WKPageSetTextZoomFactor(_webView.pageRef, factor) : WKPageSetPageZoomFactor(_webView.pageRef, factor);
182 return [self currentZoomFactor] * DefaultZoomFactorRatio < DefaultMaximumZoomFactor;
185 - (void)zoomIn:(id)sender;
187 if (![self canZoomIn])
190 double factor = [self currentZoomFactor] * DefaultZoomFactorRatio;
191 [self setCurrentZoomFactor:factor];
196 return [self currentZoomFactor] / DefaultZoomFactorRatio > DefaultMinimumZoomFactor;
199 - (void)zoomOut:(id)sender;
201 if (![self canZoomIn])
204 double factor = [self currentZoomFactor] / DefaultZoomFactorRatio;
205 [self setCurrentZoomFactor:factor];
210 return _zoomTextOnly ? (WKPageGetTextZoomFactor(_webView.pageRef) != 1) : (WKPageGetPageZoomFactor(_webView.pageRef) != 1);
213 - (void)resetZoom:(id)sender;
215 if (![self canResetZoom])
219 WKPageSetTextZoomFactor(_webView.pageRef, 1);
221 WKPageSetPageZoomFactor(_webView.pageRef, 1);
224 - (IBAction)toggleZoomMode:(id)sender
228 double currentTextZoom = WKPageGetTextZoomFactor(_webView.pageRef);
229 WKPageSetPageAndTextZoomFactors(_webView.pageRef, currentTextZoom, 1);
232 double currentPageZoom = WKPageGetPageZoomFactor(_webView.pageRef);
233 WKPageSetPageAndTextZoomFactors(_webView.pageRef, 1, currentPageZoom);
237 #pragma mark Loader Client Callbacks
239 static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
241 [(BrowserWindowController *)clientInfo didStartProvisionalLoadForFrame:frame];
244 static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
246 [(BrowserWindowController *)clientInfo didReceiveServerRedirectForProvisionalLoadForFrame:frame];
249 static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
251 [(BrowserWindowController *)clientInfo didFailProvisionalLoadWithErrorForFrame:frame];
254 static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
256 [(BrowserWindowController *)clientInfo didCommitLoadForFrame:frame];
259 static void didFinishDocumentLoadForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
261 LOG(@"didFinishDocumentLoadForFrame");
264 static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
266 LOG(@"didFinishLoadForFrame");
269 static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
271 [(BrowserWindowController *)clientInfo didFailLoadWithErrorForFrame:frame];
274 static void didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef frame, const void *clientInfo)
276 CFStringRef cfTitle = WKStringCopyCFString(0, title);
277 LOG(@"didReceiveTitleForFrame \"%@\"", (NSString *)cfTitle);
281 static void didFirstLayoutForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
283 LOG(@"didFirstLayoutForFrame");
286 static void didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef page, WKFrameRef frame, const void *clientInfo)
288 LOG(@"didFirstVisuallyNonEmptyLayoutForFrame");
291 static void didStartProgress(WKPageRef page, const void *clientInfo)
293 [(BrowserWindowController *)clientInfo didStartProgress];
296 static void didChangeProgress(WKPageRef page, const void *clientInfo)
298 [(BrowserWindowController *)clientInfo didChangeProgress:WKPageGetEstimatedProgress(page)];
301 static void didFinishProgress(WKPageRef page, const void *clientInfo)
303 [(BrowserWindowController *)clientInfo didFinishProgress];
306 static void didBecomeUnresponsive(WKPageRef page, const void *clientInfo)
308 LOG(@"didBecomeUnresponsive");
311 static void didBecomeResponsive(WKPageRef page, const void *clientInfo)
313 LOG(@"didBecomeResponsive");
316 static void processDidExit(WKPageRef page, const void *clientInfo)
318 LOG(@"processDidExit");
321 static void didChangeBackForwardList(WKPageRef page, const void *clientInfo)
323 [(BrowserWindowController *)clientInfo validateToolbar];
326 #pragma mark Policy Client Callbacks
328 static void decidePolicyForNavigationAction(WKPageRef page, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void *clientInfo)
330 LOG(@"decidePolicyForNavigationAction");
331 WKFramePolicyListenerUse(listener);
334 static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void *clientInfo)
336 LOG(@"decidePolicyForNewWindowAction");
337 WKFramePolicyListenerUse(listener);
340 static void decidePolicyForMIMEType(WKPageRef page, WKStringRef MIMEType, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void *clientInfo)
342 WKFramePolicyListenerUse(listener);
345 #pragma mark UI Client Callbacks
347 static WKPageRef createNewPage(WKPageRef page, const void* clientInfo)
349 LOG(@"createNewPage");
350 BrowserWindowController *controller = [[BrowserWindowController alloc] initWithPageNamespace:WKPageGetPageNamespace(page)];
351 [controller loadWindow];
353 return controller->_webView.pageRef;
356 static void showPage(WKPageRef page, const void *clientInfo)
359 [[(BrowserWindowController *)clientInfo window] orderFront:nil];
362 static void closePage(WKPageRef page, const void *clientInfo)
366 [[(BrowserWindowController *)clientInfo window] close];
370 static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
372 NSAlert* alert = [[NSAlert alloc] init];
374 WKURLRef wkURL = WKFrameCopyURL(frame);
375 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
378 [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [(NSURL *)cfURL absoluteString]]];
381 CFStringRef cfMessage = WKStringCopyCFString(0, message);
382 [alert setInformativeText:(NSString *)cfMessage];
383 CFRelease(cfMessage);
385 [alert addButtonWithTitle:@"OK"];
391 static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
393 NSAlert* alert = [[NSAlert alloc] init];
395 WKURLRef wkURL = WKFrameCopyURL(frame);
396 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
399 [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
402 CFStringRef cfMessage = WKStringCopyCFString(0, message);
403 [alert setInformativeText:(NSString *)cfMessage];
404 CFRelease(cfMessage);
406 [alert addButtonWithTitle:@"OK"];
407 [alert addButtonWithTitle:@"Cancel"];
409 NSInteger button = [alert runModal];
412 return button == NSAlertFirstButtonReturn;
415 static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, const void* clientInfo)
417 NSAlert* alert = [[NSAlert alloc] init];
419 WKURLRef wkURL = WKFrameCopyURL(frame);
420 CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
423 [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [(NSURL *)cfURL absoluteString]]];
426 CFStringRef cfMessage = WKStringCopyCFString(0, message);
427 [alert setInformativeText:(NSString *)cfMessage];
428 CFRelease(cfMessage);
430 [alert addButtonWithTitle:@"OK"];
431 [alert addButtonWithTitle:@"Cancel"];
433 NSTextField* input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
434 CFStringRef cfDefaultValue = WKStringCopyCFString(0, defaultValue);
435 [input setStringValue:(NSString *)cfDefaultValue];
436 CFRelease(cfDefaultValue);
438 [alert setAccessoryView:input];
440 NSInteger button = [alert runModal];
442 NSString* result = nil;
443 if (button == NSAlertFirstButtonReturn) {
444 [input validateEditing];
445 result = [input stringValue];
452 return WKStringCreateWithCFString((CFStringRef)result);
457 _webView = [[WKView alloc] initWithFrame:[containerView frame] pageNamespaceRef:_pageNamespace];
459 [containerView addSubview:_webView];
460 [_webView setFrame:[containerView frame]];
462 [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
464 WKPageLoaderClient loadClient = {
466 self, /* clientInfo */
467 didStartProvisionalLoadForFrame,
468 didReceiveServerRedirectForProvisionalLoadForFrame,
469 didFailProvisionalLoadWithErrorForFrame,
470 didCommitLoadForFrame,
471 didFinishDocumentLoadForFrame,
472 didFinishLoadForFrame,
473 didFailLoadWithErrorForFrame,
474 didReceiveTitleForFrame,
475 didFirstLayoutForFrame,
476 didFirstVisuallyNonEmptyLayoutForFrame,
480 didBecomeUnresponsive,
483 didChangeBackForwardList
485 WKPageSetPageLoaderClient(_webView.pageRef, &loadClient);
487 WKPagePolicyClient policyClient = {
489 self, /* clientInfo */
490 decidePolicyForNavigationAction,
491 decidePolicyForNewWindowAction,
492 decidePolicyForMIMEType
494 WKPageSetPagePolicyClient(_webView.pageRef, &policyClient);
496 WKPageUIClient uiClient = {
498 self, /* clientInfo */
503 runJavaScriptConfirm,
505 0 /* contentsSizeChanged */
507 WKPageSetPageUIClient(_webView.pageRef, &uiClient);
510 - (void)didStartProgress
512 [progressIndicator setDoubleValue:0.0];
513 [progressIndicator setHidden:NO];
516 - (void)didChangeProgress:(double)value
518 [progressIndicator setDoubleValue:value];
521 - (void)didFinishProgress
523 [progressIndicator setHidden:YES];
524 [progressIndicator setDoubleValue:1.0];
527 - (void)updateProvisionalURLForFrame:(WKFrameRef)frame
529 WKURLRef url = WKFrameCopyProvisionalURL(frame);
533 CFURLRef cfSourceURL = WKURLCopyCFURL(0, url);
536 [urlText setStringValue:(NSString*)CFURLGetString(cfSourceURL)];
537 CFRelease(cfSourceURL);
540 - (void)didStartProvisionalLoadForFrame:(WKFrameRef)frame
542 if (!WKFrameIsMainFrame(frame))
545 [self updateProvisionalURLForFrame:frame];
548 - (void)didReceiveServerRedirectForProvisionalLoadForFrame:(WKFrameRef)frame
550 if (!WKFrameIsMainFrame(frame))
553 [self updateProvisionalURLForFrame:frame];
556 - (void)didFailProvisionalLoadWithErrorForFrame:(WKFrameRef)frame
558 if (!WKFrameIsMainFrame(frame))
561 [self updateProvisionalURLForFrame:frame];
564 - (void)didFailLoadWithErrorForFrame:(WKFrameRef)frame
566 if (!WKFrameIsMainFrame(frame))
569 [self updateProvisionalURLForFrame:frame];
572 - (void)didCommitLoadForFrame:(WKFrameRef)frame
576 - (void)loadURLString:(NSString *)urlString
578 // FIXME: We shouldn't have to set the url text here.
579 [urlText setStringValue:urlString];