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