1/* 2 * Copyright (C) 2005, 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 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 "WebBackForwardList.h" 30#import "WebBackForwardListInternal.h" 31 32#import "WebFrameInternal.h" 33#import "WebHistoryItemInternal.h" 34#import "WebHistoryItemPrivate.h" 35#import "WebKitLogging.h" 36#import "WebKitVersionChecks.h" 37#import "WebNSObjectExtras.h" 38#import "WebPreferencesPrivate.h" 39#import "WebTypesInternal.h" 40#import "WebViewPrivate.h" 41#import <WebCore/BackForwardList.h> 42#import <WebCore/HistoryItem.h> 43#import <WebCore/Page.h> 44#import <WebCore/PageCache.h> 45#import <WebCore/Settings.h> 46#import <WebCore/ThreadCheck.h> 47#import <WebCore/WebCoreObjCExtras.h> 48#import <runtime/InitializeThreading.h> 49#import <wtf/Assertions.h> 50#import <wtf/RetainPtr.h> 51#import <wtf/StdLibExtras.h> 52 53using namespace WebCore; 54 55typedef HashMap<BackForwardList*, WebBackForwardList*> BackForwardListMap; 56 57static BackForwardListMap& backForwardLists() 58{ 59 DEFINE_STATIC_LOCAL(BackForwardListMap, staticBackForwardLists, ()); 60 return staticBackForwardLists; 61} 62 63@implementation WebBackForwardList (WebBackForwardListInternal) 64 65BackForwardList* core(WebBackForwardList *webBackForwardList) 66{ 67 if (!webBackForwardList) 68 return 0; 69 70 return reinterpret_cast<BackForwardList*>(webBackForwardList->_private); 71} 72 73WebBackForwardList *kit(BackForwardList* backForwardList) 74{ 75 if (!backForwardList) 76 return nil; 77 78 if (WebBackForwardList *webBackForwardList = backForwardLists().get(backForwardList)) 79 return webBackForwardList; 80 81 return [[[WebBackForwardList alloc] initWithBackForwardList:backForwardList] autorelease]; 82} 83 84- (id)initWithBackForwardList:(PassRefPtr<BackForwardList>)backForwardList 85{ 86 WebCoreThreadViolationCheckRoundOne(); 87 self = [super init]; 88 if (!self) 89 return nil; 90 91 _private = reinterpret_cast<WebBackForwardListPrivate*>(backForwardList.releaseRef()); 92 backForwardLists().set(core(self), self); 93 return self; 94} 95 96@end 97 98@implementation WebBackForwardList 99 100+ (void)initialize 101{ 102 JSC::initializeThreading(); 103#ifndef BUILDING_ON_TIGER 104 WebCoreObjCFinalizeOnMainThread(self); 105#endif 106} 107 108- (id)init 109{ 110 return [self initWithBackForwardList:BackForwardList::create(0)]; 111} 112 113- (void)dealloc 114{ 115 if (WebCoreObjCScheduleDeallocateOnMainThread([WebBackForwardList class], self)) 116 return; 117 118 BackForwardList* backForwardList = core(self); 119 ASSERT(backForwardList); 120 if (backForwardList) { 121 ASSERT(backForwardList->closed()); 122 backForwardLists().remove(backForwardList); 123 backForwardList->deref(); 124 } 125 126 [super dealloc]; 127} 128 129- (void)finalize 130{ 131 WebCoreThreadViolationCheckRoundOne(); 132 BackForwardList* backForwardList = core(self); 133 ASSERT(backForwardList); 134 if (backForwardList) { 135 ASSERT(backForwardList->closed()); 136 backForwardLists().remove(backForwardList); 137 backForwardList->deref(); 138 } 139 140 [super finalize]; 141} 142 143- (void)_close 144{ 145 core(self)->close(); 146} 147 148- (void)addItem:(WebHistoryItem *)entry 149{ 150 core(self)->addItem(core(entry)); 151 152 // Since the assumed contract with WebBackForwardList is that it retains its WebHistoryItems, 153 // the following line prevents a whole class of problems where a history item will be created in 154 // a function, added to the BFlist, then used in the rest of that function. 155 [[entry retain] autorelease]; 156} 157 158- (void)removeItem:(WebHistoryItem *)item 159{ 160 core(self)->removeItem(core(item)); 161} 162 163- (BOOL)containsItem:(WebHistoryItem *)item 164{ 165 return core(self)->containsItem(core(item)); 166} 167 168- (void)goBack 169{ 170 core(self)->goBack(); 171} 172 173- (void)goForward 174{ 175 core(self)->goForward(); 176} 177 178- (void)goToItem:(WebHistoryItem *)item 179{ 180 core(self)->goToItem(core(item)); 181} 182 183- (WebHistoryItem *)backItem 184{ 185 return [[kit(core(self)->backItem()) retain] autorelease]; 186} 187 188- (WebHistoryItem *)currentItem 189{ 190 return [[kit(core(self)->currentItem()) retain] autorelease]; 191} 192 193- (WebHistoryItem *)forwardItem 194{ 195 return [[kit(core(self)->forwardItem()) retain] autorelease]; 196} 197 198static NSArray* vectorToNSArray(HistoryItemVector& list) 199{ 200 unsigned size = list.size(); 201 NSMutableArray *result = [[[NSMutableArray alloc] initWithCapacity:size] autorelease]; 202 for (unsigned i = 0; i < size; ++i) 203 [result addObject:kit(list[i].get())]; 204 205 return result; 206} 207 208static bool bumperCarBackForwardHackNeeded() 209{ 210 static bool hackNeeded = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.freeverse.bumpercar"] && 211 !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_BUMPERCAR_BACK_FORWARD_QUIRK); 212 213 return hackNeeded; 214} 215 216- (NSArray *)backListWithLimit:(int)limit 217{ 218 HistoryItemVector list; 219 core(self)->backListWithLimit(limit, list); 220 NSArray *result = vectorToNSArray(list); 221 222 if (bumperCarBackForwardHackNeeded()) { 223 static NSArray *lastBackListArray = nil; 224 [lastBackListArray release]; 225 lastBackListArray = [result retain]; 226 } 227 228 return result; 229} 230 231- (NSArray *)forwardListWithLimit:(int)limit 232{ 233 HistoryItemVector list; 234 core(self)->forwardListWithLimit(limit, list); 235 NSArray *result = vectorToNSArray(list); 236 237 if (bumperCarBackForwardHackNeeded()) { 238 static NSArray *lastForwardListArray = nil; 239 [lastForwardListArray release]; 240 lastForwardListArray = [result retain]; 241 } 242 243 return result; 244} 245 246- (int)capacity 247{ 248 return core(self)->capacity(); 249} 250 251- (void)setCapacity:(int)size 252{ 253 core(self)->setCapacity(size); 254} 255 256 257-(NSString *)description 258{ 259 NSMutableString *result; 260 261 result = [NSMutableString stringWithCapacity:512]; 262 263 [result appendString:@"\n--------------------------------------------\n"]; 264 [result appendString:@"WebBackForwardList:\n"]; 265 266 BackForwardList* backForwardList = core(self); 267 HistoryItemVector& entries = backForwardList->entries(); 268 269 unsigned size = entries.size(); 270 for (unsigned i = 0; i < size; ++i) { 271 if (entries[i] == backForwardList->currentItem()) { 272 [result appendString:@" >>>"]; 273 } else { 274 [result appendString:@" "]; 275 } 276 [result appendFormat:@"%2d) ", i]; 277 int currPos = [result length]; 278 [result appendString:[kit(entries[i].get()) description]]; 279 280 // shift all the contents over. a bit slow, but this is for debugging 281 NSRange replRange = {currPos, [result length]-currPos}; 282 [result replaceOccurrencesOfString:@"\n" withString:@"\n " options:0 range:replRange]; 283 284 [result appendString:@"\n"]; 285 } 286 287 [result appendString:@"\n--------------------------------------------\n"]; 288 289 return result; 290} 291 292- (void)setPageCacheSize:(NSUInteger)size 293{ 294 [kit(core(self)->page()) setUsesPageCache:size != 0]; 295} 296 297- (NSUInteger)pageCacheSize 298{ 299 return [kit(core(self)->page()) usesPageCache] ? pageCache()->capacity() : 0; 300} 301 302- (int)backListCount 303{ 304 return core(self)->backListCount(); 305} 306 307- (int)forwardListCount 308{ 309 return core(self)->forwardListCount(); 310} 311 312- (WebHistoryItem *)itemAtIndex:(int)index 313{ 314 return [[kit(core(self)->itemAtIndex(index)) retain] autorelease]; 315} 316 317@end 318