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