|
1 // -*- c-basic-offset: 4 -*- |
|
2 /* |
|
3 * Copyright (C) 2006 Apple Computer, Inc. |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Library General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Library General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Library General Public License |
|
16 * along with this library; see the file COPYING.LIB. If not, write to |
|
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
18 * Boston, MA 02110-1301, USA. |
|
19 */ |
|
20 |
|
21 #include "config.h" |
|
22 #include "Page.h" |
|
23 |
|
24 #include "Chrome.h" |
|
25 #include "ChromeClient.h" |
|
26 #include "ContextMenuClient.h" |
|
27 #include "ContextMenuController.h" |
|
28 #include "EditorClient.h" |
|
29 #include "DragController.h" |
|
30 #include "FocusController.h" |
|
31 #include "Frame.h" |
|
32 #include "FrameLoader.h" |
|
33 #include "FrameTree.h" |
|
34 #include "FrameView.h" |
|
35 #include "HistoryItem.h" |
|
36 #include "InspectorController.h" |
|
37 #include "Logging.h" |
|
38 #include "ProgressTracker.h" |
|
39 #include "RenderWidget.h" |
|
40 #include "SelectionController.h" |
|
41 #include "Settings.h" |
|
42 #include "StringHash.h" |
|
43 #include "Widget.h" |
|
44 #include <kjs/collector.h> |
|
45 #include <kjs/JSLock.h> |
|
46 #include <wtf/HashMap.h> |
|
47 |
|
48 using namespace KJS; |
|
49 |
|
50 namespace WebCore { |
|
51 |
|
52 static HashSet<Page*>* allPages; |
|
53 static HashMap<String, HashSet<Page*>*>* frameNamespaces; |
|
54 |
|
55 #ifndef NDEBUG |
|
56 WTFLogChannel LogWebCorePageLeaks = { 0x00000000, "", WTFLogChannelOn }; |
|
57 |
|
58 struct PageCounter { |
|
59 static int count; |
|
60 ~PageCounter() |
|
61 { |
|
62 if (count) |
|
63 LOG(WebCorePageLeaks, "LEAK: %d Page\n", count); |
|
64 } |
|
65 }; |
|
66 int PageCounter::count = 0; |
|
67 static PageCounter pageCounter; |
|
68 #endif |
|
69 |
|
70 Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient) |
|
71 : m_chrome(new Chrome(this, chromeClient)) |
|
72 , m_dragCaretController(new SelectionController(0, true)) |
|
73 , m_dragController(new DragController(this, dragClient)) |
|
74 , m_focusController(new FocusController(this)) |
|
75 , m_contextMenuController(new ContextMenuController(this, contextMenuClient)) |
|
76 , m_inspectorController(new InspectorController(this, inspectorClient)) |
|
77 , m_settings(new Settings(this)) |
|
78 , m_progress(new ProgressTracker) |
|
79 , m_backForwardList(new BackForwardList(this)) |
|
80 , m_editorClient(editorClient) |
|
81 , m_frameCount(0) |
|
82 , m_tabKeyCyclesThroughElements(true) |
|
83 , m_defersLoading(false) |
|
84 , m_inLowQualityInterpolationMode(false) |
|
85 , m_parentInspectorController(0) |
|
86 { |
|
87 if (!allPages) { |
|
88 allPages = new HashSet<Page*>; |
|
89 setFocusRingColorChangeFunction(setNeedsReapplyStyles); |
|
90 } |
|
91 |
|
92 ASSERT(!allPages->contains(this)); |
|
93 allPages->add(this); |
|
94 |
|
95 #ifndef NDEBUG |
|
96 ++PageCounter::count; |
|
97 #endif |
|
98 } |
|
99 |
|
100 Page::~Page() |
|
101 { |
|
102 m_mainFrame->setView(0); |
|
103 setGroupName(String()); |
|
104 allPages->remove(this); |
|
105 |
|
106 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) |
|
107 frame->pageDestroyed(); |
|
108 m_editorClient->pageDestroyed(); |
|
109 m_inspectorController->pageDestroyed(); |
|
110 |
|
111 m_backForwardList->close(); |
|
112 |
|
113 #ifndef NDEBUG |
|
114 --PageCounter::count; |
|
115 |
|
116 // Cancel keepAlive timers, to ensure we release all Frames before exiting. |
|
117 // It's safe to do this because we prohibit closing a Page while JavaScript |
|
118 // is executing. |
|
119 Frame::cancelAllKeepAlive(); |
|
120 #endif |
|
121 } |
|
122 |
|
123 void Page::setMainFrame(PassRefPtr<Frame> mainFrame) |
|
124 { |
|
125 ASSERT(!m_mainFrame); // Should only be called during initialization |
|
126 m_mainFrame = mainFrame; |
|
127 } |
|
128 |
|
129 BackForwardList* Page::backForwardList() |
|
130 { |
|
131 return m_backForwardList.get(); |
|
132 } |
|
133 |
|
134 bool Page::goBack() |
|
135 { |
|
136 HistoryItem* item = m_backForwardList->backItem(); |
|
137 |
|
138 if (item) { |
|
139 goToItem(item, FrameLoadTypeBack); |
|
140 return true; |
|
141 } |
|
142 return false; |
|
143 } |
|
144 |
|
145 bool Page::goForward() |
|
146 { |
|
147 HistoryItem* item = m_backForwardList->forwardItem(); |
|
148 |
|
149 if (item) { |
|
150 goToItem(item, FrameLoadTypeForward); |
|
151 return true; |
|
152 } |
|
153 return false; |
|
154 } |
|
155 |
|
156 void Page::goToItem(HistoryItem* item, FrameLoadType type) |
|
157 { |
|
158 // Abort any current load if we're going to a history item |
|
159 m_mainFrame->loader()->stopAllLoaders(); |
|
160 m_mainFrame->loader()->goToItem(item, type); |
|
161 } |
|
162 |
|
163 void Page::setGroupName(const String& name) |
|
164 { |
|
165 if (frameNamespaces && !m_groupName.isEmpty()) { |
|
166 HashSet<Page*>* oldNamespace = frameNamespaces->get(m_groupName); |
|
167 if (oldNamespace) { |
|
168 oldNamespace->remove(this); |
|
169 if (oldNamespace->isEmpty()) { |
|
170 frameNamespaces->remove(m_groupName); |
|
171 delete oldNamespace; |
|
172 } |
|
173 } |
|
174 } |
|
175 m_groupName = name; |
|
176 if (!name.isEmpty()) { |
|
177 if (!frameNamespaces) |
|
178 frameNamespaces = new HashMap<String, HashSet<Page*>*>; |
|
179 HashSet<Page*>* newNamespace = frameNamespaces->get(name); |
|
180 if (!newNamespace) { |
|
181 newNamespace = new HashSet<Page*>; |
|
182 frameNamespaces->add(name, newNamespace); |
|
183 } |
|
184 newNamespace->add(this); |
|
185 } |
|
186 } |
|
187 |
|
188 const HashSet<Page*>* Page::frameNamespace() const |
|
189 { |
|
190 return (frameNamespaces && !m_groupName.isEmpty()) ? frameNamespaces->get(m_groupName) : 0; |
|
191 } |
|
192 |
|
193 const HashSet<Page*>* Page::frameNamespace(const String& groupName) |
|
194 { |
|
195 return (frameNamespaces && !groupName.isEmpty()) ? frameNamespaces->get(groupName) : 0; |
|
196 } |
|
197 |
|
198 void Page::setNeedsReapplyStyles() |
|
199 { |
|
200 if (!allPages) |
|
201 return; |
|
202 HashSet<Page*>::iterator end = allPages->end(); |
|
203 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) |
|
204 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) |
|
205 frame->setNeedsReapplyStyles(); |
|
206 } |
|
207 |
|
208 const Selection& Page::selection() const |
|
209 { |
|
210 return focusController()->focusedOrMainFrame()->selectionController()->selection(); |
|
211 } |
|
212 |
|
213 void Page::setDefersLoading(bool defers) |
|
214 { |
|
215 if (defers == m_defersLoading) |
|
216 return; |
|
217 |
|
218 m_defersLoading = defers; |
|
219 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) |
|
220 frame->loader()->setDefersLoading(defers); |
|
221 } |
|
222 |
|
223 void Page::clearUndoRedoOperations() |
|
224 { |
|
225 m_editorClient->clearUndoRedoOperations(); |
|
226 } |
|
227 |
|
228 bool Page::inLowQualityImageInterpolationMode() const |
|
229 { |
|
230 return m_inLowQualityInterpolationMode; |
|
231 } |
|
232 |
|
233 void Page::setInLowQualityImageInterpolationMode(bool mode) |
|
234 { |
|
235 m_inLowQualityInterpolationMode = mode; |
|
236 } |
|
237 |
|
238 } // namespace WebCore |