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