From 231d4e3152a9c27a73b6ac7badbe6be673aa3ddf Mon Sep 17 00:00:00 2001 From: Steve Block Date: Thu, 8 Oct 2009 17:19:54 +0100 Subject: Merge webkit.org at R49305 : Automatic merge by git. Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7 --- .../mac/WebView/WebDelegateImplementationCaching.h | 13 + .../WebView/WebDelegateImplementationCaching.mm | 18 + WebKit/mac/WebView/WebDynamicScrollBarsView.h | 2 + WebKit/mac/WebView/WebDynamicScrollBarsView.mm | 66 ++- WebKit/mac/WebView/WebFrame.mm | 9 +- WebKit/mac/WebView/WebFrameLoadDelegatePrivate.h | 39 ++ WebKit/mac/WebView/WebFramePrivate.h | 2 + WebKit/mac/WebView/WebFrameView.mm | 2 - WebKit/mac/WebView/WebHTMLView.mm | 87 +-- WebKit/mac/WebView/WebHTMLViewInternal.h | 3 + WebKit/mac/WebView/WebHistoryDelegate.h | 42 ++ WebKit/mac/WebView/WebJSPDFDoc.h | 30 ++ WebKit/mac/WebView/WebJSPDFDoc.mm | 76 +++ WebKit/mac/WebView/WebNavigationData.h | 46 ++ WebKit/mac/WebView/WebNavigationData.mm | 108 ++++ WebKit/mac/WebView/WebPDFDocumentExtras.h | 32 ++ WebKit/mac/WebView/WebPDFDocumentExtras.mm | 141 +++++ WebKit/mac/WebView/WebPDFRepresentation.h | 2 +- WebKit/mac/WebView/WebPDFRepresentation.m | 145 ----- WebKit/mac/WebView/WebPDFRepresentation.mm | 176 +++++++ WebKit/mac/WebView/WebPolicyDelegatePrivate.h | 2 + WebKit/mac/WebView/WebPreferenceKeysPrivate.h | 5 + WebKit/mac/WebView/WebPreferences.mm | 61 +++ WebKit/mac/WebView/WebPreferencesPrivate.h | 19 + WebKit/mac/WebView/WebScriptDebugger.mm | 7 +- WebKit/mac/WebView/WebTextCompletionController.mm | 7 +- WebKit/mac/WebView/WebUIDelegatePrivate.h | 6 +- WebKit/mac/WebView/WebVideoFullscreenController.h | 64 +++ WebKit/mac/WebView/WebVideoFullscreenController.mm | 444 ++++++++++++++++ .../WebVideoFullscreenHUDWindowController.h | 61 +++ .../WebVideoFullscreenHUDWindowController.mm | 583 +++++++++++++++++++++ WebKit/mac/WebView/WebView.mm | 203 ++++++- WebKit/mac/WebView/WebViewData.h | 9 + WebKit/mac/WebView/WebViewData.mm | 3 + WebKit/mac/WebView/WebViewInternal.h | 11 +- WebKit/mac/WebView/WebViewPrivate.h | 48 ++ WebKit/mac/WebView/WebWindowAnimation.h | 59 +++ WebKit/mac/WebView/WebWindowAnimation.m | 239 +++++++++ 38 files changed, 2646 insertions(+), 224 deletions(-) create mode 100644 WebKit/mac/WebView/WebFrameLoadDelegatePrivate.h create mode 100644 WebKit/mac/WebView/WebHistoryDelegate.h create mode 100644 WebKit/mac/WebView/WebJSPDFDoc.h create mode 100644 WebKit/mac/WebView/WebJSPDFDoc.mm create mode 100644 WebKit/mac/WebView/WebNavigationData.h create mode 100644 WebKit/mac/WebView/WebNavigationData.mm create mode 100644 WebKit/mac/WebView/WebPDFDocumentExtras.h create mode 100644 WebKit/mac/WebView/WebPDFDocumentExtras.mm delete mode 100644 WebKit/mac/WebView/WebPDFRepresentation.m create mode 100644 WebKit/mac/WebView/WebPDFRepresentation.mm create mode 100644 WebKit/mac/WebView/WebVideoFullscreenController.h create mode 100644 WebKit/mac/WebView/WebVideoFullscreenController.mm create mode 100644 WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h create mode 100644 WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm create mode 100644 WebKit/mac/WebView/WebWindowAnimation.h create mode 100644 WebKit/mac/WebView/WebWindowAnimation.m (limited to 'WebKit/mac/WebView') diff --git a/WebKit/mac/WebView/WebDelegateImplementationCaching.h b/WebKit/mac/WebView/WebDelegateImplementationCaching.h index 41e44e0..907ba42 100644 --- a/WebKit/mac/WebView/WebDelegateImplementationCaching.h +++ b/WebKit/mac/WebView/WebDelegateImplementationCaching.h @@ -67,6 +67,8 @@ struct WebFrameLoadDelegateImplementationCache { IMP didFirstVisuallyNonEmptyLayoutInFrameFunc; IMP didReceiveIconForFrameFunc; IMP didFinishDocumentLoadForFrameFunc; + IMP didDisplayInsecureContentFunc; + IMP didRunInsecureContentFunc; }; struct WebScriptDebugDelegateImplementationCache { @@ -79,9 +81,17 @@ struct WebScriptDebugDelegateImplementationCache { IMP exceptionWasRaisedFunc; }; +struct WebHistoryDelegateImplementationCache { + IMP navigatedFunc; + IMP clientRedirectFunc; + IMP serverRedirectFunc; + IMP setTitleFunc; +}; + WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *); WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *); WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *); +WebHistoryDelegateImplementationCache* WebViewGetHistoryDelegateImplementations(WebView *webView); id CallFormDelegate(WebView *, SEL, id, id); id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5); @@ -119,3 +129,6 @@ id CallScriptDebugDelegate(IMP, WebView *, SEL, id, id, NSInteger, id); id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, NSInteger, id); id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, id, id, id); id CallScriptDebugDelegate(IMP, WebView *, SEL, id, NSInteger, NSInteger, id); + +id CallHistoryDelegate(IMP, WebView *, SEL, id, id); +id CallHistoryDelegate(IMP, WebView *, SEL, id, id, id); diff --git a/WebKit/mac/WebView/WebDelegateImplementationCaching.mm b/WebKit/mac/WebView/WebDelegateImplementationCaching.mm index 441df92..7757fc7 100644 --- a/WebKit/mac/WebView/WebDelegateImplementationCaching.mm +++ b/WebKit/mac/WebView/WebDelegateImplementationCaching.mm @@ -60,6 +60,14 @@ WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplemen return &webView->_private->scriptDebugDelegateImplementations; } +WebHistoryDelegateImplementationCache* WebViewGetHistoryDelegateImplementations(WebView *webView) +{ + static WebHistoryDelegateImplementationCache empty; + if (!webView) + return ∅ + return &webView->_private->historyDelegateImplementations; +} + // We use these functions to call the delegates and block exceptions. These functions are // declared inside a WebView category to get direct access to the delegate data memebers, // preventing more ObjC message dispatch and compensating for the expense of the @try/@catch. @@ -540,6 +548,16 @@ id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id o return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, integer2, object2); } +id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2) +{ + return CallDelegate(implementation, self, self->_private->historyDelegate, selector, object1, object2); +} + +id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3) +{ + return CallDelegate(implementation, self, self->_private->historyDelegate, selector, object1, object2, object3); +} + // The form delegate needs to have it's own implementation, because the first argument is never the WebView id CallFormDelegate(WebView *self, SEL selector, id object1, id object2) diff --git a/WebKit/mac/WebView/WebDynamicScrollBarsView.h b/WebKit/mac/WebView/WebDynamicScrollBarsView.h index ce92b33..40aadc0 100644 --- a/WebKit/mac/WebView/WebDynamicScrollBarsView.h +++ b/WebKit/mac/WebView/WebDynamicScrollBarsView.h @@ -43,6 +43,8 @@ extern const int WebCoreScrollbarAlwaysOn; BOOL suppressLayout; BOOL suppressScrollers; BOOL inUpdateScrollers; + BOOL verticallyPinnedByPreviousWheelEvent; + BOOL horizontallyPinnedByPreviousWheelEvent; unsigned inUpdateScrollersLayoutPass; } - (void)setAllowsHorizontalScrolling:(BOOL)flag; // This method is used by Safari, so it cannot be removed. diff --git a/WebKit/mac/WebView/WebDynamicScrollBarsView.mm b/WebKit/mac/WebView/WebDynamicScrollBarsView.mm index 0cf2a98..3c28e3c 100644 --- a/WebKit/mac/WebView/WebDynamicScrollBarsView.mm +++ b/WebKit/mac/WebView/WebDynamicScrollBarsView.mm @@ -89,15 +89,26 @@ static const unsigned cMaxUpdateScrollbarsPass = 2; - (void)updateScrollers { - BOOL hasVerticalScroller = [self hasVerticalScroller]; + NSView *documentView = [self documentView]; + + // If we came in here with the view already needing a layout, then go ahead and do that + // first. (This will be the common case, e.g., when the page changes due to window resizing for example). + // This layout will not re-enter updateScrollers and does not count towards our max layout pass total. + if (!suppressLayout && !suppressScrollers && [documentView isKindOfClass:[WebHTMLView class]]) { + WebHTMLView* htmlView = (WebHTMLView*)documentView; + if ([htmlView _needsLayout]) { + inUpdateScrollers = YES; + [(id )documentView layout]; + inUpdateScrollers = NO; + } + } + BOOL hasHorizontalScroller = [self hasHorizontalScroller]; + BOOL hasVerticalScroller = [self hasVerticalScroller]; BOOL newHasHorizontalScroller = hasHorizontalScroller; BOOL newHasVerticalScroller = hasVerticalScroller; - BOOL needsLayout = NO; - - NSView *documentView = [self documentView]; if (!documentView) { newHasHorizontalScroller = NO; newHasVerticalScroller = NO; @@ -122,19 +133,7 @@ static const unsigned cMaxUpdateScrollbarsPass = 2; return; } - needsLayout = NO; - - // If we came in here with the view already needing a layout, then go ahead and do that - // first. (This will be the common case, e.g., when the page changes due to window resizing for example). - // This layout will not re-enter updateScrollers and does not count towards our max layout pass total. - if ([documentView isKindOfClass:[WebHTMLView class]]) { - WebHTMLView* htmlView = (WebHTMLView*)documentView; - if ([htmlView _needsLayout]) { - inUpdateScrollers = YES; - [(id )documentView layout]; - inUpdateScrollers = NO; - } - } + BOOL needsLayout = NO; NSSize documentSize = [documentView frame].size; NSSize visibleSize = [self documentVisibleRect].size; @@ -199,7 +198,8 @@ static const unsigned cMaxUpdateScrollbarsPass = 2; // http://www.linuxpowered.com/archive/howto/Net-HOWTO-8.html. // The underlying cause is some problem in the NSText machinery, but I was not // able to pin it down. - if (!inUpdateScrollers && [[NSGraphicsContext currentContext] isDrawingToScreen]) + NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; + if (!inUpdateScrollers && (!currentContext || [currentContext isDrawingToScreen])) [self updateScrollers]; } @@ -328,17 +328,41 @@ static const unsigned cMaxUpdateScrollbarsPass = 2; BOOL isContinuous; WKGetWheelEventDeltas(event, &deltaX, &deltaY, &isContinuous); + BOOL isLatchingEvent = WKIsLatchingWheelEvent(event); + if (fabsf(deltaY) > fabsf(deltaX)) { if (![self allowsVerticalScrolling]) { [[self nextResponder] scrollWheel:event]; return; } - } else if (![self allowsHorizontalScrolling]) { - [[self nextResponder] scrollWheel:event]; - return; + + if (isLatchingEvent && !verticallyPinnedByPreviousWheelEvent) { + double verticalPosition = [[self verticalScroller] doubleValue]; + if ((deltaY >= 0.0 && verticalPosition == 0.0) || (deltaY <= 0.0 && verticalPosition == 1.0)) + return; + } + } else { + if (![self allowsHorizontalScrolling]) { + [[self nextResponder] scrollWheel:event]; + return; + } + + if (isLatchingEvent && !horizontallyPinnedByPreviousWheelEvent) { + double horizontalPosition = [[self horizontalScroller] doubleValue]; + if ((deltaX >= 0.0 && horizontalPosition == 0.0) || (deltaX <= 0.0 && horizontalPosition == 1.0)) + return; + } } [super scrollWheel:event]; + + if (!isLatchingEvent) { + double verticalPosition = [[self verticalScroller] doubleValue]; + double horizontalPosition = [[self horizontalScroller] doubleValue]; + + verticallyPinnedByPreviousWheelEvent = (verticalPosition == 0.0 || verticalPosition == 1.0); + horizontallyPinnedByPreviousWheelEvent = (horizontalPosition == 0.0 || horizontalPosition == 1.0); + } } - (BOOL)accessibilityIsIgnored diff --git a/WebKit/mac/WebView/WebFrame.mm b/WebKit/mac/WebView/WebFrame.mm index c03ef58..27aac67 100644 --- a/WebKit/mac/WebView/WebFrame.mm +++ b/WebKit/mac/WebView/WebFrame.mm @@ -1174,7 +1174,7 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins]; if (DOMWindow* domWindow = _private->coreFrame->domWindow()) { - if (domWindow->hasEventListener(eventNames().unloadEvent)) + if (domWindow->hasEventListeners(eventNames().unloadEvent)) [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener]; if (domWindow->optionalApplicationCache()) @@ -1195,6 +1195,13 @@ static inline WebDataSource *dataSource(DocumentLoader* loader) return result; } +- (BOOL)_allowsFollowingLink:(NSURL *)URL +{ + if (!_private->coreFrame) + return YES; + return SecurityOrigin::canLoad(URL, String(), _private->coreFrame->document()); +} + @end @implementation WebFrame diff --git a/WebKit/mac/WebView/WebFrameLoadDelegatePrivate.h b/WebKit/mac/WebView/WebFrameLoadDelegatePrivate.h new file mode 100644 index 0000000..80fa08a --- /dev/null +++ b/WebKit/mac/WebView/WebFrameLoadDelegatePrivate.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009 Adam Barth. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@class WebSecurityOrigin; + +@interface NSObject (WebFrameLoadDelegatePrivate) + +- (void)webViewDidDisplayInsecureContent:(WebView *)webView; + +- (void)webView:(WebView *)webView didRunInsecureContent:(WebSecurityOrigin *)origin; + +@end diff --git a/WebKit/mac/WebView/WebFramePrivate.h b/WebKit/mac/WebView/WebFramePrivate.h index 8e7a2ef..7446584 100644 --- a/WebKit/mac/WebView/WebFramePrivate.h +++ b/WebKit/mac/WebView/WebFramePrivate.h @@ -110,4 +110,6 @@ typedef enum { - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace; - (NSMutableDictionary *)_cacheabilityDictionary; + +- (BOOL)_allowsFollowingLink:(NSURL *)URL; @end diff --git a/WebKit/mac/WebView/WebFrameView.mm b/WebKit/mac/WebView/WebFrameView.mm index 1a460ea..c300586 100644 --- a/WebKit/mac/WebView/WebFrameView.mm +++ b/WebKit/mac/WebView/WebFrameView.mm @@ -273,8 +273,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class objCCl owner->setWidget(view); // Now the render part owns the view, so we don't any more. } - - view->initScrollbars(); } @end diff --git a/WebKit/mac/WebView/WebHTMLView.mm b/WebKit/mac/WebView/WebHTMLView.mm index d58c765..102f630 100644 --- a/WebKit/mac/WebView/WebHTMLView.mm +++ b/WebKit/mac/WebView/WebHTMLView.mm @@ -125,6 +125,7 @@ using namespace WebCore; using namespace HTMLNames; using namespace WTF; +using namespace std; @interface NSWindow (BorderViewAccess) - (NSView*)_web_borderView; @@ -212,6 +213,9 @@ extern NSString *NSTextInputReplacementRangeAttributeName; - (void)_setDrawsOwnDescendants:(BOOL)drawsOwnDescendants; - (void)_propagateDirtyRectsToOpaqueAncestors; - (void)_windowChangedKeyState; +#if USE(ACCELERATED_COMPOSITING) && defined(BUILDING_ON_LEOPARD) +- (void)_updateLayerGeometryFromView; +#endif @end @interface NSApplication (WebNSApplicationDetails) @@ -979,8 +983,7 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart) { // FIXME: this can fail if the dataSource is nil, which happens when the WebView is tearing down from the window closing. WebHTMLView *view = (WebHTMLView *)[[[[_private->dataSource _webView] mainFrame] frameView] documentView]; - ASSERT(view); - ASSERT([view isKindOfClass:[WebHTMLView class]]); + ASSERT(!view || [view isKindOfClass:[WebHTMLView class]]); return view; } @@ -1148,8 +1151,11 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) { NSPoint origin = [[self superview] bounds].origin; if (!NSEqualPoints(_private->lastScrollPosition, origin)) { - if (Frame* coreFrame = core([self _frame])) - coreFrame->eventHandler()->sendScrollEvent(); + if (Frame* coreFrame = core([self _frame])) { + if (FrameView* coreView = coreFrame->view()) + coreView->scrollPositionChanged(); + } + [_private->completionController endRevertingChange:NO moveLeft:NO]; WebView *webView = [self _webView]; @@ -1649,10 +1655,10 @@ static void _updateMouseoverTimerCallback(CFRunLoopTimerRef timer, void *info) urlStringSize.height = [urlFont ascender] - [urlFont descender]; imageSize.height += urlStringSize.height; if (urlStringSize.width > MAX_DRAG_LABEL_WIDTH) { - imageSize.width = MAX(MAX_DRAG_LABEL_WIDTH + DRAG_LABEL_BORDER_X * 2.0f, MIN_DRAG_LABEL_WIDTH_BEFORE_CLIP); + imageSize.width = max(MAX_DRAG_LABEL_WIDTH + DRAG_LABEL_BORDER_X * 2, MIN_DRAG_LABEL_WIDTH_BEFORE_CLIP); clipURLString = YES; } else { - imageSize.width = MAX(labelSize.width + DRAG_LABEL_BORDER_X * 2.0f, urlStringSize.width + DRAG_LABEL_BORDER_X * 2.0f); + imageSize.width = max(labelSize.width + DRAG_LABEL_BORDER_X * 2, urlStringSize.width + DRAG_LABEL_BORDER_X * 2); } } NSImage *dragImage = [[[NSImage alloc] initWithSize: imageSize] autorelease]; @@ -2299,24 +2305,36 @@ static bool matchesExtensionOrEquivalent(NSString *filename, NSString *extension return [[webView _editingDelegateForwarder] webView:webView doCommandBySelector:selector]; } +typedef HashMap SelectorNameMap; + +// Map selectors into Editor command names. +// This is not needed for any selectors that have the same name as the Editor command. +static const SelectorNameMap* createSelectorExceptionMap() +{ + SelectorNameMap* map = new HashMap; + + map->add(@selector(insertNewlineIgnoringFieldEditor:), "InsertNewline"); + map->add(@selector(insertParagraphSeparator:), "InsertNewline"); + map->add(@selector(insertTabIgnoringFieldEditor:), "InsertTab"); + map->add(@selector(pageDown:), "MovePageDown"); + map->add(@selector(pageDownAndModifySelection:), "MovePageDownAndModifySelection"); + map->add(@selector(pageUp:), "MovePageUp"); + map->add(@selector(pageUpAndModifySelection:), "MovePageUpAndModifySelection"); + + return map; +} + static String commandNameForSelector(SEL selector) { - // Change a few command names into ones supported by WebCore::Editor. - // If this list gets too long we might decide we need to use a hash table. - if (selector == @selector(insertParagraphSeparator:) || selector == @selector(insertNewlineIgnoringFieldEditor:)) - return "InsertNewline"; - if (selector == @selector(insertTabIgnoringFieldEditor:)) - return "InsertTab"; - if (selector == @selector(pageDown:)) - return "MovePageDown"; - if (selector == @selector(pageDownAndModifySelection:)) - return "MovePageDownAndModifySelection"; - if (selector == @selector(pageUp:)) - return "MovePageUp"; - if (selector == @selector(pageUpAndModifySelection:)) - return "MovePageUpAndModifySelection"; + // Check the exception map first. + static const SelectorNameMap* exceptionMap = createSelectorExceptionMap(); + SelectorNameMap::const_iterator it = exceptionMap->find(selector); + if (it != exceptionMap->end()) + return it->second; // Remove the trailing colon. + // No need to capitalize the command name since Editor command names are + // not case sensitive. const char* selectorName = sel_getName(selector); size_t selectorNameLength = strlen(selectorName); if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':') @@ -3160,7 +3178,8 @@ WEBCORE_COMMAND(yankAndSelect) double start = CFAbsoluteTimeGetCurrent(); #endif - if ([[self _webView] _mustDrawUnionedRect:rect singleRects:rects count:count]) + WebView *webView = [self _webView]; + if ([webView _mustDrawUnionedRect:rect singleRects:rects count:count]) [self drawSingleRect:rect]; else for (int i = 0; i < count; ++i) @@ -3175,16 +3194,19 @@ WEBCORE_COMMAND(yankAndSelect) [self _setAsideSubviews]; #if USE(ACCELERATED_COMPOSITING) - if ([[self _webView] _needsOneShotDrawingSynchronization]) { + if ([webView _needsOneShotDrawingSynchronization]) { // Disable screen updates so that any layer changes committed here // don't show up on the screen before the window flush at the end - // of the current window display. - [[self window] disableScreenUpdatesUntilFlush]; + // of the current window display, but only if a window flush is actually + // going to happen. + NSWindow *window = [self window]; + if ([window viewsNeedDisplay]) + [window disableScreenUpdatesUntilFlush]; // Make sure any layer changes that happened as a result of layout // via -viewWillDraw are committed. [CATransaction flush]; - [[self _webView] _setNeedsOneShotDrawingSynchronization:NO]; + [webView _setNeedsOneShotDrawingSynchronization:NO]; } #endif } @@ -3407,10 +3429,6 @@ done: if (!page) return NSDragOperationNone; - // FIXME: Why do we override the source provided operation here? Why not in DragController::startDrag - if (page->dragController()->sourceDragOperation() == DragOperationNone) - return NSDragOperationGeneric | NSDragOperationCopy; - return (NSDragOperation)page->dragController()->sourceDragOperation(); } @@ -3715,7 +3733,7 @@ static BOOL isInPasswordField(Frame* coreFrame) #ifdef __LP64__ // If the new bottom is equal to the old bottom (when both are treated as floats), we just copy // oldBottom over to newBottom. This prevents rounding errors that can occur when converting newBottomFloat to a double. - if (fabs((float)oldBottom - newBottomFloat) <= std::numeric_limits::epsilon()) + if (fabs((float)oldBottom - newBottomFloat) <= numeric_limits::epsilon()) *newBottom = oldBottom; else #endif @@ -3750,7 +3768,7 @@ static BOOL isInPasswordField(Frame* coreFrame) float maxShrinkToFitScaleFactor = 1.0f / PrintingMaximumShrinkFactor; float shrinkToFitScaleFactor = [self _availablePaperWidthForPrintOperation:printOperation]/viewWidth; float shrinkToAvoidOrphan = _private->avoidingPrintOrphan ? (1.0f / PrintingOrphanShrinkAdjustment) : 1.0f; - return userScaleFactor * MAX(maxShrinkToFitScaleFactor, shrinkToFitScaleFactor) * shrinkToAvoidOrphan; + return userScaleFactor * max(maxShrinkToFitScaleFactor, shrinkToFitScaleFactor) * shrinkToAvoidOrphan; } // FIXME 3491344: This is a secret AppKit-internal method that we need to override in order @@ -5450,13 +5468,13 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) if (!_private->layerHostingView) return; - const CGFloat maxHeight = 4096; + const CGFloat maxHeight = 2048; NSRect layerViewFrame = [self bounds]; if (layerViewFrame.size.height > maxHeight) { CGFloat documentHeight = layerViewFrame.size.height; - // Clamp the size of the view to <= 4096px to avoid the bug. + // Clamp the size of the view to <= maxHeight to avoid the bug. layerViewFrame.size.height = maxHeight; NSRect visibleRect = [[self enclosingScrollView] documentVisibleRect]; @@ -5468,7 +5486,8 @@ static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point) CGFloat bottomOffset = documentHeight - layerViewFrame.size.height - topOffset; [[_private->layerHostingView layer] setSublayerTransform:CATransform3DMakeTranslation(0, -bottomOffset, 0)]; } - + + [_private->layerHostingView _updateLayerGeometryFromView]; // Workaround for [_private->layerHostingView setFrame:layerViewFrame]; } #endif // defined(BUILDING_ON_LEOPARD) diff --git a/WebKit/mac/WebView/WebHTMLViewInternal.h b/WebKit/mac/WebView/WebHTMLViewInternal.h index b5ec1c0..3f1f50d 100644 --- a/WebKit/mac/WebView/WebHTMLViewInternal.h +++ b/WebKit/mac/WebView/WebHTMLViewInternal.h @@ -30,6 +30,9 @@ #import "WebHTMLViewPrivate.h" +#if USE(ACCELERATED_COMPOSITING) +@class CALayer; +#endif @class WebFrame; namespace WebCore { diff --git a/WebKit/mac/WebView/WebHistoryDelegate.h b/WebKit/mac/WebView/WebHistoryDelegate.h new file mode 100644 index 0000000..4029eb0 --- /dev/null +++ b/WebKit/mac/WebView/WebHistoryDelegate.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@class WebFrame; +@class WebNavigationData; +@class WebView; + +@interface NSObject (WebHistoryDelegate) + +- (void)webView:(WebView *)webView didNavigateWithNavigationData:(WebNavigationData *)navigationData inFrame:(WebFrame *)webFrame; + +- (void)webView:(WebView *)webView didPerformClientRedirectFromURL:(NSString *)sourceURL toURL:(NSString *)destinationURL inFrame:(WebFrame *)webFrame; + +- (void)webView:(WebView *)webView didPerformServerRedirectFromURL:(NSString *)sourceURL toURL:(NSString *)destinationURL inFrame:(WebFrame *)webFrame; + +- (void)webView:(WebView *)webView updateHistoryTitle:(NSString *)title forURL:(NSString *)url; + +@end diff --git a/WebKit/mac/WebView/WebJSPDFDoc.h b/WebKit/mac/WebView/WebJSPDFDoc.h new file mode 100644 index 0000000..d3e756c --- /dev/null +++ b/WebKit/mac/WebView/WebJSPDFDoc.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@class WebDataSource; + +JSObjectRef makeJSPDFDoc(JSContextRef, WebDataSource *); diff --git a/WebKit/mac/WebView/WebJSPDFDoc.mm b/WebKit/mac/WebView/WebJSPDFDoc.mm new file mode 100644 index 0000000..24169fe --- /dev/null +++ b/WebKit/mac/WebView/WebJSPDFDoc.mm @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebJSPDFDoc.h" + +#import "WebDataSource.h" +#import "WebDelegateImplementationCaching.h" +#import "WebFrame.h" +#import "WebView.h" +#import + +static void jsPDFDocInitialize(JSContextRef ctx, JSObjectRef object) +{ + WebDataSource *dataSource = (WebDataSource *)JSObjectGetPrivate(object); + CFRetain(dataSource); +} + +static void jsPDFDocFinalize(JSObjectRef object) +{ + WebDataSource *dataSource = (WebDataSource *)JSObjectGetPrivate(object); + CFRelease(dataSource); +} + +static JSValueRef jsPDFDocPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + WebDataSource *dataSource = (WebDataSource *)JSObjectGetPrivate(thisObject); + + WebView *webView = [[dataSource webFrame] webView]; + CallUIDelegate(webView, @selector(webView:printFrameView:), [[dataSource webFrame] frameView]); + + return JSValueMakeUndefined(ctx); +} + +static JSStaticFunction jsPDFDocStaticFunctions[] = { + { "print", jsPDFDocPrint, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, + { 0, 0, 0 }, +}; + +static JSClassDefinition jsPDFDocClassDefinition = { + 0, + kJSClassAttributeNone, + "Doc", + 0, + 0, + jsPDFDocStaticFunctions, + jsPDFDocInitialize, jsPDFDocFinalize, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +JSObjectRef makeJSPDFDoc(JSContextRef ctx, WebDataSource *dataSource) +{ + static JSClassRef jsPDFDocClass = JSClassCreate(&jsPDFDocClassDefinition); + + return JSObjectMake(ctx, jsPDFDocClass, dataSource); +} diff --git a/WebKit/mac/WebView/WebNavigationData.h b/WebKit/mac/WebView/WebNavigationData.h new file mode 100644 index 0000000..227df16 --- /dev/null +++ b/WebKit/mac/WebView/WebNavigationData.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@class WebFrame; +@class WebNavigationDataPrivate; +@class WebView; + +@interface WebNavigationData : NSObject +{ +@private + WebNavigationDataPrivate *_private; +} + +- (id)initWithURLString:(NSString *)url title:(NSString *)title originalRequest:(NSURLRequest *)request response:(NSURLResponse *)response hasSubstituteData:(BOOL)hasSubstituteData clientRedirectSource:(NSString *)redirectSource; +- (NSString *)url; +- (NSString *)title; +- (NSURLRequest *)originalRequest; +- (NSURLResponse *)response; +- (BOOL)hasSubstituteData; +- (NSString *)clientRedirectSource; + +@end diff --git a/WebKit/mac/WebView/WebNavigationData.mm b/WebKit/mac/WebView/WebNavigationData.mm new file mode 100644 index 0000000..290d8b1 --- /dev/null +++ b/WebKit/mac/WebView/WebNavigationData.mm @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebNavigationData.h" + +@interface WebNavigationDataPrivate : NSObject +{ +@public + NSString *url; + NSString *title; + NSURLRequest *originalRequest; + NSURLResponse *response; + BOOL hasSubstituteData; + NSString *clientRedirectSource; +} + +@end + +@implementation WebNavigationDataPrivate + +- (void)dealloc +{ + [url release]; + [title release]; + [originalRequest release]; + [response release]; + [clientRedirectSource release]; + + [super dealloc]; +} + +@end + +@implementation WebNavigationData + +- (id)initWithURLString:(NSString *)url title:(NSString *)title originalRequest:(NSURLRequest *)request response:(NSURLResponse *)response hasSubstituteData:(BOOL)hasSubstituteData clientRedirectSource:(NSString *)redirectSource; +{ + _private = [[WebNavigationDataPrivate alloc] init]; + + _private->url = [url retain]; + _private->title = [title retain]; + _private->originalRequest = [request retain]; + _private->response = [response retain]; + _private->hasSubstituteData = hasSubstituteData; + _private->clientRedirectSource = [redirectSource retain]; + + return self; +} + +- (NSString *)url +{ + return _private->url; +} + +- (NSString *)title +{ + return _private->title; +} + +- (NSURLRequest *)originalRequest +{ + return _private->originalRequest; +} + +- (NSURLResponse *)response +{ + return _private->response; +} + +- (BOOL)hasSubstituteData +{ + return _private->hasSubstituteData; +} + +- (NSString *)clientRedirectSource +{ + return _private->clientRedirectSource; +} + +- (void)dealloc +{ + [_private release]; + [super dealloc]; +} + +@end diff --git a/WebKit/mac/WebView/WebPDFDocumentExtras.h b/WebKit/mac/WebView/WebPDFDocumentExtras.h new file mode 100644 index 0000000..5a33ccf --- /dev/null +++ b/WebKit/mac/WebView/WebPDFDocumentExtras.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@interface PDFDocument (WebPDFDocumentExtras) +- (NSArray *)_web_allScripts; +@end + +void addWebPDFDocumentExtras(Class); diff --git a/WebKit/mac/WebView/WebPDFDocumentExtras.mm b/WebKit/mac/WebView/WebPDFDocumentExtras.mm new file mode 100644 index 0000000..ec580ec --- /dev/null +++ b/WebKit/mac/WebView/WebPDFDocumentExtras.mm @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebPDFDocumentExtras.h" + +#import "WebTypesInternal.h" +#import +#import +#import +#import + +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) +@interface PDFDocument (Internal) +- (CGPDFDocumentRef)documentRef; +@end +#endif + +static void appendValuesInPDFNameSubtreeToVector(CGPDFDictionaryRef subtree, Vector& values) +{ + CGPDFArrayRef names; + if (CGPDFDictionaryGetArray(subtree, "Names", &names)) { + size_t nameCount = CGPDFArrayGetCount(names) / 2; + for (size_t i = 0; i < nameCount; ++i) { + CGPDFObjectRef object; + CGPDFArrayGetObject(names, 2 * i + 1, &object); + values.append(object); + } + return; + } + + CGPDFArrayRef kids; + if (!CGPDFDictionaryGetArray(subtree, "Kids", &kids)) + return; + + size_t kidCount = CGPDFArrayGetCount(kids); + for (size_t i = 0; i < kidCount; ++i) { + CGPDFDictionaryRef kid; + if (!CGPDFArrayGetDictionary(kids, i, &kid)) + continue; + appendValuesInPDFNameSubtreeToVector(kid, values); + } +} + +static void getAllValuesInPDFNameTree(CGPDFDictionaryRef tree, Vector& allValues) +{ + appendValuesInPDFNameSubtreeToVector(tree, allValues); +} + +static NSArray *web_PDFDocumentAllScripts(id self, SEL _cmd) +{ + NSMutableArray *scripts = [NSMutableArray array]; + CGPDFDocumentRef pdfDocument = [self documentRef]; + if (!pdfDocument) + return scripts; + + CGPDFDictionaryRef pdfCatalog = CGPDFDocumentGetCatalog(pdfDocument); + if (!pdfCatalog) + return scripts; + + // Get the dictionary of all document-level name trees. + CGPDFDictionaryRef namesDictionary; + if (!CGPDFDictionaryGetDictionary(pdfCatalog, "Names", &namesDictionary)) + return scripts; + + // Get the document-level "JavaScript" name tree. + CGPDFDictionaryRef javaScriptNameTree; + if (!CGPDFDictionaryGetDictionary(namesDictionary, "JavaScript", &javaScriptNameTree)) + return scripts; + + // The names are aribtrary. We are only interested in the values. + Vector objects; + getAllValuesInPDFNameTree(javaScriptNameTree, objects); + size_t objectCount = objects.size(); + + for (size_t i = 0; i < objectCount; ++i) { + CGPDFDictionaryRef javaScriptAction; + if (!CGPDFObjectGetValue(reinterpret_cast(objects[i]), kCGPDFObjectTypeDictionary, &javaScriptAction)) + continue; + + // A JavaScript action must have an action type of "JavaScript". + const char* actionType; + if (!CGPDFDictionaryGetName(javaScriptAction, "S", &actionType) || strcmp(actionType, "JavaScript")) + continue; + + const UInt8* bytes = 0; + CFIndex length; + CGPDFStreamRef stream; + CGPDFStringRef string; + RetainPtr data; + if (CGPDFDictionaryGetStream(javaScriptAction, "JS", &stream)) { + CGPDFDataFormat format; + data.adoptCF(CGPDFStreamCopyData(stream, &format)); + bytes = CFDataGetBytePtr(data.get()); + length = CFDataGetLength(data.get()); + } else if (CGPDFDictionaryGetString(javaScriptAction, "JS", &string)) { + bytes = CGPDFStringGetBytePtr(string); + length = CGPDFStringGetLength(string); + } + if (!bytes) + continue; + + NSStringEncoding encoding = (length > 1 && bytes[0] == 0xFE && bytes[1] == 0xFF) ? NSUnicodeStringEncoding : NSUTF8StringEncoding; + NSString *script = [[NSString alloc] initWithBytes:bytes length:length encoding:encoding]; + [scripts addObject:script]; + [script release]; + } + + return scripts; +} + +void addWebPDFDocumentExtras(Class pdfDocumentClass) +{ +#ifndef BUILDING_ON_TIGER + class_addMethod(pdfDocumentClass, @selector(_web_allScripts), (IMP)web_PDFDocumentAllScripts, "@@:"); +#else + static struct objc_method_list methodList = { 0, 1, { @selector(_web_allScripts), (char*)"@@:", (IMP)web_PDFDocumentAllScripts } }; + class_addMethods(pdfDocumentClass, &methodList); +#endif +} diff --git a/WebKit/mac/WebView/WebPDFRepresentation.h b/WebKit/mac/WebView/WebPDFRepresentation.h index 6b60d4c..be40ae1 100644 --- a/WebKit/mac/WebView/WebPDFRepresentation.h +++ b/WebKit/mac/WebView/WebPDFRepresentation.h @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import +#import "WebDocument.h" @protocol WebDocumentRepresentation; diff --git a/WebKit/mac/WebView/WebPDFRepresentation.m b/WebKit/mac/WebView/WebPDFRepresentation.m deleted file mode 100644 index 7eae380..0000000 --- a/WebKit/mac/WebView/WebPDFRepresentation.m +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import -#import -#import -#import -#import -#import -#import - -#import - -@implementation WebPDFRepresentation - -+ (NSArray *)postScriptMIMETypes -{ - return [NSArray arrayWithObjects: - @"application/postscript", - nil]; -} - -+ (NSArray *)supportedMIMETypes -{ - return [[[self class] postScriptMIMETypes] arrayByAddingObjectsFromArray: - [NSArray arrayWithObjects: - @"text/pdf", - @"application/pdf", - nil]]; -} - -+ (Class)PDFDocumentClass -{ - static Class PDFDocumentClass = nil; - if (PDFDocumentClass == nil) { - PDFDocumentClass = [[WebPDFView PDFKitBundle] classNamed:@"PDFDocument"]; - if (PDFDocumentClass == nil) { - LOG_ERROR("Couldn't find PDFDocument class in PDFKit.framework"); - } - } - return PDFDocumentClass; -} - -- (void)setDataSource:(WebDataSource *)dataSource; -{ -} - -- (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource; -{ -} - -- (void)receivedError:(NSError *)error withDataSource:(WebDataSource *)dataSource; -{ -} - -- (NSData *)convertPostScriptDataSourceToPDF:(NSData *)data -{ - // Convert PostScript to PDF using Quartz 2D API - // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_ps_convert/chapter_16_section_1.html - - CGPSConverterCallbacks callbacks = { 0, 0, 0, 0, 0, 0, 0, 0 }; - CGPSConverterRef converter = CGPSConverterCreate(0, &callbacks, 0); - ASSERT(converter); - - CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data); - ASSERT(provider); - - CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); - ASSERT(result); - - CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(result); - ASSERT(consumer); - - // Error handled by detecting zero-length 'result' in caller - CGPSConverterConvert(converter, provider, consumer, 0); - - CFRelease(converter); - CFRelease(provider); - CFRelease(consumer); - - return WebCFAutorelease(result); -} - -- (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource -{ - NSData *data = [dataSource data]; - - NSArray *postScriptMIMETypes = [[self class] postScriptMIMETypes]; - NSString *mimeType = [dataSource _responseMIMEType]; - if ([postScriptMIMETypes containsObject:mimeType]) { - data = [self convertPostScriptDataSourceToPDF:data]; - if ([data length] == 0) - return; - } - - WebPDFView *view = (WebPDFView *)[[[dataSource webFrame] frameView] documentView]; - PDFDocument *doc = [[[[self class] PDFDocumentClass] alloc] initWithData:data]; - [view setPDFDocument:doc]; - [doc release]; -} - - -- (BOOL)canProvideDocumentSource -{ - return NO; -} - - -- (NSString *)documentSource -{ - return nil; -} - - -- (NSString *)title -{ - return nil; -} - -@end diff --git a/WebKit/mac/WebView/WebPDFRepresentation.mm b/WebKit/mac/WebView/WebPDFRepresentation.mm new file mode 100644 index 0000000..924bda8 --- /dev/null +++ b/WebKit/mac/WebView/WebPDFRepresentation.mm @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebPDFRepresentation.h" + +#import "WebDataSourcePrivate.h" +#import "WebFrame.h" +#import "WebJSPDFDoc.h" +#import "WebNSObjectExtras.h" +#import "WebPDFDocumentExtras.h" +#import "WebPDFView.h" +#import "WebTypesInternal.h" +#import +#import +#import +#import + +@implementation WebPDFRepresentation + ++ (NSArray *)postScriptMIMETypes +{ + return [NSArray arrayWithObjects: + @"application/postscript", + nil]; +} + ++ (NSArray *)supportedMIMETypes +{ + return [[[self class] postScriptMIMETypes] arrayByAddingObjectsFromArray: + [NSArray arrayWithObjects: + @"text/pdf", + @"application/pdf", + nil]]; +} + ++ (Class)PDFDocumentClass +{ + static Class PDFDocumentClass = nil; + if (PDFDocumentClass == nil) { + PDFDocumentClass = [[WebPDFView PDFKitBundle] classNamed:@"PDFDocument"]; + if (PDFDocumentClass == nil) { + LOG_ERROR("Couldn't find PDFDocument class in PDFKit.framework"); + } + } + return PDFDocumentClass; +} + ++ (void)initialize +{ + if (self != [WebPDFRepresentation class]) + return; + + Class pdfDocumentClass = [self PDFDocumentClass]; + if (pdfDocumentClass) + addWebPDFDocumentExtras(pdfDocumentClass); +} + +- (void)setDataSource:(WebDataSource *)dataSource; +{ +} + +- (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource; +{ +} + +- (void)receivedError:(NSError *)error withDataSource:(WebDataSource *)dataSource; +{ +} + +- (NSData *)convertPostScriptDataSourceToPDF:(NSData *)data +{ + // Convert PostScript to PDF using Quartz 2D API + // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_ps_convert/chapter_16_section_1.html + + CGPSConverterCallbacks callbacks = { 0, 0, 0, 0, 0, 0, 0, 0 }; + CGPSConverterRef converter = CGPSConverterCreate(0, &callbacks, 0); + ASSERT(converter); + + CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data); + ASSERT(provider); + + CFMutableDataRef result = CFDataCreateMutable(kCFAllocatorDefault, 0); + ASSERT(result); + + CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(result); + ASSERT(consumer); + + // Error handled by detecting zero-length 'result' in caller + CGPSConverterConvert(converter, provider, consumer, 0); + + CFRelease(converter); + CFRelease(provider); + CFRelease(consumer); + + return WebCFAutorelease(result); +} + +- (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource +{ + NSData *data = [dataSource data]; + + NSArray *postScriptMIMETypes = [[self class] postScriptMIMETypes]; + NSString *mimeType = [dataSource _responseMIMEType]; + if ([postScriptMIMETypes containsObject:mimeType]) { + data = [self convertPostScriptDataSourceToPDF:data]; + if ([data length] == 0) + return; + } + + WebPDFView *view = (WebPDFView *)[[[dataSource webFrame] frameView] documentView]; + PDFDocument *doc = [[[[self class] PDFDocumentClass] alloc] initWithData:data]; + [view setPDFDocument:doc]; + + NSArray *scripts = [doc _web_allScripts]; + [doc release]; + doc = nil; + + NSUInteger scriptCount = [scripts count]; + if (!scriptCount) + return; + + JSGlobalContextRef ctx = JSGlobalContextCreate(0); + JSObjectRef jsPDFDoc = makeJSPDFDoc(ctx, dataSource); + + for (NSUInteger i = 0; i < scriptCount; ++i) { + JSStringRef script = JSStringCreateWithCFString((CFStringRef)[scripts objectAtIndex:i]); + JSEvaluateScript(ctx, script, jsPDFDoc, 0, 0, 0); + JSStringRelease(script); + } + + JSGlobalContextRelease(ctx); +} + +- (BOOL)canProvideDocumentSource +{ + return NO; +} + + +- (NSString *)documentSource +{ + return nil; +} + + +- (NSString *)title +{ + return nil; +} + +@end diff --git a/WebKit/mac/WebView/WebPolicyDelegatePrivate.h b/WebKit/mac/WebView/WebPolicyDelegatePrivate.h index 45f8f45..efdf007 100644 --- a/WebKit/mac/WebView/WebPolicyDelegatePrivate.h +++ b/WebKit/mac/WebView/WebPolicyDelegatePrivate.h @@ -49,4 +49,6 @@ typedef enum { @interface NSObject (WebPolicyDelegatePrivate) // Needed for can view pages from the back/forward cache that should be disallowed by Parental Controls - (BOOL)webView:(WebView *)webView shouldGoToHistoryItem:(WebHistoryItem *)item; + +- (BOOL)webView:(WebView *)webView shouldLoadMediaURL:(NSURL *)url inFrame:(WebFrame *)frame; @end diff --git a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h index 6565c09..d6c9d3c 100644 --- a/WebKit/mac/WebView/WebPreferenceKeysPrivate.h +++ b/WebKit/mac/WebView/WebPreferenceKeysPrivate.h @@ -55,6 +55,8 @@ #define WebKitPluginsEnabledPreferenceKey @"WebKitPluginsEnabled" #define WebKitDatabasesEnabledPreferenceKey @"WebKitDatabasesEnabledPreferenceKey" #define WebKitLocalStorageEnabledPreferenceKey @"WebKitLocalStorageEnabledPreferenceKey" +#define WebKitExperimentalNotificationsEnabledPreferenceKey @"WebKitExperimentalNotificationsEnabledPreferenceKey" +#define WebKitExperimentalWebSocketsEnabledPreferenceKey @"WebKitExperimentalWebSocketsEnabledPreferenceKey" #define WebKitAllowAnimatedImagesPreferenceKey @"WebKitAllowAnimatedImagesPreferenceKey" #define WebKitAllowAnimatedImageLoopingPreferenceKey @"WebKitAllowAnimatedImageLoopingPreferenceKey" #define WebKitDisplayImagesKey @"WebKitDisplayImagesKey" @@ -84,6 +86,9 @@ #define WebKitZoomsTextOnlyPreferenceKey @"WebKitZoomsTextOnly" #define WebKitXSSAuditorEnabledPreferenceKey @"WebKitXSSAuditorEnabled" #define WebKitAcceleratedCompositingEnabledPreferenceKey @"WebKitAcceleratedCompositingEnabled" +#define WebKitWebGLEnabledPreferenceKey @"WebKitWebGLEnabled" +#define WebKitPluginHalterEnabledPreferenceKey @"WebKitPluginHalterEnabled" +#define WebKitPluginAllowedRunTimePreferenceKey @"WebKitPluginAllowedRunTime" // These are private both because callers should be using the cover methods and because the // cover methods themselves are private. diff --git a/WebKit/mac/WebView/WebPreferences.mm b/WebKit/mac/WebView/WebPreferences.mm index 378b280..2910d27 100644 --- a/WebKit/mac/WebView/WebPreferences.mm +++ b/WebKit/mac/WebView/WebPreferences.mm @@ -320,6 +320,8 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:YES], WebKitPluginsEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitDatabasesEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitLocalStorageEnabledPreferenceKey, + [NSNumber numberWithBool:NO], WebKitExperimentalNotificationsEnabledPreferenceKey, + [NSNumber numberWithBool:NO], WebKitExperimentalWebSocketsEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitAllowAnimatedImagesPreferenceKey, [NSNumber numberWithBool:YES], WebKitAllowAnimatedImageLoopingPreferenceKey, [NSNumber numberWithBool:YES], WebKitDisplayImagesKey, @@ -350,6 +352,9 @@ static WebCacheModel cacheModelForMainBundle(void) [NSNumber numberWithBool:YES], WebKitZoomsTextOnlyPreferenceKey, [NSNumber numberWithBool:YES], WebKitXSSAuditorEnabledPreferenceKey, [NSNumber numberWithBool:YES], WebKitAcceleratedCompositingEnabledPreferenceKey, + [NSNumber numberWithBool:NO], WebKitWebGLEnabledPreferenceKey, + [NSNumber numberWithBool:NO], WebKitPluginHalterEnabledPreferenceKey, + [NSNumber numberWithUnsignedInt:4], WebKitPluginAllowedRunTimePreferenceKey, nil]; // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above @@ -1011,6 +1016,26 @@ static WebCacheModel cacheModelForMainBundle(void) [self _setBoolValue:localStorageEnabled forKey:WebKitLocalStorageEnabledPreferenceKey]; } +- (BOOL)experimentalNotificationsEnabled +{ + return [self _boolValueForKey:WebKitExperimentalNotificationsEnabledPreferenceKey]; +} + +- (void)setExperimentalNotificationsEnabled:(BOOL)experimentalNotificationsEnabled +{ + [self _setBoolValue:experimentalNotificationsEnabled forKey:WebKitExperimentalNotificationsEnabledPreferenceKey]; +} + +- (BOOL)experimentalWebSocketsEnabled +{ + return [self _boolValueForKey:WebKitExperimentalWebSocketsEnabledPreferenceKey]; +} + +- (void)setExperimentalWebSocketsEnabled:(BOOL)experimentalWebSocketsEnabled +{ + [self _setBoolValue:experimentalWebSocketsEnabled forKey:WebKitExperimentalWebSocketsEnabledPreferenceKey]; +} + + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident { LOG(Encoding, "requesting for %@\n", ident); @@ -1138,6 +1163,36 @@ static NSString *classIBCreatorID = nil; [self _setBoolValue:enabled forKey:WebKitAcceleratedCompositingEnabledPreferenceKey]; } +- (BOOL)webGLEnabled +{ + return [self _boolValueForKey:WebKitWebGLEnabledPreferenceKey]; +} + +- (void)setWebGLEnabled:(BOOL)enabled +{ + [self _setBoolValue:enabled forKey:WebKitWebGLEnabledPreferenceKey]; +} + +- (BOOL)pluginHalterEnabled +{ + return [self _boolValueForKey:WebKitPluginHalterEnabledPreferenceKey]; +} + +- (void)setPluginHalterEnabled:(BOOL)enabled +{ + [self _setBoolValue:enabled forKey:WebKitPluginHalterEnabledPreferenceKey]; +} + +- (unsigned)pluginAllowedRunTime +{ + return [self _integerValueForKey:WebKitPluginAllowedRunTimePreferenceKey]; +} + +- (void)setPluginAllowedRunTime:(unsigned)allowedRunTime +{ + return [self _setIntegerValue:allowedRunTime forKey:WebKitPluginAllowedRunTimePreferenceKey]; +} + - (void)didRemoveFromWebView { ASSERT(_private->numWebViews); @@ -1152,6 +1207,12 @@ static NSString *classIBCreatorID = nil; { ++_private->numWebViews; } + +- (void)_setPreferenceForTestWithValue:(NSString *)value forKey:(NSString *)key +{ + [self _setStringValue:value forKey:key]; +} + @end @implementation WebPreferences (WebInternal) diff --git a/WebKit/mac/WebView/WebPreferencesPrivate.h b/WebKit/mac/WebView/WebPreferencesPrivate.h index d571869..6a25921 100644 --- a/WebKit/mac/WebView/WebPreferencesPrivate.h +++ b/WebKit/mac/WebView/WebPreferencesPrivate.h @@ -107,6 +107,18 @@ extern NSString *WebPreferencesRemovedNotification; - (BOOL)isXSSAuditorEnabled; - (void)setXSSAuditorEnabled:(BOOL)flag; +- (BOOL)experimentalNotificationsEnabled; +- (void)setExperimentalNotificationsEnabled:(BOOL)notificationsEnabled; + +- (BOOL)experimentalWebSocketsEnabled; +- (void)setExperimentalWebSocketsEnabled:(BOOL)websocketsEnabled; + +- (BOOL)pluginHalterEnabled; +- (void)setPluginHalterEnabled:(BOOL)enabled; + +- (unsigned)pluginAllowedRunTime; +- (void)setPluginAllowedRunTime:(unsigned)allowedRunTime; + // zero means do AutoScale - (float)PDFScaleFactor; - (void)setPDFScaleFactor:(float)scale; @@ -117,6 +129,10 @@ extern NSString *WebPreferencesRemovedNotification; - (WebTextDirectionSubmenuInclusionBehavior)textDirectionSubmenuInclusionBehavior; - (void)setTextDirectionSubmenuInclusionBehavior:(WebTextDirectionSubmenuInclusionBehavior)behavior; +// Used to set preference specified in the test via LayoutTestController.overridePreference(..). +// For use with DumpRenderTree only. +- (void)_setPreferenceForTestWithValue:(NSString *)value forKey:(NSString *)key; + // If site-specific spoofing is enabled, some pages that do inappropriate user-agent string checks will be // passed a nonstandard user-agent string to get them to work correctly. This method might be removed in // the future when there's no more need for it. @@ -139,6 +155,9 @@ extern NSString *WebPreferencesRemovedNotification; - (BOOL)acceleratedCompositingEnabled; - (void)setAcceleratedCompositingEnabled:(BOOL)enabled; +- (BOOL)webGLEnabled; +- (void)setWebGLEnabled:(BOOL)enabled; + // Other private methods - (void)_postPreferencesChangesNotification; + (WebPreferences *)_getInstanceForIdentifier:(NSString *)identifier; diff --git a/WebKit/mac/WebView/WebScriptDebugger.mm b/WebKit/mac/WebView/WebScriptDebugger.mm index 76bdf58..8deccff 100644 --- a/WebKit/mac/WebView/WebScriptDebugger.mm +++ b/WebKit/mac/WebView/WebScriptDebugger.mm @@ -32,13 +32,14 @@ #import "WebFrameInternal.h" #import "WebScriptDebugDelegate.h" #import "WebViewInternal.h" +#import +#import +#import #import #import #import #import #import -#import -#import using namespace JSC; using namespace WebCore; @@ -68,7 +69,7 @@ static NSURL *toNSURL(const UString& s) { if (s.isEmpty()) return nil; - return KURL(s); + return KURL(ParsedURLString, s); } static WebFrame *toWebFrame(JSGlobalObject* globalObject) diff --git a/WebKit/mac/WebView/WebTextCompletionController.mm b/WebKit/mac/WebView/WebTextCompletionController.mm index f7c172f..6c37b98 100644 --- a/WebKit/mac/WebView/WebTextCompletionController.mm +++ b/WebKit/mac/WebView/WebTextCompletionController.mm @@ -39,6 +39,7 @@ @end using namespace WebCore; +using namespace std; // This class handles the complete: operation. // It counts on its host view to call endRevertingChange: whenever the current completion needs to be aborted. @@ -131,7 +132,7 @@ using namespace WebCore; windowFrame.size.height = numberToShow * [_tableView rowHeight] + (numberToShow + 1) * [_tableView intercellSpacing].height; windowFrame.origin.y -= windowFrame.size.height; NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont systemFontOfSize:12.0f], NSFontAttributeName, nil]; - float maxWidth = 0.0f; + CGFloat maxWidth = 0; int maxIndex = -1; int i; for (i = 0; i < numberToShow; i++) { @@ -146,8 +147,8 @@ using namespace WebCore; maxWidth = ceilf([NSScrollView frameSizeForContentSize:NSMakeSize(maxWidth, 100.0f) hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder].width); maxWidth = ceilf([NSWindow frameRectForContentRect:NSMakeRect(0.0f, 0.0f, maxWidth, 100.0f) styleMask:NSBorderlessWindowMask].size.width); maxWidth += 5.0f; - windowFrame.size.width = MAX(maxWidth, windowFrame.size.width); - maxWidth = MIN(400.0f, windowFrame.size.width); + windowFrame.size.width = max(maxWidth, windowFrame.size.width); + maxWidth = min(400, windowFrame.size.width); } [_popupWindow setFrame:windowFrame display:NO]; diff --git a/WebKit/mac/WebView/WebUIDelegatePrivate.h b/WebKit/mac/WebView/WebUIDelegatePrivate.h index 717cf01..0715475 100644 --- a/WebKit/mac/WebView/WebUIDelegatePrivate.h +++ b/WebKit/mac/WebView/WebUIDelegatePrivate.h @@ -109,7 +109,7 @@ enum { - (void)webView:(WebView *)sender willPopupMenu:(NSMenu *)menu; - (void)webView:(WebView *)sender contextMenuItemSelected:(NSMenuItem *)item forElement:(NSDictionary *)element; - (void)webView:(WebView *)sender saveFrameView:(WebFrameView *)frameView showingPanel:(BOOL)showingPanel; - +- (BOOL)webView:(WebView *)sender shouldHaltPlugin:(DOMNode *)pluginNode; /*! @method webView:frame:exceededDatabaseQuotaForSecurityOrigin:database: @param sender The WebView sending the delegate method. @@ -127,8 +127,8 @@ enum { - (BOOL)webView:(WebView *)sender frame:(WebFrame *)frame requestGeolocationPermission:(WebGeolocation *)geolocation securityOrigin:(WebSecurityOrigin *)origin; - (void)webView:(WebView *)sender formStateDidChangeForNode:(DOMNode *)node; -- (void)webView:(WebView *)sender formStateDidFocusNode:(DOMNode *)node; -- (void)webView:(WebView *)sender formStateDidBlurNode:(DOMNode *)node; +- (void)webView:(WebView *)sender formDidFocusNode:(DOMNode *)node; +- (void)webView:(WebView *)sender formDidBlurNode:(DOMNode *)node; /*! @method webView:printFrame: diff --git a/WebKit/mac/WebView/WebVideoFullscreenController.h b/WebKit/mac/WebView/WebVideoFullscreenController.h new file mode 100644 index 0000000..bb6a083 --- /dev/null +++ b/WebKit/mac/WebView/WebVideoFullscreenController.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if ENABLE(VIDEO) + +#import +#import +#import + +@protocol WebVideoFullscreenControllerDelegate; +@class WebVideoFullscreenHUDWindowController; +@class WebWindowFadeAnimation; + +@interface WebVideoFullscreenController : NSWindowController +{ +@private + RefPtr _mediaElement; // (retain) + id _delegate; // (assign) + + NSWindow *_backgroundFullscreenWindow; // (retain) + WebVideoFullscreenHUDWindowController* _hudController; // (retain) + + WebWindowFadeAnimation *_fadeAnimation; // (retain) + + BOOL _isEndingFullscreen; + BOOL _isWindowLoaded; + BOOL _forceDisableAnimation; +} + +- (id)delegate; +- (void)setDelegate:(id)delegate; + +- (void)setMediaElement:(WebCore::HTMLMediaElement*)mediaElement; +- (WebCore::HTMLMediaElement*)mediaElement; + +- (void)enterFullscreen:(NSScreen *)screen; +- (void)exitFullscreen; + +@end + +#endif + diff --git a/WebKit/mac/WebView/WebVideoFullscreenController.mm b/WebKit/mac/WebView/WebVideoFullscreenController.mm new file mode 100644 index 0000000..6592ad2 --- /dev/null +++ b/WebKit/mac/WebView/WebVideoFullscreenController.mm @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if ENABLE(VIDEO) + +#import +#import +#import + +#import +#import +#import + +#import "WebVideoFullscreenController.h" +#import "WebVideoFullscreenHUDWindowController.h" +#import "WebKitSystemInterface.h" +#import "WebTypesInternal.h" +#import "WebWindowAnimation.h" + +SOFT_LINK_FRAMEWORK(QTKit) +SOFT_LINK_CLASS(QTKit, QTMovieView) + +@interface WebVideoFullscreenWindow : NSWindow +#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER) + +#endif +{ + SEL _controllerActionOnAnimationEnd; + WebWindowScaleAnimation *_fullscreenAnimation; // (retain) + QTMovieView *_movieView; // (retain) +} +- (void)animateFromRect:(NSRect)startRect toRect:(NSRect)endRect withSubAnimation:(NSAnimation *)subAnimation controllerAction:(SEL)controllerAction; +- (QTMovieView *)movieView; +- (void)setMovieView:(QTMovieView *)movieView; +@end + +@interface WebVideoFullscreenController(HUDWindowControllerDelegate) +@end + +@implementation WebVideoFullscreenController +- (id)init +{ + // Do not defer window creation, to make sure -windowNumber is created (needed by WebWindowScaleAnimation). + NSWindow *window = [[WebVideoFullscreenWindow alloc] initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + self = [super initWithWindow:window]; + [window release]; + if (!self) + return nil; + [self windowDidLoad]; + return self; + +} +- (void)dealloc +{ + ASSERT(!_backgroundFullscreenWindow); + ASSERT(!_fadeAnimation); + [super dealloc]; +} + +- (WebVideoFullscreenWindow *)fullscreenWindow +{ + return (WebVideoFullscreenWindow *)[super window]; +} + +- (void)windowDidLoad +{ + WebVideoFullscreenWindow *window = [self fullscreenWindow]; + QTMovieView *view = [[getQTMovieViewClass() alloc] init]; + [view setFillColor:[NSColor clearColor]]; + [window setMovieView:view]; + [view setControllerVisible:NO]; + [view setPreservesAspectRatio:YES]; + if (_mediaElement) + [view setMovie:_mediaElement->platformMedia().qtMovie]; + [window setHasShadow:YES]; // This is nicer with a shadow. + [window setLevel:NSPopUpMenuWindowLevel-1]; + [view release]; +} + +- (WebCore::HTMLMediaElement*)mediaElement; +{ + return _mediaElement.get(); +} + +- (void)setMediaElement:(WebCore::HTMLMediaElement*)mediaElement; +{ + _mediaElement = mediaElement; + if ([self isWindowLoaded]) { + QTMovieView *movieView = [[self fullscreenWindow] movieView]; + [movieView setMovie:_mediaElement->platformMedia().qtMovie]; + } +} + +- (id)delegate +{ + return _delegate; +} + +- (void)setDelegate:(id)delegate; +{ + _delegate = delegate; +} + +- (CGFloat)clearFadeAnimation +{ + [_fadeAnimation stopAnimation]; + CGFloat previousAlpha = [_fadeAnimation currentAlpha]; + [_fadeAnimation setWindow:nil]; + [_fadeAnimation release]; + _fadeAnimation = nil; + return previousAlpha; +} + +- (void)windowDidExitFullscreen +{ + [self clearFadeAnimation]; + [[self window] close]; + [self setWindow:nil]; + SetSystemUIMode(kUIModeNormal, 0); + [_hudController setDelegate:nil]; + [_hudController release]; + _hudController = nil; + [_backgroundFullscreenWindow close]; + [_backgroundFullscreenWindow release]; + _backgroundFullscreenWindow = nil; + + [self autorelease]; // Associated -retain is in -exitFullscreen. + _isEndingFullscreen = NO; +} + +- (void)windowDidEnterFullscreen +{ + [self clearFadeAnimation]; + + ASSERT(!_hudController); + _hudController = [[WebVideoFullscreenHUDWindowController alloc] init]; + [_hudController setDelegate:self]; + + SetSystemUIMode(kUIModeAllSuppressed , 0); + [NSCursor setHiddenUntilMouseMoves:YES]; + + // Give the HUD keyboard focus initially + [_hudController fadeWindowIn]; +} + +- (NSRect)mediaElementRect +{ + return _mediaElement->screenRect(); +} + +#pragma mark - +#pragma mark Exposed Interface + +static void constrainFrameToRatioOfFrame(NSRect *frameToConstrain, const NSRect *frame) +{ + // Keep a constrained aspect ratio for the destination window + double originalRatio = frame->size.width / frame->size.height; + double newRatio = frameToConstrain->size.width / frameToConstrain->size.height; + if (newRatio > originalRatio) { + double newWidth = originalRatio * frameToConstrain->size.height; + double diff = frameToConstrain->size.width - newWidth; + frameToConstrain->size.width = newWidth; + frameToConstrain->origin.x += diff / 2; + } else { + double newHeight = frameToConstrain->size.width / originalRatio; + double diff = frameToConstrain->size.height - newHeight; + frameToConstrain->size.height = newHeight; + frameToConstrain->origin.y += diff / 2; + } +} + +static NSWindow *createBackgroundFullscreenWindow(NSRect frame, int level) +{ + NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + [window setOpaque:YES]; + [window setBackgroundColor:[NSColor blackColor]]; + [window setLevel:level]; + [window setHidesOnDeactivate:YES]; + [window setReleasedWhenClosed:NO]; + return window; +} + +- (void)setupFadeAnimationIfNeededAndFadeIn:(BOOL)fadeIn +{ + CGFloat initialAlpha = fadeIn ? 0 : 1; + if (_fadeAnimation) { + // Make sure we support queuing animation if the previous one isn't over yet + initialAlpha = [self clearFadeAnimation]; + } + if (!_forceDisableAnimation) + _fadeAnimation = [[WebWindowFadeAnimation alloc] initWithDuration:0.2 window:_backgroundFullscreenWindow initialAlpha:initialAlpha finalAlpha:fadeIn ? 1 : 0]; +} + +- (void)enterFullscreen:(NSScreen *)screen; +{ + if (!screen) + screen = [NSScreen mainScreen]; + + NSRect frame = [self mediaElementRect]; + NSRect endFrame = [screen frame]; + constrainFrameToRatioOfFrame(&endFrame, &frame); + + // Create a black window if needed + if (!_backgroundFullscreenWindow) + _backgroundFullscreenWindow = createBackgroundFullscreenWindow([screen frame], [[self window] level]-1); + else + [_backgroundFullscreenWindow setFrame:[screen frame] display:NO]; + + [self setupFadeAnimationIfNeededAndFadeIn:YES]; + if (_forceDisableAnimation) { + // This will disable scale animation + frame = NSZeroRect; + } + [[self fullscreenWindow] animateFromRect:frame toRect:endFrame withSubAnimation:_fadeAnimation controllerAction:@selector(windowDidEnterFullscreen)]; + + [_backgroundFullscreenWindow orderWindow:NSWindowBelow relativeTo:[[self fullscreenWindow] windowNumber]]; +} + +- (void)exitFullscreen +{ + if (_isEndingFullscreen) + return; + _isEndingFullscreen = YES; + [_hudController closeWindow]; + + NSRect endFrame = [self mediaElementRect]; + + [self setupFadeAnimationIfNeededAndFadeIn:NO]; + if (_forceDisableAnimation) { + // This will disable scale animation + endFrame = NSZeroRect; + } + + // We have to retain ourselves because we want to be alive for the end of the animation. + // If our owner releases us we could crash if this is not the case. + // Balanced in windowDidExitFullscreen + [self retain]; + + [[self fullscreenWindow] animateFromRect:[[self window] frame] toRect:endFrame withSubAnimation:_fadeAnimation controllerAction:@selector(windowDidExitFullscreen)]; +} + +#pragma mark - +#pragma mark Window callback + +- (void)requestExitFullscreenWithAnimation:(BOOL)animation +{ + if (_isEndingFullscreen) + return; + + _forceDisableAnimation = !animation; + _mediaElement->exitFullscreen(); + _forceDisableAnimation = NO; +} + +- (void)requestExitFullscreen +{ + [self requestExitFullscreenWithAnimation:YES]; +} + +- (void)fadeHUDIn +{ + [_hudController fadeWindowIn]; +} +@end + +@implementation WebVideoFullscreenWindow + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag +{ + UNUSED_PARAM(aStyle); + self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag]; + if (!self) + return nil; + [self setOpaque:NO]; + [self setBackgroundColor:[NSColor clearColor]]; + [self setHidesOnDeactivate:YES]; + [self setIgnoresMouseEvents:NO]; + [self setAcceptsMouseMovedEvents:YES]; + return self; +} + +- (void)dealloc +{ + ASSERT(!_fullscreenAnimation); + [super dealloc]; +} + +- (QTMovieView *)movieView +{ + return _movieView; +} + +- (void)setMovieView:(QTMovieView *)movieView +{ + if (_movieView == movieView) + return; + [_movieView release]; + _movieView = [movieView retain]; + [self setContentView:_movieView]; +} + +- (BOOL)resignFirstResponder +{ + return NO; +} + +- (BOOL)canBecomeKeyWindow +{ + return NO; +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + UNUSED_PARAM(theEvent); +} + +- (void)cancelOperation:(id)sender +{ + UNUSED_PARAM(sender); + [[self windowController] requestExitFullscreen]; +} + +- (void)animatedResizeDidEnd +{ + // Call our windowController. + if (_controllerActionOnAnimationEnd) + [[self windowController] performSelector:_controllerActionOnAnimationEnd]; + _controllerActionOnAnimationEnd = NULL; +} + +// +// This function will animate a change of frame rectangle +// We support queuing animation, that means that we'll correctly +// interrupt the running animation, and queue the next one. +// +- (void)animateFromRect:(NSRect)startRect toRect:(NSRect)endRect withSubAnimation:(NSAnimation *)subAnimation controllerAction:(SEL)controllerAction +{ + _controllerActionOnAnimationEnd = controllerAction; + + BOOL wasAnimating = NO; + if (_fullscreenAnimation) { + wasAnimating = YES; + + // Interrupt any running animation. + [_fullscreenAnimation stopAnimation]; + + // Save the current rect to ensure a smooth transition. + startRect = [_fullscreenAnimation currentFrame]; + [_fullscreenAnimation release]; + _fullscreenAnimation = nil; + } + + if (NSIsEmptyRect(startRect) || NSIsEmptyRect(endRect)) { + // Fakely end the subanimation. + [subAnimation setCurrentProgress:1.0]; + // And remove the weak link to the window. + [subAnimation stopAnimation]; + + [self setFrame:endRect display:NO]; + [self makeKeyAndOrderFront:self]; + [self animatedResizeDidEnd]; + return; + } + + if (!wasAnimating) { + // We'll downscale the window during the animation based on the higher resolution rect + BOOL higherResolutionIsEndRect = startRect.size.width < endRect.size.width && startRect.size.height < endRect.size.height; + [self setFrame:higherResolutionIsEndRect ? endRect : startRect display:NO]; + } + + ASSERT(!_fullscreenAnimation); + _fullscreenAnimation = [[WebWindowScaleAnimation alloc] initWithHintedDuration:0.2 window:self initalFrame:startRect finalFrame:endRect]; + [_fullscreenAnimation setSubAnimation:subAnimation]; + [_fullscreenAnimation setDelegate:self]; + + // Make sure the animation has scaled the window before showing it. + [_fullscreenAnimation setCurrentProgress:0]; + [self makeKeyAndOrderFront:self]; + + [_fullscreenAnimation startAnimation]; +} + +- (void)animationDidEnd:(NSAnimation *)animation +{ +#if !defined(BUILDING_ON_TIGER) // Animations are never threaded on Tiger. + if (![NSThread isMainThread]) { + [self performSelectorOnMainThread:@selector(animationDidEnd:) withObject:animation waitUntilDone:NO]; + return; + } +#endif + if (animation != _fullscreenAnimation) + return; + + // The animation is not really over and was interrupted + // Don't send completion events. + if ([animation currentProgress] < 1.0) + return; + + // Ensure that animation (and subanimation) don't keep + // the weak reference to the window ivar that may be destroyed from + // now on. + [_fullscreenAnimation setWindow:nil]; + + [_fullscreenAnimation autorelease]; + _fullscreenAnimation = nil; + + [self animatedResizeDidEnd]; +} + +- (void)mouseMoved:(NSEvent *)theEvent +{ + [[self windowController] fadeHUDIn]; +} + +- (void)resignKeyWindow +{ + [super resignKeyWindow]; + [[self windowController] requestExitFullscreenWithAnimation:NO]; +} +@end + +#endif /* ENABLE(VIDEO) */ diff --git a/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h new file mode 100644 index 0000000..8b06c1c --- /dev/null +++ b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if ENABLE(VIDEO) + +#import +#import + +@protocol WebVideoFullscreenHUDWindowControllerDelegate; + +@interface WebVideoFullscreenHUDWindowController : NSWindowController { +@private + id _delegate; + NSTimer *_timelineUpdateTimer; +#if !defined(BUILDING_ON_TIGER) + NSTrackingArea *_area; +#endif + BOOL _mouseIsInHUD; + + NSControl *_timeline; + NSTextField *_remainingTimeText; + NSTextField *_elapsedTimeText; + NSControl *_volumeSlider; + NSControl *_playButton; +} +- (id)delegate; +- (void)setDelegate:(id)delegate; +- (void)fadeWindowIn; +- (void)fadeWindowOut; +- (void)closeWindow; + +@end + +@protocol WebVideoFullscreenHUDWindowControllerDelegate +- (void)requestExitFullscreen; +- (WebCore::HTMLMediaElement*)mediaElement; +@end + +#endif diff --git a/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm new file mode 100644 index 0000000..2edfccc --- /dev/null +++ b/WebKit/mac/WebView/WebVideoFullscreenHUDWindowController.mm @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if ENABLE(VIDEO) + +#import "WebVideoFullscreenHUDWindowController.h" + +#import +#import "WebKitSystemInterface.h" +#import "WebTypesInternal.h" +#import + +#define HAVE_MEDIA_CONTROL (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) + +@interface WebVideoFullscreenHUDWindowController (Private) + +- (void)updateTime; +- (void)timelinePositionChanged:(id)sender; +- (float)currentTime; +- (void)setCurrentTime:(float)currentTime; +- (double)duration; + +- (double)maxVolume; +- (void)volumeChanged:(id)sender; +- (double)volume; +- (void)setVolume:(double)volume; + +- (void)playingChanged:(id)sender; +- (BOOL)playing; +- (void)setPlaying:(BOOL)playing; + +- (void)rewind:(id)sender; +- (void)fastForward:(id)sender; + +- (NSString *)remainingTimeText; +- (NSString *)elapsedTimeText; + +- (void)exitFullscreen:(id)sender; +@end + + +// +// HUD Window +// + +@interface WebVideoFullscreenHUDWindow : NSWindow +@end + +@implementation WebVideoFullscreenHUDWindow + +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag +{ + UNUSED_PARAM(aStyle); + self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag]; + if (!self) + return nil; + + [self setOpaque:NO]; + [self setBackgroundColor:[NSColor clearColor]]; + [self setLevel:NSPopUpMenuWindowLevel]; + [self setAcceptsMouseMovedEvents:YES]; + [self setIgnoresMouseEvents:NO]; + [self setMovableByWindowBackground:YES]; + [self setHidesOnDeactivate:YES]; + + return self; +} + +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +- (void)cancelOperation:(id)sender +{ + [[self windowController] exitFullscreen:self]; +} + +- (void)center +{ + NSRect hudFrame = [self frame]; + NSRect screenFrame = [[NSScreen mainScreen] frame]; + [self setFrameTopLeftPoint:NSMakePoint(screenFrame.origin.x + (screenFrame.size.width - hudFrame.size.width) / 2, + screenFrame.origin.y + (screenFrame.size.height - hudFrame.size.height) / 6)]; +} + +- (void)keyDown:(NSEvent *)event +{ + [super keyDown:event]; + [[self windowController] fadeWindowIn]; +} + +@end + +// +// HUD Window Controller +// + +static const CGFloat windowHeight = 59; +static const CGFloat windowWidth = 438; + +static const NSTimeInterval HUDWindowFadeOutDelay = 3; + +@implementation WebVideoFullscreenHUDWindowController + +- (id)init +{ + NSWindow* window = [[WebVideoFullscreenHUDWindow alloc] initWithContentRect:NSMakeRect(0, 0, windowWidth, windowHeight) + styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + self = [super initWithWindow:window]; + [window setDelegate:self]; + [window release]; + if (!self) + return nil; + [self windowDidLoad]; + return self; +} + +- (void)dealloc +{ + ASSERT(!_timelineUpdateTimer); +#if !defined(BUILDING_ON_TIGER) + ASSERT(!_area); +#endif + [_timeline release]; + [_remainingTimeText release]; + [_elapsedTimeText release]; + [_volumeSlider release]; + [_playButton release]; + [super dealloc]; +} + +#if !defined(BUILDING_ON_TIGER) +- (void)setArea:(NSTrackingArea *)area +{ + if (area == _area) + return; + [_area release]; + _area = [area retain]; +} +#endif + +- (id)delegate +{ + return _delegate; +} + +- (void)setDelegate:(id)delegate +{ + _delegate = delegate; +} + +- (void)scheduleTimeUpdate +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(unscheduleTimeUpdate) object:self]; + + // First, update right away, then schedule future update + [self updateTime]; + + [_timelineUpdateTimer invalidate]; + [_timelineUpdateTimer release]; + + // Note that this creates a retain cycle between the window and us. + _timelineUpdateTimer = [[NSTimer timerWithTimeInterval:0.25 target:self selector:@selector(updateTime) userInfo:nil repeats:YES] retain]; +#if defined(BUILDING_ON_TIGER) + [[NSRunLoop currentRunLoop] addTimer:_timelineUpdateTimer forMode:(NSString*)kCFRunLoopCommonModes]; +#else + [[NSRunLoop currentRunLoop] addTimer:_timelineUpdateTimer forMode:NSRunLoopCommonModes]; +#endif +} + +- (void)unscheduleTimeUpdate +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(unscheduleTimeUpdate) object:nil]; + + [_timelineUpdateTimer invalidate]; + [_timelineUpdateTimer release]; + _timelineUpdateTimer = nil; +} + +- (void)fadeWindowIn +{ + NSWindow *window = [self window]; + if (![window isVisible]) + [window setAlphaValue:0]; + + [window makeKeyAndOrderFront:self]; +#if defined(BUILDING_ON_TIGER) + [window setAlphaValue:1]; +#else + [[window animator] setAlphaValue:1]; +#endif + [self scheduleTimeUpdate]; + + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeWindowOut) object:nil]; + if (!_mouseIsInHUD && [self playing]) // Don't fade out when paused. + [self performSelector:@selector(fadeWindowOut) withObject:nil afterDelay:HUDWindowFadeOutDelay]; +} + +- (void)fadeWindowOut +{ + [NSCursor setHiddenUntilMouseMoves:YES]; +#if defined(BUILDING_ON_TIGER) + [[self window] setAlphaValue:0]; +#else + [[[self window] animator] setAlphaValue:0]; +#endif + [self performSelector:@selector(unscheduleTimeUpdate) withObject:nil afterDelay:1]; +} + +- (void)closeWindow +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeWindowOut) object:nil]; + [self unscheduleTimeUpdate]; + NSWindow *window = [self window]; +#if !defined(BUILDING_ON_TIGER) + [[window contentView] removeTrackingArea:_area]; + [self setArea:nil]; +#endif + [window close]; + [window setDelegate:nil]; + [self setWindow:nil]; +} + +#ifndef HAVE_MEDIA_CONTROL +enum { + WKMediaUIControlPlayPauseButton, + WKMediaUIControlRewindButton, + WKMediaUIControlFastForwardButton, + WKMediaUIControlExitFullscreenButton, + WKMediaUIControlVolumeDownButton, + WKMediaUIControlSlider, + WKMediaUIControlVolumeUpButton, + WKMediaUIControlTimeline +}; +#endif + +static NSControl *createControlWithMediaUIControlType(int controlType, NSRect frame) +{ +#ifdef HAVE_MEDIA_CONTROL + NSControl *control = WKCreateMediaUIControl(controlType); + [control setFrame:frame]; + return control; +#else + if (controlType == WKMediaUIControlSlider) + return [[NSSlider alloc] initWithFrame:frame]; + return [[NSControl alloc] initWithFrame:frame]; +#endif +} + +static NSTextField *createTimeTextField(NSRect frame) +{ + NSTextField *textField = [[NSTextField alloc] initWithFrame:frame]; + [textField setTextColor:[NSColor whiteColor]]; + [textField setBordered:NO]; + [textField setFont:[NSFont systemFontOfSize:10]]; + [textField setDrawsBackground:NO]; + [textField setBezeled:NO]; + [textField setEditable:NO]; + [textField setSelectable:NO]; + return textField; +} + +- (void)windowDidLoad +{ + static const CGFloat kMargin = 9; + static const CGFloat kMarginTop = 9; + static const CGFloat kButtonSize = 25; + static const CGFloat kButtonMiniSize = 16; + + NSWindow *window = [self window]; + ASSERT(window); + +#ifdef HAVE_MEDIA_CONTROL + NSView *background = WKCreateMediaUIBackgroundView(); +#else + NSView *background = [[NSView alloc] init]; +#endif + [window setContentView:background]; +#if !defined(BUILDING_ON_TIGER) + _area = [[NSTrackingArea alloc] initWithRect:[background bounds] options:NSTrackingMouseEnteredAndExited|NSTrackingActiveAlways owner:self userInfo:nil]; + [background addTrackingArea:_area]; +#endif + [background release]; + + NSView *contentView = [[self window] contentView]; + + CGFloat top = windowHeight - kMarginTop; + CGFloat center = (windowWidth - kButtonSize) / 2; + _playButton = createControlWithMediaUIControlType(WKMediaUIControlPlayPauseButton, NSMakeRect(center, top - kButtonSize, kButtonSize, kButtonSize)); + [_playButton setTarget:self]; + [_playButton setAction:@selector(playingChanged:)]; + [contentView addSubview:_playButton]; + + CGFloat closeToRight = windowWidth - 2 * kMargin - kButtonMiniSize; + NSControl *exitFullscreenButton = createControlWithMediaUIControlType(WKMediaUIControlExitFullscreenButton, NSMakeRect(closeToRight, top - kButtonSize / 2 - kButtonMiniSize / 2, kButtonMiniSize, kButtonMiniSize)); + [exitFullscreenButton setAction:@selector(exitFullscreen:)]; + [exitFullscreenButton setTarget:self]; + [contentView addSubview:exitFullscreenButton]; + [exitFullscreenButton release]; + + CGFloat left = kMargin; + NSControl *volumeDownButton = createControlWithMediaUIControlType(WKMediaUIControlVolumeDownButton, NSMakeRect(left, top - kButtonSize / 2 - kButtonMiniSize / 2, kButtonMiniSize, kButtonMiniSize)); + [contentView addSubview:volumeDownButton]; + [volumeDownButton release]; + + static const int volumeSliderWidth = 50; + + left = kMargin + kButtonMiniSize; + _volumeSlider = createControlWithMediaUIControlType(WKMediaUIControlSlider, NSMakeRect(left, top - kButtonSize / 2 - kButtonMiniSize / 2, volumeSliderWidth, kButtonMiniSize)); + [_volumeSlider setValue:[NSNumber numberWithDouble:[self maxVolume]] forKey:@"maxValue"]; + [_volumeSlider setTarget:self]; + [_volumeSlider setAction:@selector(volumeChanged:)]; + [contentView addSubview:_volumeSlider]; + + left = kMargin + kButtonMiniSize + volumeSliderWidth + kButtonMiniSize / 2; + NSControl *button = createControlWithMediaUIControlType(WKMediaUIControlVolumeUpButton, NSMakeRect(left, top - kButtonSize / 2 - kButtonMiniSize / 2, kButtonMiniSize, kButtonMiniSize)); + [contentView addSubview:button]; + [button release]; + + static const int timeTextWidth = 50; + static const int sliderHeight = 13; + static const int sliderMarginFixup = 4; + +#ifdef HAVE_MEDIA_CONTROL + _timeline = WKCreateMediaUIControl(WKMediaUIControlTimeline); +#else + _timeline = [[NSSlider alloc] init]; +#endif + [_timeline setTarget:self]; + [_timeline setAction:@selector(timelinePositionChanged:)]; + [_timeline setFrame:NSMakeRect(kMargin + timeTextWidth + kMargin/2, kMargin - sliderMarginFixup, windowWidth - 2 * (kMargin - sliderMarginFixup) - kMargin * 2 - 2 * timeTextWidth, sliderHeight)]; + [contentView addSubview:_timeline]; + + static const int timeTextHeight = 11; + + _elapsedTimeText = createTimeTextField(NSMakeRect(kMargin, kMargin, timeTextWidth, timeTextHeight)); + [contentView addSubview:_elapsedTimeText]; + + _remainingTimeText = createTimeTextField(NSMakeRect(windowWidth - kMargin - timeTextWidth, kMargin, timeTextWidth, timeTextHeight)); + [contentView addSubview:_remainingTimeText]; + + [window recalculateKeyViewLoop]; + [window setInitialFirstResponder:_playButton]; + [window center]; +} + +/* + * Bindings + * + */ + +- (void)updateVolume +{ + [_volumeSlider setDoubleValue:[self volume]]; +} + +- (void)updateTime +{ + [self updateVolume]; + + [_timeline setFloatValue:[self currentTime]]; + [(NSSlider*)_timeline setMaxValue:[self duration]]; + + [_remainingTimeText setStringValue:[self remainingTimeText]]; + [_elapsedTimeText setStringValue:[self elapsedTimeText]]; +} + +- (void)fastForward +{ +} + +- (void)timelinePositionChanged:(id)sender +{ + [self setCurrentTime:[_timeline floatValue]]; +} + +- (float)currentTime +{ + return [_delegate mediaElement] ? [_delegate mediaElement]->currentTime() : 0; +} + +- (void)setCurrentTime:(float)currentTime +{ + if (![_delegate mediaElement]) + return; + WebCore::ExceptionCode e; + [_delegate mediaElement]->setCurrentTime(currentTime, e); +} + +- (double)duration +{ + return [_delegate mediaElement] ? [_delegate mediaElement]->duration() : 0; +} + +- (double)maxVolume +{ + // Set the volume slider resolution + return 100; +} + +- (void)volumeChanged:(id)sender +{ + [self setVolume:[_volumeSlider doubleValue]]; +} + +- (double)volume +{ + return [_delegate mediaElement] ? [_delegate mediaElement]->volume() * [self maxVolume] : 0; +} + +- (void)setVolume:(double)volume +{ + if (![_delegate mediaElement]) + return; + WebCore::ExceptionCode e; + [_delegate mediaElement]->setVolume(volume / [self maxVolume], e); +} + +- (void)playingChanged:(id)sender +{ + [self setPlaying:![self playing]]; + + // Keep HUD visible when paused + if (![self playing]) + [self fadeWindowIn]; + else if (!_mouseIsInHUD) { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fadeWindowOut) object:nil]; + [self performSelector:@selector(fadeWindowOut) withObject:nil afterDelay:HUDWindowFadeOutDelay]; + } +} + +- (BOOL)playing +{ + if (![_delegate mediaElement]) + return false; + return ![_delegate mediaElement]->canPlay(); +} + +- (void)setPlaying:(BOOL)playing +{ + if (![_delegate mediaElement]) + return; + + if (playing) + [_delegate mediaElement]->play(); + else + [_delegate mediaElement]->pause(); +} + +static NSString *timeToString(double time) +{ + if (!isfinite(time)) + time = 0; + int seconds = (int)fabsf(time); + int hours = seconds / (60 * 60); + int minutes = (seconds / 60) % 60; + seconds %= 60; + if (hours) { + if (hours > 9) + return [NSString stringWithFormat:@"%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds]; + else + return [NSString stringWithFormat:@"%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds]; + } + else + return [NSString stringWithFormat:@"%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds]; + +} + +static NSString *stringToTimeTextAttributed(NSString *string, NSTextAlignment align) +{ + NSShadow *blackShadow = [[NSShadow alloc] init]; + [blackShadow setShadowColor:[NSColor blackColor]]; + [blackShadow setShadowBlurRadius:0]; + [blackShadow setShadowOffset:NSMakeSize(0, -1)]; + NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; + [style setAlignment:align]; + NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:blackShadow, NSShadowAttributeName, style, NSParagraphStyleAttributeName, nil]; + [style release]; + [blackShadow release]; + + NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:dict]; + return [attrString autorelease]; +} + +- (NSString *)remainingTimeText +{ + if (![_delegate mediaElement]) + return @""; + + // Negative number + return stringToTimeTextAttributed(timeToString([_delegate mediaElement]->currentTime() - [_delegate mediaElement]->duration()), NSLeftTextAlignment); +} + +- (NSString *)elapsedTimeText +{ + if (![_delegate mediaElement]) + return @""; + + return stringToTimeTextAttributed(timeToString([_delegate mediaElement]->currentTime()), NSRightTextAlignment); +} + +/* + * Tracking area callbacks + * + */ + +- (void)mouseEntered:(NSEvent *)theEvent +{ + // Make sure the HUD won't be hidden from now + _mouseIsInHUD = YES; + [self fadeWindowIn]; +} + +- (void)mouseExited:(NSEvent *)theEvent +{ + _mouseIsInHUD = NO; + [self fadeWindowIn]; +} + +/* + * Other Interface callbacks + * + */ + +- (void)rewind:(id)sender +{ + if (![_delegate mediaElement]) + return; + [_delegate mediaElement]->rewind(30); +} + +- (void)fastForward:(id)sender +{ + if (![_delegate mediaElement]) + return; +} + +- (void)exitFullscreen:(id)sender +{ + [_delegate requestExitFullscreen]; +} + +/* + * Window callback + * + */ + +- (void)windowDidExpose:(NSNotification *)notification +{ + [self scheduleTimeUpdate]; +} + +- (void)windowDidClose:(NSNotification *)notification +{ + [self unscheduleTimeUpdate]; +} + +@end + +#endif diff --git a/WebKit/mac/WebView/WebView.mm b/WebKit/mac/WebView/WebView.mm index 20f2712..83c7e20 100644 --- a/WebKit/mac/WebView/WebView.mm +++ b/WebKit/mac/WebView/WebView.mm @@ -84,6 +84,7 @@ #import "WebPanelAuthenticationHandler.h" #import "WebPasteboardHelper.h" #import "WebPluginDatabase.h" +#import "WebPluginHalterClient.h" #import "WebPolicyDelegate.h" #import "WebPreferenceKeysPrivate.h" #import "WebPreferencesPrivate.h" @@ -93,6 +94,7 @@ #import "WebTextIterator.h" #import "WebUIDelegate.h" #import "WebUIDelegatePrivate.h" +#import "WebVideoFullscreenController.h" #import #import #import @@ -619,7 +621,7 @@ static bool runningTigerMail() didOneTimeInitialization = true; } - _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self)); + _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self), new WebPluginHalterClient(self)); _private->page->settings()->setLocalStorageDatabasePath([[self preferences] _localStorageDatabasePath]); @@ -661,11 +663,11 @@ static bool runningTigerMail() if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { // Originally, we allowed all local loads. - FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForAll); + SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll); } else if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION)) { // Later, we allowed local loads for local URLs and documents loaded // with substitute data. - FrameLoader::setLocalLoadPolicy(FrameLoader::AllowLocalLoadsForLocalAndSubstituteData); + SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData); } if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_CONTENT_SNIFFING_FOR_FILE_URLS)) @@ -997,6 +999,8 @@ static bool fastDocumentTeardownEnabled() return; } + [self _exitFullscreen]; + if (Frame* mainFrame = [self _mainCoreFrame]) mainFrame->loader()->detachFromParent(); @@ -1277,6 +1281,8 @@ static bool fastDocumentTeardownEnabled() settings->setPluginsEnabled([preferences arePlugInsEnabled]); settings->setDatabasesEnabled([preferences databasesEnabled]); settings->setLocalStorageEnabled([preferences localStorageEnabled]); + settings->setExperimentalNotificationsEnabled([preferences experimentalNotificationsEnabled]); + settings->setExperimentalWebSocketsEnabled([preferences experimentalWebSocketsEnabled]); settings->setPrivateBrowsingEnabled([preferences privateBrowsingEnabled]); settings->setSansSerifFontFamily([preferences sansSerifFontFamily]); settings->setSerifFontFamily([preferences serifFontFamily]); @@ -1311,6 +1317,9 @@ static bool fastDocumentTeardownEnabled() settings->setXSSAuditorEnabled([preferences isXSSAuditorEnabled]); settings->setEnforceCSSMIMETypeInStrictMode(!WKAppVersionCheckLessThan(@"com.apple.iWeb", -1, 2.1)); settings->setAcceleratedCompositingEnabled([preferences acceleratedCompositingEnabled]); + settings->setPluginHalterEnabled([preferences pluginHalterEnabled]); + settings->setPluginAllowedRunTime([preferences pluginAllowedRunTime]); + settings->setWebGLEnabled([preferences webGLEnabled]); } static inline IMP getMethod(id o, SEL s) @@ -1371,6 +1380,8 @@ static inline IMP getMethod(id o, SEL s) cache->willCloseFrameFunc = getMethod(delegate, @selector(webView:willCloseFrame:)); cache->willPerformClientRedirectToURLDelayFireDateForFrameFunc = getMethod(delegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:)); cache->windowScriptObjectAvailableFunc = getMethod(delegate, @selector(webView:windowScriptObjectAvailable:)); + cache->didDisplayInsecureContentFunc = getMethod(delegate, @selector(webViewDidDisplayInsecureContent:)); + cache->didRunInsecureContentFunc = getMethod(delegate, @selector(webView:didRunInsecureContent:)); } - (void)_cacheScriptDebugDelegateImplementations @@ -1396,6 +1407,22 @@ static inline IMP getMethod(id o, SEL s) cache->exceptionWasRaisedFunc = getMethod(delegate, @selector(webView:exceptionWasRaised:sourceId:line:forWebFrame:)); } +- (void)_cacheHistoryDelegateImplementations +{ + WebHistoryDelegateImplementationCache *cache = &_private->historyDelegateImplementations; + id delegate = _private->historyDelegate; + + if (!delegate) { + bzero(cache, sizeof(WebHistoryDelegateImplementationCache)); + return; + } + + cache->navigatedFunc = getMethod(delegate, @selector(webView:didNavigateWithNavigationData:inFrame:)); + cache->clientRedirectFunc = getMethod(delegate, @selector(webView:didPerformClientRedirectFromURL:toURL:inFrame:)); + cache->serverRedirectFunc = getMethod(delegate, @selector(webView:didPerformServerRedirectFromURL:toURL:inFrame:)); + cache->setTitleFunc = getMethod(delegate, @selector(webView:updateHistoryTitle:forURL:)); +} + - (id)_policyDelegateForwarder { if (!_private->policyDelegateForwarder) @@ -2092,6 +2119,15 @@ static inline IMP getMethod(id o, SEL s) return _private ? _private->insertionPasteboard : nil; } ++ (void)_whiteListAccessFromOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains +{ + SecurityOrigin::whiteListAccessFromOrigin(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); +} + ++(void)_resetOriginAccessWhiteLists +{ + SecurityOrigin::resetOriginAccessWhiteLists(); +} - (void)_updateActiveState { @@ -2099,6 +2135,108 @@ static inline IMP getMethod(id o, SEL s) _private->page->focusController()->setActive([[self window] isKeyWindow]); } +static PassOwnPtr > toStringVector(NSArray* patterns) +{ + // Convert the patterns into Vectors. + NSUInteger count = [patterns count]; + if (count == 0) + return 0; + Vector* patternsVector = new Vector; + for (NSUInteger i = 0; i < count; ++i) { + id entry = [patterns objectAtIndex:i]; + if ([entry isKindOfClass:[NSString class]]) + patternsVector->append(String((NSString*)entry)); + } + return patternsVector; +} + ++ (void)_addUserScriptToGroup:(NSString *)groupName source:(NSString *)source url:(NSURL *)url worldID:(unsigned)worldID + whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist injectionTime:(WebUserScriptInjectionTime)injectionTime +{ + String group(groupName); + if (group.isEmpty() || worldID == UINT_MAX) + return; + + PageGroup* pageGroup = PageGroup::pageGroup(group); + if (!pageGroup) + return; + + pageGroup->addUserScript(source, url, toStringVector(whitelist), toStringVector(blacklist), worldID, + injectionTime == WebInjectAtDocumentStart ? InjectAtDocumentStart : InjectAtDocumentEnd); +} + ++ (void)_addUserStyleSheetToGroup:(NSString *)groupName source:(NSString *)source url:(NSURL *)url worldID:(unsigned)worldID + whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist +{ + String group(groupName); + if (group.isEmpty() || worldID == UINT_MAX) + return; + + PageGroup* pageGroup = PageGroup::pageGroup(group); + if (!pageGroup) + return; + + pageGroup->addUserStyleSheet(source, url, toStringVector(whitelist), toStringVector(blacklist), worldID); +} + ++ (void)_removeUserContentFromGroup:(NSString *)groupName url:(NSURL *)url worldID:(unsigned)worldID +{ + String group(groupName); + if (group.isEmpty()) + return; + + PageGroup* pageGroup = PageGroup::pageGroup(group); + if (!pageGroup) + return; + + pageGroup->removeUserContentWithURLForWorld(url, worldID); +} + ++ (void)_removeUserContentFromGroup:(NSString *)groupName worldID:(unsigned)worldID +{ + String group(groupName); + if (group.isEmpty()) + return; + + PageGroup* pageGroup = PageGroup::pageGroup(group); + if (!pageGroup) + return; + + pageGroup->removeUserContentForWorld(worldID); +} + ++ (void)_removeAllUserContentFromGroup:(NSString *)groupName +{ + String group(groupName); + if (group.isEmpty()) + return; + + PageGroup* pageGroup = PageGroup::pageGroup(group); + if (!pageGroup) + return; + + pageGroup->removeAllUserContent(); +} + +- (BOOL)cssAnimationsSuspended +{ + return _private->cssAnimationsSuspended; +} + +- (void)setCSSAnimationsSuspended:(BOOL)suspended +{ + if (suspended == _private->cssAnimationsSuspended) + return; + + _private->cssAnimationsSuspended = suspended; + + Frame* frame = core([self mainFrame]); + if (suspended) + frame->animation()->suspendAnimations(frame->document()); + else + frame->animation()->resumeAnimations(frame->document()); +} + @end @implementation _WebSafeForwarder @@ -3875,6 +4013,17 @@ done: { return _private->scriptDebugDelegate; } + +- (void)setHistoryDelegate:(id)delegate +{ + _private->historyDelegate = delegate; + [self _cacheHistoryDelegateImplementations]; +} + +- (id)historyDelegate +{ + return _private->historyDelegate; +} - (BOOL)shouldClose { @@ -5091,13 +5240,16 @@ static WebFrameView *containingFrameView(NSView *view) id documentView = [[[self selectedFrame] frameView] documentView]; if (![documentView conformsToProtocol:@protocol(WebDocumentText)]) return; - + NSString *selectedString = [(id )documentView selectedString]; - if ([selectedString length] == 0) { + if (![selectedString length]) return; - } +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:selectedString]; +#else (void)HISearchWindowShow((CFStringRef)selectedString, kNilOptions); +#endif } #if USE(ACCELERATED_COMPOSITING) @@ -5469,6 +5621,45 @@ static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActi #endif +#if ENABLE(VIDEO) + +- (void)_enterFullscreenForNode:(WebCore::Node*)node +{ + ASSERT(node->hasTagName(WebCore::HTMLNames::videoTag)); + HTMLMediaElement* videoElement = static_cast(node); + + if (_private->fullscreenController) { + if ([_private->fullscreenController mediaElement] == videoElement) { + // The backend may just warn us that the underlaying plaftormMovie() + // has changed. Just force an update. + [_private->fullscreenController setMediaElement:videoElement]; + return; // No more to do. + } + + // First exit Fullscreen for the old mediaElement. + [_private->fullscreenController mediaElement]->exitFullscreen(); + // This previous call has to trigger _exitFullscreen, + // which has to clear _private->fullscreenController. + ASSERT(!_private->fullscreenController); + } + if (!_private->fullscreenController) { + _private->fullscreenController = [[WebVideoFullscreenController alloc] init]; + [_private->fullscreenController setMediaElement:videoElement]; + [_private->fullscreenController enterFullscreen:[[self window] screen]]; + } + else + [_private->fullscreenController setMediaElement:videoElement]; +} + +- (void)_exitFullscreen +{ + [_private->fullscreenController exitFullscreen]; + [_private->fullscreenController release]; + _private->fullscreenController = nil; +} + +#endif + @end #ifdef BUILDING_ON_LEOPARD diff --git a/WebKit/mac/WebView/WebViewData.h b/WebKit/mac/WebView/WebViewData.h index 91d83a7..6ec94a7 100644 --- a/WebKit/mac/WebView/WebViewData.h +++ b/WebKit/mac/WebView/WebViewData.h @@ -43,6 +43,9 @@ namespace WebCore { @class WebPreferences; @class WebTextCompletionController; @protocol WebFormDelegate; +#if ENABLE(VIDEO) +@class WebVideoFullscreenController; +#endif extern BOOL applicationIsTerminating; extern int pluginDatabaseClientCount; @@ -64,6 +67,7 @@ extern int pluginDatabaseClientCount; id editingDelegate; id editingDelegateForwarder; id scriptDebugDelegate; + id historyDelegate; WebInspector *inspector; WebNodeHighlight *currentNodeHighlight; @@ -86,6 +90,7 @@ extern int pluginDatabaseClientCount; WebResourceDelegateImplementationCache resourceLoadDelegateImplementations; WebFrameLoadDelegateImplementationCache frameLoadDelegateImplementations; WebScriptDebugDelegateImplementationCache scriptDebugDelegateImplementations; + WebHistoryDelegateImplementationCache historyDelegateImplementations; void *observationInfo; @@ -100,6 +105,7 @@ extern int pluginDatabaseClientCount; BOOL hoverFeedbackSuspended; BOOL usesPageCache; BOOL catchesDelegateExceptions; + BOOL cssAnimationsSuspended; NSColor *backgroundColor; @@ -157,5 +163,8 @@ extern int pluginDatabaseClientCount; NSEvent *autoscrollTriggerEvent; CFRunLoopTimerRef updateMouseoverTimer; +#if ENABLE(VIDEO) + WebVideoFullscreenController *fullscreenController; +#endif } @end diff --git a/WebKit/mac/WebView/WebViewData.mm b/WebKit/mac/WebView/WebViewData.mm index 48e7f6c..835f46e 100644 --- a/WebKit/mac/WebView/WebViewData.mm +++ b/WebKit/mac/WebView/WebViewData.mm @@ -57,6 +57,7 @@ int pluginDatabaseClientCount = 0; allowsUndo = YES; usesPageCache = YES; shouldUpdateWhileOffscreen = YES; + cssAnimationsSuspended = NO; zoomMultiplier = 1; @@ -80,6 +81,7 @@ int pluginDatabaseClientCount = 0; ASSERT(applicationIsTerminating || !page); ASSERT(applicationIsTerminating || !preferences); ASSERT(!insertionPasteboard); + ASSERT(!fullscreenController); [applicationNameForUserAgent release]; [backgroundColor release]; @@ -99,6 +101,7 @@ int pluginDatabaseClientCount = 0; { ASSERT_MAIN_THREAD(); ASSERT(!insertionPasteboard); + ASSERT(!fullscreenController); [super finalize]; } diff --git a/WebKit/mac/WebView/WebViewInternal.h b/WebKit/mac/WebView/WebViewInternal.h index b8266c5..521aeee 100644 --- a/WebKit/mac/WebView/WebViewInternal.h +++ b/WebKit/mac/WebView/WebViewInternal.h @@ -41,6 +41,7 @@ namespace WebCore { class KURL; class KeyboardEvent; class Page; + class Node; } #endif @@ -110,10 +111,6 @@ namespace WebCore { - (id)_policyDelegateForwarder; - (void)_pushPerformingProgrammaticFocus; - (void)_popPerformingProgrammaticFocus; -- (void)_incrementProgressForIdentifier:(id)identifier response:(NSURLResponse *)response; -- (void)_incrementProgressForIdentifier:(id)identifier length:(int)length; -- (void)_completeProgressForIdentifier:(id)identifer; -- (void)_progressStarted:(WebFrame *)frame; - (void)_didStartProvisionalLoadForFrame:(WebFrame *)frame; + (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; - (BOOL)_viewClass:(Class *)vClass andRepresentationClass:(Class *)rClass forMIMEType:(NSString *)MIMEType; @@ -138,7 +135,6 @@ namespace WebCore { - (void)_didChangeValueForKey:(NSString *)key; - (WebBasePluginPackage *)_pluginForMIMEType:(NSString *)MIMEType; - (WebBasePluginPackage *)_pluginForExtension:(NSString *)extension; -- (BOOL)_isMIMETypeRegisteredAsPlugin:(NSString *)MIMEType; - (void)setCurrentNodeHighlight:(WebNodeHighlight *)nodeHighlight; - (WebNodeHighlight *)currentNodeHighlight; @@ -168,4 +164,9 @@ namespace WebCore { - (void)_setInsertionPasteboard:(NSPasteboard *)pasteboard; +#if ENABLE(VIDEO) && defined(__cplusplus) +- (void)_enterFullscreenForNode:(WebCore::Node*)node; +- (void)_exitFullscreen; +#endif + @end diff --git a/WebKit/mac/WebView/WebViewPrivate.h b/WebKit/mac/WebView/WebViewPrivate.h index 362b2e6..fa5d28c 100644 --- a/WebKit/mac/WebView/WebViewPrivate.h +++ b/WebKit/mac/WebView/WebViewPrivate.h @@ -76,6 +76,11 @@ typedef enum { } WebDashboardBehavior; #endif +typedef enum { + WebInjectAtDocumentStart, + WebInjectAtDocumentEnd, +} WebUserScriptInjectionTime; + @interface WebController : NSTreeController { IBOutlet WebView *webView; } @@ -134,6 +139,20 @@ typedef enum { */ - (id)scriptDebugDelegate; +/*! + @method setHistoryDelegate: + @abstract Set the WebView's WebHistoryDelegate delegate. + @param delegate The WebHistoryDelegate to set as the delegate. +*/ +- (void)setHistoryDelegate:(id)delegate; + +/*! + @method historyDelegate + @abstract Return the WebView's WebHistoryDelegate delegate. + @result The WebView's WebHistoryDelegate delegate. +*/ +- (id)historyDelegate; + - (BOOL)shouldClose; /*! @@ -443,6 +462,35 @@ Could be worth adding to the API. // Which pasteboard text is coming from in editing delegate methods such as shouldInsertNode. - (NSPasteboard *)_insertionPasteboard; +// Whitelists access from an origin (sourceOrigin) to a set of one or more origins described by the parameters: +// - destinationProtocol: The protocol to grant access to. +// - destinationHost: The host to grant access to. +// - allowDestinationSubdomains: If host is a domain, setting this to YES will whitelist host and all its subdomains, recursively. ++ (void)_whiteListAccessFromOrigin:(NSString *)sourceOrigin destinationProtocol:(NSString *)destinationProtocol destinationHost:(NSString *)destinationHost allowDestinationSubdomains:(BOOL)allowDestinationSubdomains; + +// Removes all white list entries created with _whiteListAccessFromOrigin. ++ (void)_resetOriginAccessWhiteLists; + ++ (void)_addUserScriptToGroup:(NSString *)groupName source:(NSString *)source url:(NSURL *)url worldID:(unsigned)worldID whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist injectionTime:(WebUserScriptInjectionTime)injectionTime; ++ (void)_addUserStyleSheetToGroup:(NSString *)groupName source:(NSString *)source url:(NSURL *)url worldID:(unsigned)worldID whitelist:(NSArray *)whitelist blacklist:(NSArray *)blacklist; ++ (void)_removeUserContentFromGroup:(NSString *)groupName url:(NSURL *)url worldID:(unsigned)worldID; ++ (void)_removeUserContentFromGroup:(NSString *)groupName worldID:(unsigned)worldID; ++ (void)_removeAllUserContentFromGroup:(NSString *)groupName; + +/*! + @method cssAnimationsSuspended + @abstract Returns whether or not CSS Animations are suspended. + @result YES if CSS Animations are suspended. +*/ +- (BOOL)cssAnimationsSuspended; + +/*! + @method setCSSAnimationsSuspended + @param paused YES to suspend animations, NO to resume animations. + @discussion Suspends or resumes all running animations and transitions in the page. +*/ +- (void)setCSSAnimationsSuspended:(BOOL)suspended; + @end @interface WebView (WebViewPrintingPrivate) diff --git a/WebKit/mac/WebView/WebWindowAnimation.h b/WebKit/mac/WebView/WebWindowAnimation.h new file mode 100644 index 0000000..c73dcce --- /dev/null +++ b/WebKit/mac/WebView/WebWindowAnimation.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +@interface WebWindowScaleAnimation : NSAnimation { +@private + NSRect _initialFrame, _finalFrame, _realFrame; + NSWindow *_window; // (assign) + NSAnimation *_subAnimation; // (retain) + NSTimeInterval _hintedDuration; +} +- (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame; + +- (void)setSubAnimation:(NSAnimation *)animation; + +- (NSRect)currentFrame; + +// Be sure to call setWindow:nil to clear the weak link _window when appropriate +- (void)setWindow:(NSWindow *)window; +@end + + +@interface WebWindowFadeAnimation : NSAnimation { +@private + CGFloat _initialAlpha, _finalAlpha; + NSWindow *_window; // (retain) + BOOL _isStopped; + +} +- (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha; + +- (CGFloat)currentAlpha; + +// Be sure to call setWindow:nil to clear the weak link _window when appropriate +- (void)setWindow:(NSWindow *)window; +@end diff --git a/WebKit/mac/WebView/WebWindowAnimation.m b/WebKit/mac/WebView/WebWindowAnimation.m new file mode 100644 index 0000000..3ab64bf --- /dev/null +++ b/WebKit/mac/WebView/WebWindowAnimation.m @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "WebWindowAnimation.h" +#import "WebKitSystemInterface.h" +#import + +static const CGFloat slowMotionFactor = 10.; + +static NSTimeInterval WebWindowAnimationDurationFromDuration(NSTimeInterval duration) +{ + return ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) ? duration * slowMotionFactor : duration; +} + +static NSRect scaledRect(NSRect _initialFrame, NSRect _finalFrame, double factor) +{ + NSRect currentRect = _initialFrame; + currentRect.origin.x += (NSMinX(_finalFrame) - NSMinX(_initialFrame)) * factor; + currentRect.origin.y += (NSMinY(_finalFrame) - NSMinY(_initialFrame)) * factor; + currentRect.size.width += (NSWidth(_finalFrame) - NSWidth(_initialFrame)) * factor; + currentRect.size.height += (NSHeight(_finalFrame) - NSHeight(_initialFrame)) * factor; + return currentRect; +} + +static CGFloat squaredDistance(NSPoint point1, NSPoint point2) +{ + CGFloat deltaX = point1.x - point2.x; + CGFloat deltaY = point1.y - point2.y; + return deltaX * deltaX + deltaY * deltaY; +} + +@implementation WebWindowScaleAnimation + +- (id)init +{ + self = [super init]; + if (!self) + return nil; +#ifndef BUILDING_ON_TIGER + [self setAnimationBlockingMode:NSAnimationNonblockingThreaded]; +#endif + [self setFrameRate:60.]; + return self; +} + +- (id)initWithHintedDuration:(NSTimeInterval)duration window:(NSWindow *)window initalFrame:(NSRect)initialFrame finalFrame:(NSRect)finalFrame +{ + self = [self init]; + if (!self) + return nil; + _hintedDuration = duration; + _window = window; + _initialFrame = initialFrame; + _finalFrame = finalFrame; + _realFrame = [window frame]; + return self; +} + +- (void) dealloc +{ + [_window release]; + [_subAnimation release]; + [super dealloc]; +} + +- (void)setDuration:(NSTimeInterval)duration +{ + [super setDuration:WebWindowAnimationDurationFromDuration(duration)]; +} + +- (void)setWindow:(NSWindow *)window +{ + _window = window; +} + +- (float)currentValue +{ + return 0.5 - 0.5 * cos(M_PI * (1 - [self currentProgress])); +} + +- (NSRect)currentFrame +{ + return scaledRect(_finalFrame, _initialFrame, [self currentValue]); +} + +- (void)setCurrentProgress:(NSAnimationProgress)progress +{ + if (!_window) + return; + + [super setCurrentProgress:progress]; + + NSRect currentRect = [self currentFrame]; +#ifndef BUILDING_ON_TIGER + WKWindowSetScaledFrame(_window, currentRect, _realFrame); +#else + [_window setFrame:currentRect display:YES]; +#endif + [_subAnimation setCurrentProgress:progress]; +} + +- (void)setSubAnimation:(NSAnimation *)animation +{ + id oldAnimation = _subAnimation; + _subAnimation = [animation retain]; + [oldAnimation release]; +} + +- (NSTimeInterval)additionalDurationNeededToReachFinalFrame +{ + static const CGFloat maxAdditionalDuration = 1.0; + static const CGFloat speedFactor = 0.0001; + + CGFloat maxDist = squaredDistance(_initialFrame.origin, _finalFrame.origin); + CGFloat dist; + + dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMinY(_finalFrame))); + if (dist > maxDist) + maxDist = dist; + + dist = squaredDistance(NSMakePoint(NSMaxX(_initialFrame), NSMaxY(_initialFrame)), NSMakePoint(NSMaxX(_finalFrame), NSMaxY(_finalFrame))); + if (dist > maxDist) + maxDist = dist; + + dist = squaredDistance(NSMakePoint(NSMinX(_initialFrame), NSMinY(_initialFrame)), NSMakePoint(NSMinX(_finalFrame), NSMinY(_finalFrame))); + if (dist > maxDist) + maxDist = dist; + + return MIN(sqrt(maxDist) * speedFactor, maxAdditionalDuration); +} + +- (void)startAnimation +{ + // Compute extra time + if (_hintedDuration) + [self setDuration:_hintedDuration + [self additionalDurationNeededToReachFinalFrame]]; + [super startAnimation]; +} + +- (void)stopAnimation +{ + _window = nil; + [super stopAnimation]; + [_subAnimation stopAnimation]; +} + +@end + +@implementation WebWindowFadeAnimation + +- (id)init +{ + self = [super init]; + if (!self) + return nil; +#ifndef BUILDING_ON_TIGER + [self setAnimationBlockingMode:NSAnimationNonblockingThreaded]; +#endif + [self setFrameRate:60]; + [self setAnimationCurve:NSAnimationEaseInOut]; + return self; +} + +- (id)initWithDuration:(NSTimeInterval)duration window:(NSWindow *)window initialAlpha:(CGFloat)initialAlpha finalAlpha:(CGFloat)finalAlpha +{ + self = [self init]; + if (!self) + return nil; + _window = window; + _initialAlpha = initialAlpha; + _finalAlpha = finalAlpha; + return self; +} + +- (void)setDuration:(NSTimeInterval)duration +{ + [super setDuration:WebWindowAnimationDurationFromDuration(duration)]; +} + +- (CGFloat)currentAlpha +{ + return MAX(0.0, MIN(1.0, _initialAlpha + [self currentValue] * (_finalAlpha - _initialAlpha))); +} + +- (void)setCurrentProgress:(NSAnimationProgress)progress +{ + if (_isStopped) + return; + + ASSERT(_window); + [super setCurrentProgress:progress]; + +#ifndef BUILDING_ON_TIGER + WKWindowSetAlpha(_window, [self currentAlpha]); +#else + [_window setAlphaValue:[self currentAlpha]]; +#endif +} + +- (void)setWindow:(NSWindow*)window +{ + _window = window; +} + +- (void)stopAnimation +{ + // This is relevant when we are a sub animation of a scale animation. + // In this case we are hosted in the animated thread of the parent + // and even after [super stopAnimation], the parent might call + // setCurrrentProgress. + _isStopped = YES; + + [super stopAnimation]; +} + +@end + -- cgit v1.1