WebPageProxyCF.cpp revision 2fc2651226baac27029e38c9d6ef883fa32084db
1/* 2 * Copyright (C) 2010, 2011 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. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "WebPageProxy.h" 28 29#include "DataReference.h" 30#include "Logging.h" 31#include "SessionState.h" 32#include "WebBackForwardList.h" 33#include "WebData.h" 34#include "WebPageMessages.h" 35#include "WebProcessProxy.h" 36 37#include <wtf/RetainPtr.h> 38#include <CoreFoundation/CFPropertyList.h> 39 40using namespace WebCore; 41 42namespace WebKit { 43 44DEFINE_STATIC_GETTER(CFStringRef, SessionHistoryKey, (CFSTR("SessionHistory"))); 45 46static const UInt32 CurrentSessionStateDataVersion = 2; 47 48PassRefPtr<WebData> WebPageProxy::sessionStateData(WebPageProxySessionStateFilterCallback filter, void* context) const 49{ 50 RetainPtr<CFDictionaryRef> sessionHistoryDictionary(AdoptCF, m_backForwardList->createCFDictionaryRepresentation(filter, context)); 51 52 // For now we're only serializing the back/forward list. If that object is null, then the entire sessionState can be null. 53 if (!sessionHistoryDictionary) 54 return 0; 55 56 const void* keys[1] = { SessionHistoryKey() }; 57 const void* values[1] = { sessionHistoryDictionary.get() }; 58 59 RetainPtr<CFDictionaryRef> stateDictionary(AdoptCF, CFDictionaryCreate(0, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 60 61 RetainPtr<CFWriteStreamRef> writeStream(AdoptCF, CFWriteStreamCreateWithAllocatedBuffers(0, 0)); 62 if (!writeStream) 63 return 0; 64 65 if (!CFWriteStreamOpen(writeStream.get())) 66 return 0; 67 68 if (!CFPropertyListWriteToStream(stateDictionary.get(), writeStream.get(), kCFPropertyListBinaryFormat_v1_0, 0)) 69 return 0; 70 71 RetainPtr<CFDataRef> stateCFData(AdoptCF, (CFDataRef)CFWriteStreamCopyProperty(writeStream.get(), kCFStreamPropertyDataWritten)); 72 73 CFIndex length = CFDataGetLength(stateCFData.get()); 74 Vector<unsigned char> stateVector(length + sizeof(UInt32)); 75 76 // Put the session state version number at the start of the buffer 77 stateVector.data()[0] = (CurrentSessionStateDataVersion & 0xFF000000) >> 24; 78 stateVector.data()[1] = (CurrentSessionStateDataVersion & 0x00FF0000) >> 16; 79 stateVector.data()[2] = (CurrentSessionStateDataVersion & 0x0000FF00) >> 8; 80 stateVector.data()[3] = (CurrentSessionStateDataVersion & 0x000000FF); 81 82 // Copy in the actual session state data 83 CFDataGetBytes(stateCFData.get(), CFRangeMake(0, length), stateVector.data() + sizeof(UInt32)); 84 85 return WebData::create(stateVector); 86} 87 88void WebPageProxy::restoreFromSessionStateData(WebData* webData) 89{ 90 if (!webData || webData->size() < sizeof(UInt32)) 91 return; 92 93 const unsigned char* buffer = webData->bytes(); 94 UInt32 versionHeader = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3]; 95 96 if (versionHeader != CurrentSessionStateDataVersion) { 97 LOG(SessionState, "Unrecognized version header for session state data - cannot restore"); 98 return; 99 } 100 101 RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, webData->bytes() + sizeof(UInt32), webData->size() - sizeof(UInt32))); 102 103 CFStringRef propertyListError = 0; 104 RetainPtr<CFPropertyListRef> propertyList(AdoptCF, CFPropertyListCreateFromXMLData(0, data.get(), kCFPropertyListImmutable, &propertyListError)); 105 if (propertyListError) { 106 CFRelease(propertyListError); 107 LOG(SessionState, "Could not read session state property list"); 108 return; 109 } 110 111 if (!propertyList) 112 return; 113 114 if (CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID()) { 115 LOG(SessionState, "SessionState property list is not a CFDictionaryRef (%i) - its CFTypeID is %i", (int)CFDictionaryGetTypeID(), (int)CFGetTypeID(propertyList.get())); 116 return; 117 } 118 119 CFTypeRef sessionHistoryRef = CFDictionaryGetValue(static_cast<CFDictionaryRef>(propertyList.get()), SessionHistoryKey()); 120 if (!sessionHistoryRef || CFGetTypeID(sessionHistoryRef) != CFDictionaryGetTypeID()) { 121 LOG(SessionState, "SessionState dictionary does not contain a SessionHistoryDictionary key, it is of the wrong type"); 122 return; 123 } 124 125 CFDictionaryRef sessionHistoryDictionary = static_cast<CFDictionaryRef>(sessionHistoryRef); 126 if (!m_backForwardList->restoreFromCFDictionaryRepresentation(sessionHistoryDictionary)) { 127 LOG(SessionState, "Failed to restore back/forward list from SessionHistoryDictionary"); 128 return; 129 } 130 131 const BackForwardListItemVector& entries = m_backForwardList->entries(); 132 size_t size = entries.size(); 133 for (size_t i = 0; i < size; ++i) 134 process()->registerNewWebBackForwardListItem(entries[i].get()); 135 136 SandboxExtension::Handle sandboxExtensionHandle; 137 if (WebBackForwardListItem* item = m_backForwardList->currentItem()) 138 initializeSandboxExtensionHandle(KURL(KURL(), item->url()), sandboxExtensionHandle); 139 140 process()->send(Messages::WebPage::RestoreSessionAndNavigateToCurrentItem(SessionState(m_backForwardList->entries(), m_backForwardList->currentIndex()), sandboxExtensionHandle), m_pageID); 141} 142 143} // namespace WebKit 144