diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKit/Misc/WebElementDictionary.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebKit/Misc/WebElementDictionary.mm Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,251 @@ +/* + * Copyright (C) 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 "WebElementDictionary.h" + +#import "WebDOMOperations.h" +#import "WebFrame.h" +#import "WebFrameBridge.h" +#import "WebFrameInternal.h" +#import "WebKitLogging.h" +#import "WebView.h" +#import "WebViewPrivate.h" + +#import +#import +#import +#import +#import +#import +#import + +using namespace WebCore; + +static CFMutableDictionaryRef lookupTable = NULL; + +static void addLookupKey(NSString *key, SEL selector) +{ + CFDictionaryAddValue(lookupTable, key, selector); +} + +static void cacheValueForKey(const void *key, const void *value, void *self) +{ + // calling objectForKey will cache the value in our _cache dictionary + [(WebElementDictionary *)self objectForKey:(NSString *)key]; +} + +@implementation WebElementDictionary + +#ifndef BUILDING_ON_TIGER ++ (void)initialize +{ + WebCoreObjCFinalizeOnMainThread(self); +} +#endif + ++ (void)initializeLookupTable +{ + if (lookupTable) + return; + + lookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL); + + addLookupKey(WebElementDOMNodeKey, @selector(_domNode)); + addLookupKey(WebElementFrameKey, @selector(_webFrame)); + addLookupKey(WebElementImageAltStringKey, @selector(_altDisplayString)); + addLookupKey(WebElementImageKey, @selector(_image)); + addLookupKey(WebElementImageRectKey, @selector(_imageRect)); + addLookupKey(WebElementImageURLKey, @selector(_absoluteImageURL)); + addLookupKey(WebElementIsSelectedKey, @selector(_isSelected)); + addLookupKey(WebElementSpellingToolTipKey, @selector(_spellingToolTip)); + addLookupKey(WebElementTitleKey, @selector(_title)); + addLookupKey(WebElementLinkURLKey, @selector(_absoluteLinkURL)); + addLookupKey(WebElementLinkTargetFrameKey, @selector(_targetWebFrame)); + addLookupKey(WebElementLinkTitleKey, @selector(_titleDisplayString)); + addLookupKey(WebElementLinkLabelKey, @selector(_textContent)); + addLookupKey(WebElementLinkIsLiveKey, @selector(_isLiveLink)); + addLookupKey(WebElementIsContentEditableKey, @selector(_isContentEditable)); +} + +- (id)initWithHitTestResult:(const HitTestResult&)result +{ + [[self class] initializeLookupTable]; + [super init]; + _result = new HitTestResult(result); + return self; +} + +- (void)dealloc +{ + delete _result; + [_cache release]; + [_nilValues release]; + [super dealloc]; +} + +- (void)finalize +{ + ASSERT_MAIN_THREAD(); + delete _result; + [super finalize]; +} + +- (void)_fillCache +{ + CFDictionaryApplyFunction(lookupTable, cacheValueForKey, self); + _cacheComplete = YES; +} + +- (unsigned)count +{ + if (!_cacheComplete) + [self _fillCache]; + return [_cache count]; +} + +- (NSEnumerator *)keyEnumerator +{ + if (!_cacheComplete) + [self _fillCache]; + return [_cache keyEnumerator]; +} + +- (id)objectForKey:(id)key +{ + id value = [_cache objectForKey:key]; + if (value || _cacheComplete || [_nilValues containsObject:key]) + return value; + + SEL selector = (SEL)CFDictionaryGetValue(lookupTable, key); + if (!selector) + return nil; + value = [self performSelector:selector]; + + unsigned lookupTableCount = CFDictionaryGetCount(lookupTable); + if (value) { + if (!_cache) + _cache = [[NSMutableDictionary alloc] initWithCapacity:lookupTableCount]; + [_cache setObject:value forKey:key]; + } else { + if (!_nilValues) + _nilValues = [[NSMutableSet alloc] initWithCapacity:lookupTableCount]; + [_nilValues addObject:key]; + } + + _cacheComplete = ([_cache count] + [_nilValues count]) == lookupTableCount; + + return value; +} + +- (DOMNode *)_domNode +{ + return kit(_result->innerNonSharedNode()); +} + +- (WebFrame *)_webFrame +{ + return [[[self _domNode] ownerDocument] webFrame]; +} + +// String's NSString* operator converts null Strings to empty NSStrings for compatibility +// with AppKit. We need to work around that here. +static NSString* NSStringOrNil(String coreString) +{ + if (coreString.isNull()) + return nil; + return coreString; +} + +- (NSString *)_altDisplayString +{ + return NSStringOrNil(_result->altDisplayString()); +} + +- (NSString *)_spellingToolTip +{ + return NSStringOrNil(_result->spellingToolTip()); +} + +- (NSImage *)_image +{ + Image* image = _result->image(); + return image ? image->getNSImage() : nil; +} + +- (NSValue *)_imageRect +{ + IntRect rect = _result->imageRect(); + return rect.isEmpty() ? nil : [NSValue valueWithRect:rect]; +} + +- (NSURL *)_absoluteImageURL +{ + return _result->absoluteImageURL().getNSURL(); +} + +- (NSNumber *)_isSelected +{ + return [NSNumber numberWithBool:_result->isSelected()]; +} + +- (NSString *)_title +{ + return NSStringOrNil(_result->title()); +} + +- (NSURL *)_absoluteLinkURL +{ + return _result->absoluteLinkURL().getNSURL(); +} + +- (WebFrame *)_targetWebFrame +{ + return kit(_result->targetFrame()); +} + +- (NSString *)_titleDisplayString +{ + return NSStringOrNil(_result->titleDisplayString()); +} + +- (NSString *)_textContent +{ + return NSStringOrNil(_result->textContent()); +} + +- (NSNumber *)_isLiveLink +{ + return [NSNumber numberWithBool:_result->isLiveLink()]; +} + +- (NSNumber *)_isContentEditable +{ + return [NSNumber numberWithBool:_result->isContentEditable()]; +} + +@end