Home | History | Annotate | Download | only in History
      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/RetainPtr.h>
     51 #import <wtf/StdLibExtras.h>
     52 #import <wtf/Threading.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 #ifndef BUILDING_ON_TIGER
    108     WebCoreObjCFinalizeOnMainThread(self);
    109 #endif
    110 }
    111 
    112 - (id)init
    113 {
    114     return [self initWithBackForwardList:BackForwardListImpl::create(0)];
    115 }
    116 
    117 - (void)dealloc
    118 {
    119     if (WebCoreObjCScheduleDeallocateOnMainThread([WebBackForwardList class], self))
    120         return;
    121 
    122     BackForwardListImpl* backForwardList = core(self);
    123     ASSERT(backForwardList);
    124     if (backForwardList) {
    125         ASSERT(backForwardList->closed());
    126         backForwardLists().remove(backForwardList);
    127         backForwardList->deref();
    128     }
    129 
    130     [super dealloc];
    131 }
    132 
    133 - (void)finalize
    134 {
    135     WebCoreThreadViolationCheckRoundOne();
    136     BackForwardListImpl* backForwardList = core(self);
    137     ASSERT(backForwardList);
    138     if (backForwardList) {
    139         ASSERT(backForwardList->closed());
    140         backForwardLists().remove(backForwardList);
    141         backForwardList->deref();
    142     }
    143 
    144     [super finalize];
    145 }
    146 
    147 - (void)_close
    148 {
    149     core(self)->close();
    150 }
    151 
    152 - (void)addItem:(WebHistoryItem *)entry
    153 {
    154     core(self)->addItem(core(entry));
    155 
    156     // Since the assumed contract with WebBackForwardList is that it retains its WebHistoryItems,
    157     // the following line prevents a whole class of problems where a history item will be created in
    158     // a function, added to the BFlist, then used in the rest of that function.
    159     [[entry retain] autorelease];
    160 }
    161 
    162 - (void)removeItem:(WebHistoryItem *)item
    163 {
    164     core(self)->removeItem(core(item));
    165 }
    166 
    167 - (BOOL)containsItem:(WebHistoryItem *)item
    168 {
    169     return core(self)->containsItem(core(item));
    170 }
    171 
    172 - (void)goBack
    173 {
    174     core(self)->goBack();
    175 }
    176 
    177 - (void)goForward
    178 {
    179     core(self)->goForward();
    180 }
    181 
    182 - (void)goToItem:(WebHistoryItem *)item
    183 {
    184     core(self)->goToItem(core(item));
    185 }
    186 
    187 - (WebHistoryItem *)backItem
    188 {
    189     return [[kit(core(self)->backItem()) retain] autorelease];
    190 }
    191 
    192 - (WebHistoryItem *)currentItem
    193 {
    194     return [[kit(core(self)->currentItem()) retain] autorelease];
    195 }
    196 
    197 - (WebHistoryItem *)forwardItem
    198 {
    199     return [[kit(core(self)->forwardItem()) retain] autorelease];
    200 }
    201 
    202 static NSArray* vectorToNSArray(HistoryItemVector& list)
    203 {
    204     unsigned size = list.size();
    205     NSMutableArray *result = [[[NSMutableArray alloc] initWithCapacity:size] autorelease];
    206     for (unsigned i = 0; i < size; ++i)
    207         [result addObject:kit(list[i].get())];
    208 
    209     return result;
    210 }
    211 
    212 static bool bumperCarBackForwardHackNeeded()
    213 {
    214     static bool hackNeeded = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.freeverse.bumpercar"] &&
    215         !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_BUMPERCAR_BACK_FORWARD_QUIRK);
    216 
    217     return hackNeeded;
    218 }
    219 
    220 - (NSArray *)backListWithLimit:(int)limit
    221 {
    222     HistoryItemVector list;
    223     core(self)->backListWithLimit(limit, list);
    224     NSArray *result = vectorToNSArray(list);
    225 
    226     if (bumperCarBackForwardHackNeeded()) {
    227         static NSArray *lastBackListArray = nil;
    228         [lastBackListArray release];
    229         lastBackListArray = [result retain];
    230     }
    231 
    232     return result;
    233 }
    234 
    235 - (NSArray *)forwardListWithLimit:(int)limit
    236 {
    237     HistoryItemVector list;
    238     core(self)->forwardListWithLimit(limit, list);
    239     NSArray *result = vectorToNSArray(list);
    240 
    241     if (bumperCarBackForwardHackNeeded()) {
    242         static NSArray *lastForwardListArray = nil;
    243         [lastForwardListArray release];
    244         lastForwardListArray = [result retain];
    245     }
    246 
    247     return result;
    248 }
    249 
    250 - (int)capacity
    251 {
    252     return core(self)->capacity();
    253 }
    254 
    255 - (void)setCapacity:(int)size
    256 {
    257     core(self)->setCapacity(size);
    258 }
    259 
    260 
    261 -(NSString *)description
    262 {
    263     NSMutableString *result;
    264 
    265     result = [NSMutableString stringWithCapacity:512];
    266 
    267     [result appendString:@"\n--------------------------------------------\n"];
    268     [result appendString:@"WebBackForwardList:\n"];
    269 
    270     BackForwardListImpl* backForwardList = core(self);
    271     HistoryItemVector& entries = backForwardList->entries();
    272 
    273     unsigned size = entries.size();
    274     for (unsigned i = 0; i < size; ++i) {
    275         if (entries[i] == backForwardList->currentItem()) {
    276             [result appendString:@" >>>"];
    277         } else {
    278             [result appendString:@"    "];
    279         }
    280         [result appendFormat:@"%2d) ", i];
    281         int currPos = [result length];
    282         [result appendString:[kit(entries[i].get()) description]];
    283 
    284         // shift all the contents over.  a bit slow, but this is for debugging
    285         NSRange replRange = {currPos, [result length]-currPos};
    286         [result replaceOccurrencesOfString:@"\n" withString:@"\n        " options:0 range:replRange];
    287 
    288         [result appendString:@"\n"];
    289     }
    290 
    291     [result appendString:@"\n--------------------------------------------\n"];
    292 
    293     return result;
    294 }
    295 
    296 - (void)setPageCacheSize:(NSUInteger)size
    297 {
    298     [kit(core(self)->page()) setUsesPageCache:size != 0];
    299 }
    300 
    301 - (NSUInteger)pageCacheSize
    302 {
    303     return [kit(core(self)->page()) usesPageCache] ? pageCache()->capacity() : 0;
    304 }
    305 
    306 - (int)backListCount
    307 {
    308     return core(self)->backListCount();
    309 }
    310 
    311 - (int)forwardListCount
    312 {
    313     return core(self)->forwardListCount();
    314 }
    315 
    316 - (WebHistoryItem *)itemAtIndex:(int)index
    317 {
    318     return [[kit(core(self)->itemAtIndex(index)) retain] autorelease];
    319 }
    320 
    321 @end
    322