|
1 /* |
|
2 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> |
|
3 * |
|
4 * All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions |
|
8 * are met: |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * 2. Redistributions in binary form must reproduce the above copyright |
|
12 * notice, this list of conditions and the following disclaimer in the |
|
13 * documentation and/or other materials provided with the distribution. |
|
14 * |
|
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
|
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
|
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
|
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
26 */ |
|
27 |
|
28 #include "config.h" |
|
29 |
|
30 #include "Frame.h" |
|
31 #include "DocLoader.h" |
|
32 #include "ResourceHandle.h" |
|
33 #include "DeprecatedString.h" |
|
34 #include "ResourceHandleManagerSymbian.h" |
|
35 #include "ResourceHandleInternal.h" |
|
36 #include "WebCoreFrameBridge.h" |
|
37 #include "UrlConnection.h" |
|
38 #include "StaticObjectsContainer.h" |
|
39 #include "ResourceLoaderDelegate.h" |
|
40 |
|
41 #include "SynchRequest.h" |
|
42 |
|
43 #include "BrCtl.h" |
|
44 #include "FrameTree.h" |
|
45 #include "Page.h" |
|
46 #include "WebFrame.h" |
|
47 #include "WebFrameBridge.h" |
|
48 #include "WebFrameView.h" |
|
49 #include "WebView.h" |
|
50 #include "kjs_window.h" |
|
51 |
|
52 #define notImplemented() {} |
|
53 |
|
54 namespace WebCore { |
|
55 |
|
56 |
|
57 using namespace KJS; |
|
58 using namespace std; |
|
59 |
|
60 class EventDeferrer : Noncopyable { |
|
61 public: |
|
62 EventDeferrer(Frame*, bool deferSelf, bool pauseTimeouts); |
|
63 ~EventDeferrer(); |
|
64 private: |
|
65 Vector<RefPtr<Frame>, 16> m_deferredFrames; |
|
66 Vector<pair<RefPtr<Frame>, PausedTimeouts*>, 16> m_pausedTimeouts; |
|
67 }; |
|
68 |
|
69 |
|
70 class AsyncCancel : public MUrlConnection, public CAsyncOneShot |
|
71 { |
|
72 public: |
|
73 AsyncCancel(ResourceHandle* _handle) : MUrlConnection(_handle), CAsyncOneShot(CActive::EPriorityHigh + 1) {} |
|
74 |
|
75 virtual ~AsyncCancel() {} |
|
76 virtual int submit() {Call(); return KErrNone;} |
|
77 virtual void cancel() { CActive::Cancel(); } |
|
78 virtual void download(WebCore::ResourceHandle* handle, const WebCore::ResourceRequest& request, const WebCore::ResourceResponse& response) {} |
|
79 virtual int totalContentSize() { return 0; } |
|
80 void response() {} |
|
81 void complete(int error) {} |
|
82 private: |
|
83 void RunL() |
|
84 { |
|
85 CResourceHandleManager::self()->receivedFinished(m_handle, KErrCancel, this); |
|
86 derefHandle(); |
|
87 } |
|
88 }; |
|
89 |
|
90 |
|
91 ResourceHandleInternal::~ResourceHandleInternal() |
|
92 { |
|
93 } |
|
94 |
|
95 ResourceHandle::~ResourceHandle() |
|
96 { |
|
97 cancel(); |
|
98 delete d->m_connection; |
|
99 } |
|
100 |
|
101 bool ResourceHandle::start(Frame* frame) |
|
102 { |
|
103 ASSERT(frame); |
|
104 |
|
105 if (!frame) |
|
106 return false; |
|
107 |
|
108 // If we are no longer attached to a Page, this must be an attempted load from an |
|
109 // onUnload handler, so let's just block it. |
|
110 if (!frame->page()) |
|
111 return false; |
|
112 |
|
113 // |
|
114 d->m_connection = StaticObjectsContainer::instance()->resourceLoaderDelegate()->CreateUrlConnection(this, frame); |
|
115 int error = CResourceHandleManager::self()->add(this); |
|
116 if (d->m_connection == NULL || error != KErrNone) { |
|
117 // create fake connection to issue async cancel |
|
118 delete d->m_connection; |
|
119 d->m_connection = 0; |
|
120 d->m_connection = new AsyncCancel(this); |
|
121 if (d->m_connection){ |
|
122 d->m_connection->submit(); |
|
123 HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager(); |
|
124 // do not report errors on resource loads |
|
125 if (httpSessionMgr && httpSessionMgr->uiCallback() && request().mainLoad() && error != KErrNone) { |
|
126 httpSessionMgr->uiCallback()->reportError(error); |
|
127 } |
|
128 } |
|
129 } |
|
130 return (d->m_connection != NULL); |
|
131 } |
|
132 |
|
133 void ResourceHandle::cancel() |
|
134 { |
|
135 CResourceHandleManager::self()->cancel(this); |
|
136 } |
|
137 |
|
138 bool ResourceHandle::loadsBlocked() |
|
139 { |
|
140 // tot:fixme loads should be blocked when a modal dialog is open |
|
141 notImplemented(); |
|
142 return false; |
|
143 } |
|
144 |
|
145 bool ResourceHandle::willLoadFromCache(ResourceRequest& request) |
|
146 { |
|
147 // tot:fixme should set a flag is the content is coming from cache, so that we don't load favicons from the network |
|
148 notImplemented(); |
|
149 return false; |
|
150 } |
|
151 |
|
152 bool ResourceHandle::supportsBufferedData() |
|
153 { |
|
154 notImplemented(); |
|
155 return false; |
|
156 } |
|
157 |
|
158 PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() |
|
159 { |
|
160 notImplemented(); |
|
161 return 0; |
|
162 } |
|
163 |
|
164 void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, |
|
165 ResourceError& e, |
|
166 ResourceResponse& r, |
|
167 Vector<char>& data, |
|
168 Frame* frame) |
|
169 { |
|
170 ASSERT(frame); |
|
171 // Call control() in WebFrame to get current webView |
|
172 control(frame)->webView()->synchRequestPending(true); |
|
173 |
|
174 EventDeferrer deferrer(frame, false, true); // Need to suspend timer events |
|
175 |
|
176 CSynchRequest* synchXHR = CSynchRequest::NewL(); |
|
177 CleanupStack::PushL(synchXHR); |
|
178 synchXHR->CreateResource(request, e, r, data, frame); |
|
179 CleanupStack::PopAndDestroy(synchXHR); |
|
180 |
|
181 if (frame) { // Frame may be gone by now? (in case of user's navigation) |
|
182 control(frame)->webView()->synchRequestPending(false); |
|
183 } |
|
184 } |
|
185 |
|
186 void ResourceHandle::setDefersLoading(bool defers) |
|
187 { |
|
188 d->m_defersLoading = defers; |
|
189 d->m_connection->setDefersLoading(defers); |
|
190 |
|
191 } |
|
192 |
|
193 EventDeferrer::EventDeferrer(Frame* thisFrame, bool deferSelf, bool pauseTimeouts) |
|
194 { |
|
195 const HashSet<Page*>* group = thisFrame->page()->frameNamespace(); |
|
196 |
|
197 if (!group) |
|
198 return; |
|
199 |
|
200 HashSet<Page*>::const_iterator end = group->end(); |
|
201 for (HashSet<Page*>::const_iterator it = group->begin(); it != end; ++it) { |
|
202 Page* otherPage = *it; |
|
203 if ((deferSelf || pauseTimeouts)) { |
|
204 if (!otherPage->defersLoading() && (deferSelf || otherPage != thisFrame->page())) { |
|
205 m_deferredFrames.append(otherPage->mainFrame()); |
|
206 } |
|
207 |
|
208 if (pauseTimeouts) { |
|
209 for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) { |
|
210 if (Window* window = Window::retrieveWindow(frame)) { |
|
211 PausedTimeouts* timeouts = window->pauseTimeouts(); |
|
212 m_pausedTimeouts.append(make_pair(frame, timeouts)); |
|
213 } |
|
214 } |
|
215 } |
|
216 } |
|
217 } |
|
218 |
|
219 size_t count = m_deferredFrames.size(); |
|
220 for (size_t i = 0; i < count; ++i) { |
|
221 if (Page* page = m_deferredFrames[i]->page()) { |
|
222 page->setDefersLoading(true); |
|
223 } |
|
224 } |
|
225 } |
|
226 |
|
227 EventDeferrer::~EventDeferrer() |
|
228 { |
|
229 size_t count = m_deferredFrames.size(); |
|
230 for (size_t i = 0; i < count; ++i) { |
|
231 if (Page* page = m_deferredFrames[i]->page()) { |
|
232 page->setDefersLoading(false); |
|
233 } |
|
234 } |
|
235 |
|
236 count = m_pausedTimeouts.size(); |
|
237 |
|
238 for (size_t i = 0; i < count; i++) { |
|
239 Window* window = Window::retrieveWindow(m_pausedTimeouts[i].first.get()); |
|
240 if (window) { |
|
241 window->resumeTimeouts(m_pausedTimeouts[i].second); |
|
242 } |
|
243 delete m_pausedTimeouts[i].second; |
|
244 } |
|
245 } |
|
246 |
|
247 } // namespace WebCore |