Home | History | Annotate | Download | only in cf
      1 /*
      2  * Copyright (C) 2009 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  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "HistoryPropertyList.h"
     28 
     29 #include "HistoryItem.h"
     30 #include <wtf/StringExtras.h>
     31 
     32 namespace WebCore {
     33 
     34 static const int currentFileVersion = 1;
     35 
     36 HistoryPropertyListWriter::HistoryPropertyListWriter()
     37     : m_dailyVisitCountsKey("D")
     38     , m_displayTitleKey("displayTitle")
     39     , m_lastVisitWasFailureKey("lastVisitWasFailure")
     40     , m_lastVisitWasHTTPNonGetKey("lastVisitWasHTTPNonGet")
     41     , m_lastVisitedDateKey("lastVisitedDate")
     42     , m_redirectURLsKey("redirectURLs")
     43     , m_titleKey("title")
     44     , m_urlKey("")
     45     , m_visitCountKey("visitCount")
     46     , m_weeklyVisitCountsKey("W")
     47     , m_buffer(0)
     48 {
     49 }
     50 
     51 UInt8* HistoryPropertyListWriter::buffer(size_t size)
     52 {
     53     ASSERT(!m_buffer);
     54     m_buffer = static_cast<UInt8*>(CFAllocatorAllocate(0, size, 0));
     55     m_bufferSize = size;
     56     return m_buffer;
     57 }
     58 
     59 RetainPtr<CFDataRef> HistoryPropertyListWriter::releaseData()
     60 {
     61     UInt8* buffer = m_buffer;
     62     if (!buffer)
     63         return 0;
     64     m_buffer = 0;
     65     RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, buffer, m_bufferSize, 0));
     66     if (!data) {
     67         CFAllocatorDeallocate(0, buffer);
     68         return 0;
     69     }
     70     return data;
     71 }
     72 
     73 void HistoryPropertyListWriter::writeObjects(BinaryPropertyListObjectStream& stream)
     74 {
     75     size_t outerDictionaryStart = stream.writeDictionaryStart();
     76 
     77     stream.writeString("WebHistoryFileVersion");
     78     stream.writeString("WebHistoryDates");
     79 
     80     stream.writeInteger(currentFileVersion);
     81     size_t outerDateArrayStart = stream.writeArrayStart();
     82     writeHistoryItems(stream);
     83     stream.writeArrayEnd(outerDateArrayStart);
     84 
     85     stream.writeDictionaryEnd(outerDictionaryStart);
     86 }
     87 
     88 void HistoryPropertyListWriter::writeHistoryItem(BinaryPropertyListObjectStream& stream, HistoryItem* item)
     89 {
     90     size_t itemDictionaryStart = stream.writeDictionaryStart();
     91 
     92     const String& title = item->title();
     93     const String& displayTitle = item->alternateTitle();
     94     double lastVisitedDate = item->lastVisitedTime();
     95     int visitCount = item->visitCount();
     96     Vector<String>* redirectURLs = item->redirectURLs();
     97     const Vector<int>& dailyVisitCounts = item->dailyVisitCounts();
     98     const Vector<int>& weeklyVisitCounts = item->weeklyVisitCounts();
     99 
    100     // keys
    101     stream.writeString(m_urlKey);
    102     if (!title.isEmpty())
    103         stream.writeString(m_titleKey);
    104     if (!displayTitle.isEmpty())
    105         stream.writeString(m_displayTitleKey);
    106     if (lastVisitedDate)
    107         stream.writeString(m_lastVisitedDateKey);
    108     if (visitCount)
    109         stream.writeString(m_visitCountKey);
    110     if (item->lastVisitWasFailure())
    111         stream.writeString(m_lastVisitWasFailureKey);
    112     if (item->lastVisitWasHTTPNonGet())
    113         stream.writeString(m_lastVisitWasHTTPNonGetKey);
    114     if (redirectURLs)
    115         stream.writeString(m_redirectURLsKey);
    116     if (!dailyVisitCounts.isEmpty())
    117         stream.writeString(m_dailyVisitCountsKey);
    118     if (!weeklyVisitCounts.isEmpty())
    119         stream.writeString(m_weeklyVisitCountsKey);
    120 
    121     // values
    122     stream.writeUniqueString(item->urlString());
    123     if (!title.isEmpty())
    124         stream.writeString(title);
    125     if (!displayTitle.isEmpty())
    126         stream.writeString(displayTitle);
    127     if (lastVisitedDate) {
    128         char buffer[32];
    129         snprintf(buffer, sizeof(buffer), "%.1lf", lastVisitedDate);
    130         stream.writeUniqueString(buffer);
    131     }
    132     if (visitCount)
    133         stream.writeInteger(visitCount);
    134     if (item->lastVisitWasFailure())
    135         stream.writeBooleanTrue();
    136     if (item->lastVisitWasHTTPNonGet()) {
    137         ASSERT(item->urlString().startsWith("http:", false) || item->urlString().startsWith("https:", false));
    138         stream.writeBooleanTrue();
    139     }
    140     if (redirectURLs) {
    141         size_t redirectArrayStart = stream.writeArrayStart();
    142         size_t size = redirectURLs->size();
    143         ASSERT(size);
    144         for (size_t i = 0; i < size; ++i)
    145             stream.writeUniqueString(redirectURLs->at(i));
    146         stream.writeArrayEnd(redirectArrayStart);
    147     }
    148     if (size_t size = dailyVisitCounts.size())
    149         stream.writeIntegerArray(dailyVisitCounts.data(), size);
    150     if (size_t size = weeklyVisitCounts.size())
    151         stream.writeIntegerArray(weeklyVisitCounts.data(), size);
    152 
    153     stream.writeDictionaryEnd(itemDictionaryStart);
    154 }
    155 
    156 }
    157