webengine/osswebengine/WebKit/Misc/WebElementDictionary.mm
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  * 1.  Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer. 
       
    10  * 2.  Redistributions in binary form must reproduce the above copyright
       
    11  *     notice, this list of conditions and the following disclaimer in the
       
    12  *     documentation and/or other materials provided with the distribution. 
       
    13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    14  *     its contributors may be used to endorse or promote products derived
       
    15  *     from this software without specific prior written permission. 
       
    16  *
       
    17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    27  */
       
    28 
       
    29 #import "WebElementDictionary.h"
       
    30 
       
    31 #import "WebDOMOperations.h"
       
    32 #import "WebFrame.h"
       
    33 #import "WebFrameBridge.h"
       
    34 #import "WebFrameInternal.h"
       
    35 #import "WebKitLogging.h"
       
    36 #import "WebView.h"
       
    37 #import "WebViewPrivate.h"
       
    38 
       
    39 #import <WebKit/DOMCore.h>
       
    40 #import <WebKit/DOMExtensions.h>
       
    41 #import <WebCore/Frame.h>
       
    42 #import <WebCore/HitTestResult.h>
       
    43 #import <WebCore/Image.h>
       
    44 #import <WebCore/KURL.h>
       
    45 #import <WebCore/WebCoreObjCExtras.h>
       
    46 
       
    47 using namespace WebCore;
       
    48 
       
    49 static CFMutableDictionaryRef lookupTable = NULL;
       
    50 
       
    51 static void addLookupKey(NSString *key, SEL selector)
       
    52 {
       
    53     CFDictionaryAddValue(lookupTable, key, selector);
       
    54 }
       
    55 
       
    56 static void cacheValueForKey(const void *key, const void *value, void *self)
       
    57 {
       
    58     // calling objectForKey will cache the value in our _cache dictionary
       
    59     [(WebElementDictionary *)self objectForKey:(NSString *)key];
       
    60 }
       
    61 
       
    62 @implementation WebElementDictionary
       
    63 
       
    64 #ifndef BUILDING_ON_TIGER
       
    65 + (void)initialize
       
    66 {
       
    67     WebCoreObjCFinalizeOnMainThread(self);
       
    68 }
       
    69 #endif
       
    70 
       
    71 + (void)initializeLookupTable
       
    72 {
       
    73     if (lookupTable)
       
    74         return;
       
    75 
       
    76     lookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);
       
    77 
       
    78     addLookupKey(WebElementDOMNodeKey, @selector(_domNode));
       
    79     addLookupKey(WebElementFrameKey, @selector(_webFrame));
       
    80     addLookupKey(WebElementImageAltStringKey, @selector(_altDisplayString));
       
    81     addLookupKey(WebElementImageKey, @selector(_image));
       
    82     addLookupKey(WebElementImageRectKey, @selector(_imageRect));
       
    83     addLookupKey(WebElementImageURLKey, @selector(_absoluteImageURL));
       
    84     addLookupKey(WebElementIsSelectedKey, @selector(_isSelected));
       
    85     addLookupKey(WebElementSpellingToolTipKey, @selector(_spellingToolTip));
       
    86     addLookupKey(WebElementTitleKey, @selector(_title));
       
    87     addLookupKey(WebElementLinkURLKey, @selector(_absoluteLinkURL));
       
    88     addLookupKey(WebElementLinkTargetFrameKey, @selector(_targetWebFrame));
       
    89     addLookupKey(WebElementLinkTitleKey, @selector(_titleDisplayString));
       
    90     addLookupKey(WebElementLinkLabelKey, @selector(_textContent));
       
    91     addLookupKey(WebElementLinkIsLiveKey, @selector(_isLiveLink));
       
    92     addLookupKey(WebElementIsContentEditableKey, @selector(_isContentEditable));
       
    93 }
       
    94 
       
    95 - (id)initWithHitTestResult:(const HitTestResult&)result
       
    96 {
       
    97     [[self class] initializeLookupTable];
       
    98     [super init];
       
    99     _result = new HitTestResult(result);
       
   100     return self;
       
   101 }
       
   102 
       
   103 - (void)dealloc
       
   104 {
       
   105     delete _result;
       
   106     [_cache release];
       
   107     [_nilValues release];
       
   108     [super dealloc];
       
   109 }
       
   110 
       
   111 - (void)finalize
       
   112 {
       
   113     ASSERT_MAIN_THREAD();
       
   114     delete _result;
       
   115     [super finalize];
       
   116 }
       
   117 
       
   118 - (void)_fillCache
       
   119 {
       
   120     CFDictionaryApplyFunction(lookupTable, cacheValueForKey, self);
       
   121     _cacheComplete = YES;
       
   122 }
       
   123 
       
   124 - (unsigned)count
       
   125 {
       
   126     if (!_cacheComplete)
       
   127         [self _fillCache];
       
   128     return [_cache count];
       
   129 }
       
   130 
       
   131 - (NSEnumerator *)keyEnumerator
       
   132 {
       
   133     if (!_cacheComplete)
       
   134         [self _fillCache];
       
   135     return [_cache keyEnumerator];
       
   136 }
       
   137 
       
   138 - (id)objectForKey:(id)key
       
   139 {
       
   140     id value = [_cache objectForKey:key];
       
   141     if (value || _cacheComplete || [_nilValues containsObject:key])
       
   142         return value;
       
   143 
       
   144     SEL selector = (SEL)CFDictionaryGetValue(lookupTable, key);
       
   145     if (!selector)
       
   146         return nil;
       
   147     value = [self performSelector:selector];
       
   148 
       
   149     unsigned lookupTableCount = CFDictionaryGetCount(lookupTable);
       
   150     if (value) {
       
   151         if (!_cache)
       
   152             _cache = [[NSMutableDictionary alloc] initWithCapacity:lookupTableCount];
       
   153         [_cache setObject:value forKey:key];
       
   154     } else {
       
   155         if (!_nilValues)
       
   156             _nilValues = [[NSMutableSet alloc] initWithCapacity:lookupTableCount];
       
   157         [_nilValues addObject:key];
       
   158     }
       
   159 
       
   160     _cacheComplete = ([_cache count] + [_nilValues count]) == lookupTableCount;
       
   161 
       
   162     return value;
       
   163 }
       
   164 
       
   165 - (DOMNode *)_domNode
       
   166 {
       
   167     return kit(_result->innerNonSharedNode());
       
   168 }
       
   169 
       
   170 - (WebFrame *)_webFrame
       
   171 {
       
   172     return [[[self _domNode] ownerDocument] webFrame];
       
   173 }
       
   174 
       
   175 // String's NSString* operator converts null Strings to empty NSStrings for compatibility
       
   176 // with AppKit. We need to work around that here.
       
   177 static NSString* NSStringOrNil(String coreString)
       
   178 {
       
   179     if (coreString.isNull())
       
   180         return nil;
       
   181     return coreString;
       
   182 }
       
   183 
       
   184 - (NSString *)_altDisplayString
       
   185 {
       
   186     return NSStringOrNil(_result->altDisplayString());
       
   187 }
       
   188 
       
   189 - (NSString *)_spellingToolTip
       
   190 {
       
   191     return NSStringOrNil(_result->spellingToolTip());
       
   192 }
       
   193 
       
   194 - (NSImage *)_image
       
   195 {
       
   196     Image* image = _result->image();
       
   197     return image ? image->getNSImage() : nil;
       
   198 }
       
   199 
       
   200 - (NSValue *)_imageRect
       
   201 {
       
   202     IntRect rect = _result->imageRect();
       
   203     return rect.isEmpty() ? nil : [NSValue valueWithRect:rect];
       
   204 }
       
   205 
       
   206 - (NSURL *)_absoluteImageURL
       
   207 {
       
   208     return _result->absoluteImageURL().getNSURL();
       
   209 }
       
   210 
       
   211 - (NSNumber *)_isSelected
       
   212 {
       
   213     return [NSNumber numberWithBool:_result->isSelected()];
       
   214 }
       
   215 
       
   216 - (NSString *)_title
       
   217 {
       
   218     return NSStringOrNil(_result->title());
       
   219 }
       
   220 
       
   221 - (NSURL *)_absoluteLinkURL
       
   222 {
       
   223     return _result->absoluteLinkURL().getNSURL();
       
   224 }
       
   225 
       
   226 - (WebFrame *)_targetWebFrame
       
   227 {
       
   228     return kit(_result->targetFrame());
       
   229 }
       
   230 
       
   231 - (NSString *)_titleDisplayString
       
   232 {
       
   233     return NSStringOrNil(_result->titleDisplayString());
       
   234 }
       
   235 
       
   236 - (NSString *)_textContent
       
   237 {
       
   238     return NSStringOrNil(_result->textContent());
       
   239 }
       
   240 
       
   241 - (NSNumber *)_isLiveLink
       
   242 {
       
   243     return [NSNumber numberWithBool:_result->isLiveLink()];
       
   244 }
       
   245 
       
   246 - (NSNumber *)_isContentEditable
       
   247 {
       
   248     return [NSNumber numberWithBool:_result->isContentEditable()];
       
   249 }
       
   250 
       
   251 @end