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