WebBackForwardListProxy.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 "WebBackForwardListProxy.h" 28 29#include "DataReference.h" 30#include "EncoderAdapter.h" 31#include "WebCoreArgumentCoders.h" 32#include "WebPage.h" 33#include "WebPageProxyMessages.h" 34#include "WebProcess.h" 35#include "WebProcessProxyMessages.h" 36#include <WebCore/HistoryItem.h> 37#include <wtf/HashMap.h> 38 39using namespace WebCore; 40 41namespace WebKit { 42 43static const unsigned DefaultCapacity = 100; 44static const unsigned NoCurrentItemIndex = UINT_MAX; 45 46// FIXME <rdar://problem/8819268>: This leaks all HistoryItems that go into these maps. 47// We need to clear up the life time of these objects. 48 49typedef HashMap<uint64_t, RefPtr<HistoryItem> > IDToHistoryItemMap; 50typedef HashMap<RefPtr<HistoryItem>, uint64_t> HistoryItemToIDMap; 51 52static IDToHistoryItemMap& idToHistoryItemMap() 53{ 54 static IDToHistoryItemMap map; 55 return map; 56} 57 58static HistoryItemToIDMap& historyItemToIDMap() 59{ 60 static HistoryItemToIDMap map; 61 return map; 62} 63 64static uint64_t uniqueHistoryItemID = 1; 65 66static uint64_t generateHistoryItemID() 67{ 68 // These IDs exist in the WebProcess for items created by the WebProcess. 69 // The IDs generated here need to never collide with the IDs created in WebBackForwardList in the UIProcess. 70 // We accomplish this by starting from 3, and only ever using odd ids. 71 uniqueHistoryItemID += 2; 72 return uniqueHistoryItemID; 73} 74 75void WebBackForwardListProxy::setHighestItemIDFromUIProcess(uint64_t itemID) 76{ 77 if (itemID <= uniqueHistoryItemID) 78 return; 79 80 if (itemID % 2) 81 uniqueHistoryItemID = itemID; 82 else 83 uniqueHistoryItemID = itemID + 1; 84} 85 86static void updateBackForwardItem(uint64_t itemID, HistoryItem* item) 87{ 88 EncoderAdapter encoder; 89 item->encodeBackForwardTree(encoder); 90 91 WebProcess::shared().connection()->send(Messages::WebProcessProxy::AddBackForwardItem(itemID, 92 item->originalURLString(), item->urlString(), item->title(), encoder.data()), 0); 93} 94 95void WebBackForwardListProxy::addItemFromUIProcess(uint64_t itemID, PassRefPtr<WebCore::HistoryItem> prpItem) 96{ 97 RefPtr<HistoryItem> item = prpItem; 98 99 // This item/itemID pair should not already exist in our maps. 100 ASSERT(!historyItemToIDMap().contains(item.get())); 101 ASSERT(!idToHistoryItemMap().contains(itemID)); 102 103 historyItemToIDMap().set(item, itemID); 104 idToHistoryItemMap().set(itemID, item); 105} 106 107static void WK2NotifyHistoryItemChanged(HistoryItem* item) 108{ 109 uint64_t itemID = historyItemToIDMap().get(item); 110 if (!itemID) 111 return; 112 113 updateBackForwardItem(itemID, item); 114} 115 116HistoryItem* WebBackForwardListProxy::itemForID(uint64_t itemID) 117{ 118 return idToHistoryItemMap().get(itemID).get(); 119} 120 121void WebBackForwardListProxy::removeItem(uint64_t itemID) 122{ 123 IDToHistoryItemMap::iterator it = idToHistoryItemMap().find(itemID); 124 if (it == idToHistoryItemMap().end()) 125 return; 126 historyItemToIDMap().remove(it->second); 127 idToHistoryItemMap().remove(it); 128} 129 130WebBackForwardListProxy::WebBackForwardListProxy(WebPage* page) 131 : m_page(page) 132{ 133 WebCore::notifyHistoryItemChanged = WK2NotifyHistoryItemChanged; 134} 135 136void WebBackForwardListProxy::addItem(PassRefPtr<HistoryItem> prpItem) 137{ 138 RefPtr<HistoryItem> item = prpItem; 139 140 ASSERT(!historyItemToIDMap().contains(item)); 141 142 if (!m_page) 143 return; 144 145 uint64_t itemID = generateHistoryItemID(); 146 147 ASSERT(!idToHistoryItemMap().contains(itemID)); 148 149 historyItemToIDMap().set(item, itemID); 150 idToHistoryItemMap().set(itemID, item); 151 152 updateBackForwardItem(itemID, item.get()); 153 m_page->send(Messages::WebPageProxy::BackForwardAddItem(itemID)); 154} 155 156void WebBackForwardListProxy::goToItem(HistoryItem* item) 157{ 158 if (!m_page) 159 return; 160 161 m_page->send(Messages::WebPageProxy::BackForwardGoToItem(historyItemToIDMap().get(item))); 162} 163 164HistoryItem* WebBackForwardListProxy::itemAtIndex(int itemIndex) 165{ 166 if (!m_page) 167 return 0; 168 169 uint64_t itemID = 0; 170 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::BackForwardItemAtIndex(itemIndex), Messages::WebPageProxy::BackForwardItemAtIndex::Reply(itemID), m_page->pageID())) 171 return 0; 172 173 if (!itemID) 174 return 0; 175 176 return idToHistoryItemMap().get(itemID).get(); 177} 178 179int WebBackForwardListProxy::backListCount() 180{ 181 if (!m_page) 182 return 0; 183 184 int backListCount = 0; 185 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::BackForwardBackListCount(), Messages::WebPageProxy::BackForwardBackListCount::Reply(backListCount), m_page->pageID())) 186 return 0; 187 188 return backListCount; 189} 190 191int WebBackForwardListProxy::forwardListCount() 192{ 193 if (!m_page) 194 return 0; 195 196 int forwardListCount = 0; 197 if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::BackForwardForwardListCount(), Messages::WebPageProxy::BackForwardForwardListCount::Reply(forwardListCount), m_page->pageID())) 198 return 0; 199 200 return forwardListCount; 201} 202 203void WebBackForwardListProxy::close() 204{ 205 m_page = 0; 206} 207 208bool WebBackForwardListProxy::isActive() 209{ 210 // FIXME: Should check the the list is enabled and has non-zero capacity. 211 return true; 212} 213 214void WebBackForwardListProxy::clear() 215{ 216 m_page->send(Messages::WebPageProxy::BackForwardClear()); 217} 218 219#if ENABLE(WML) 220void WebBackForwardListProxy::clearWMLPageHistory() 221{ 222} 223#endif 224 225} // namespace WebKit 226