WebKit2 does not have application cache
[WebKit.git] / WebKit2 / WebProcess / WebPage / WebPage.cpp
1 /*
2  * Copyright (C) 2010 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 "WebPage.h"
27
28 #include "Arguments.h"
29 #include "DrawingArea.h"
30 #include "InjectedBundle.h"
31 #include "MessageID.h"
32 #include "WebBackForwardControllerClient.h"
33 #include "WebBackForwardListProxy.h"
34 #include "WebChromeClient.h"
35 #include "WebContextMenuClient.h"
36 #include "WebCoreArgumentCoders.h"
37 #include "WebDragClient.h"
38 #include "WebEditorClient.h"
39 #include "WebEvent.h"
40 #include "WebEventConversion.h"
41 #include "WebFrame.h"
42 #include "WebInspectorClient.h"
43 #include "WebPageMessageKinds.h"
44 #include "WebPageProxyMessageKinds.h"
45 #include "WebPreferencesStore.h"
46 #include "WebProcess.h"
47 #include <WebCore/BackForwardList.h>
48 #include <WebCore/EventHandler.h>
49 #include <WebCore/FocusController.h>
50 #include <WebCore/Frame.h>
51 #include <WebCore/FrameLoaderTypes.h>
52 #include <WebCore/FrameView.h>
53 #include <WebCore/HistoryItem.h>
54 #include <WebCore/KeyboardEvent.h>
55 #include <WebCore/Page.h>
56 #include <WebCore/PlatformKeyboardEvent.h>
57 #include <WebCore/RenderTreeAsText.h>
58 #include <WebCore/ResourceRequest.h>
59 #include <WebCore/Settings.h>
60 #include <runtime/JSLock.h>
61 #include <runtime/JSValue.h>
62
63 #ifndef NDEBUG
64 #include <wtf/RefCountedLeakCounter.h>
65 #endif
66
67 using namespace JSC;
68 using namespace WebCore;
69
70 namespace WebKit {
71
72 #ifndef NDEBUG
73 static WTF::RefCountedLeakCounter webPageCounter("WebPage");
74 #endif
75
76 PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, DrawingArea::Type drawingAreaType)
77 {
78     return adoptRef(new WebPage(pageID, viewSize, store, drawingAreaType));
79 }
80
81 WebPage::WebPage(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, DrawingArea::Type drawingAreaType)
82     : m_page(new Page(new WebChromeClient(this), new WebContextMenuClient(this), new WebEditorClient(this), new WebDragClient(this), new WebInspectorClient(this), 0, 0, 0, new WebBackForwardControllerClient(this)))
83     , m_viewSize(viewSize)
84     , m_drawingArea(DrawingArea::create(drawingAreaType, this))
85     , m_pageID(pageID)
86 {
87     ASSERT(m_pageID);
88
89     m_page->settings()->setJavaScriptEnabled(store.javaScriptEnabled);
90     m_page->settings()->setLoadsImagesAutomatically(store.loadsImagesAutomatically);
91     m_page->settings()->setPluginsEnabled(store.pluginsEnabled);
92     m_page->settings()->setMinimumFontSize(store.minimumFontSize);
93     m_page->settings()->setMinimumLogicalFontSize(store.minimumLogicalFontSize);
94     m_page->settings()->setDefaultFontSize(store.defaultFontSize);
95     m_page->settings()->setDefaultFixedFontSize(store.defaultFixedFontSize);
96     m_page->settings()->setStandardFontFamily(store.standardFontFamily);
97     m_page->settings()->setCursiveFontFamily(store.cursiveFontFamily);
98     m_page->settings()->setFantasyFontFamily(store.fantasyFontFamily);
99     m_page->settings()->setFixedFontFamily(store.fixedFontFamily);
100     m_page->settings()->setSansSerifFontFamily(store.sansSerifFontFamily);
101     m_page->settings()->setSerifFontFamily(store.serifFontFamily);
102
103     platformInitialize();
104
105     m_mainFrame = WebFrame::createMainFrame(this);
106     WebProcess::shared().connection()->send(WebPageProxyMessage::DidCreateMainFrame, m_pageID, CoreIPC::In(m_mainFrame->frameID()));
107
108     if (WebProcess::shared().injectedBundle())
109         WebProcess::shared().injectedBundle()->didCreatePage(this);
110
111 #ifndef NDEBUG
112     webPageCounter.increment();
113 #endif
114 }
115
116 WebPage::~WebPage()
117 {
118     ASSERT(!m_page);
119 #ifndef NDEBUG
120     webPageCounter.decrement();
121 #endif
122 }
123
124 void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
125 {
126     m_loaderClient.initialize(client);
127 }
128
129 void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
130 {
131     m_uiClient.initialize(client);
132 }
133
134 String WebPage::renderTreeExternalRepresentation() const
135 {
136     return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
137 }
138
139 WebFrame* WebPage::webFrame(uint64_t frameID) const
140 {
141     return m_frameMap.get(frameID);
142 }
143
144 void WebPage::addWebFrame(uint64_t frameID, WebFrame* frame)
145 {
146     m_frameMap.set(frameID, frame);
147 }
148
149 void WebPage::removeWebFrame(uint64_t frameID)
150 {
151     m_frameMap.remove(frameID);
152 }
153
154 void WebPage::close()
155 {
156     if (WebProcess::shared().injectedBundle())
157         WebProcess::shared().injectedBundle()->willDestroyPage(this);
158
159     m_mainFrame->coreFrame()->loader()->detachFromParent();
160
161     delete m_page;
162     m_page = 0;
163
164     WebProcess::shared().removeWebPage(m_pageID);
165 }
166
167 void WebPage::tryClose()
168 {
169     if (!m_mainFrame->coreFrame()->loader()->shouldClose())
170         return;
171
172     WebProcess::shared().connection()->send(WebPageProxyMessage::ClosePage, m_pageID, CoreIPC::In());
173 }
174
175 void WebPage::loadURL(const String& url)
176 {
177     m_mainFrame->coreFrame()->loader()->load(ResourceRequest(KURL(KURL(), url)), false);
178 }
179
180 void WebPage::stopLoading()
181 {
182     m_mainFrame->coreFrame()->loader()->stopForUserCancel();
183 }
184
185 void WebPage::reload(bool reloadFromOrigin)
186 {
187     m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
188 }
189
190 void WebPage::goForward(uint64_t backForwardItemID)
191 {
192     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
193     m_page->goToItem(item, FrameLoadTypeForward);
194 }
195
196 void WebPage::goBack(uint64_t backForwardItemID)
197 {
198     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
199     m_page->goToItem(item, FrameLoadTypeBack);
200 }
201
202 void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
203 {
204     HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
205     m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
206 }
207
208 void WebPage::layoutIfNeeded()
209 {
210     if (m_mainFrame->coreFrame()->view())
211         m_mainFrame->coreFrame()->view()->layoutIfNeededRecursive();
212 }
213
214 void WebPage::setSize(const WebCore::IntSize& viewSize)
215 {
216     if (m_viewSize == viewSize)
217         return;
218
219     Frame* frame = m_page->mainFrame();
220     
221     frame->view()->resize(viewSize);
222     frame->view()->setNeedsLayout();
223     m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
224     
225     m_viewSize = viewSize;
226 }
227
228 void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
229 {
230     graphicsContext.save();
231     graphicsContext.clip(rect);
232     m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
233     graphicsContext.restore();
234 }
235
236 // Events 
237
238 void WebPage::mouseEvent(const PlatformMouseEvent& event)
239 {
240     if (!m_mainFrame->coreFrame()->view())
241         return;
242
243     switch (event.eventType()) {
244         case WebCore::MouseEventPressed:
245             m_mainFrame->coreFrame()->eventHandler()->handleMousePressEvent(event);
246             break;
247         case WebCore::MouseEventReleased:
248             m_mainFrame->coreFrame()->eventHandler()->handleMouseReleaseEvent(event);
249             break;
250         case WebCore::MouseEventMoved:
251             m_mainFrame->coreFrame()->eventHandler()->mouseMoved(event);
252             break;
253         default:
254             ASSERT_NOT_REACHED();
255             break;
256     }
257 }
258
259 void WebPage::wheelEvent(PlatformWheelEvent& event)
260 {
261     if (!m_mainFrame->coreFrame()->view())
262         return;
263
264     m_mainFrame->coreFrame()->eventHandler()->handleWheelEvent(event);
265 }
266
267 void WebPage::keyEvent(const PlatformKeyboardEvent& event)
268 {
269     if (!m_mainFrame->coreFrame()->view())
270         return;
271
272     m_page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(event);
273 }
274
275 void WebPage::setActive(bool isActive)
276 {
277     m_page->focusController()->setActive(isActive);
278 }
279
280 void WebPage::setFocused(bool isFocused)
281 {
282     m_page->focusController()->setFocused(isFocused);
283 }
284
285 void WebPage::setIsInWindow(bool isInWindow)
286 {
287     if (!isInWindow) {
288         m_page->setCanStartMedia(false);
289         m_page->willMoveOffscreen();
290     } else {
291         m_page->setCanStartMedia(true);
292         m_page->didMoveOnscreen();
293     }
294 }
295
296 void WebPage::didReceivePolicyDecision(WebFrame* frame, uint64_t listenerID, WebCore::PolicyAction policyAction)
297 {
298     if (!frame)
299         return;
300     frame->didReceivePolicyDecision(listenerID, policyAction);
301 }
302
303 void WebPage::show()
304 {
305     WebProcess::shared().connection()->send(WebPageProxyMessage::ShowPage, m_pageID, CoreIPC::In());
306 }
307
308 void WebPage::runJavaScriptInMainFrame(const WebCore::String& script, uint64_t callbackID)
309 {
310     // NOTE: We need to be careful when running scripts that the objects we depend on don't
311     // disappear during script execution.
312
313     JSLock lock(SilenceAssertionsOnly);
314     JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
315     String resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
316
317     WebProcess::shared().connection()->send(WebPageProxyMessage::DidRunJavaScriptInMainFrame, m_pageID, CoreIPC::In(resultString, callbackID));
318 }
319
320 void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
321 {
322     String resultString = renderTreeExternalRepresentation();
323     WebProcess::shared().connection()->send(WebPageProxyMessage::DidGetRenderTreeExternalRepresentation, m_pageID, CoreIPC::In(resultString, callbackID));
324 }
325
326 void WebPage::preferencesDidChange(const WebPreferencesStore& store)
327 {
328     m_page->settings()->setJavaScriptEnabled(store.javaScriptEnabled);
329     m_page->settings()->setLoadsImagesAutomatically(store.loadsImagesAutomatically);
330     m_page->settings()->setOfflineWebApplicationCacheEnabled(store.offlineWebApplicationCacheEnabled);
331 }
332
333 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
334 {
335     Node* node = evt->target()->toNode();
336     ASSERT(node);
337     Frame* frame = node->document()->frame();
338     ASSERT(frame);
339
340     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
341     if (!keyEvent)
342         return false;
343
344     Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
345
346     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
347         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
348         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
349         // (e.g. Tab that inserts a Tab character, or Enter).
350         return !command.isTextInsertion() && command.execute(evt);
351     }
352
353      if (command.execute(evt))
354         return true;
355
356     // Don't insert null or control characters as they can result in unexpected behaviour
357     if (evt->charCode() < ' ')
358         return false;
359
360     return frame->editor()->insertText(evt->keyEvent()->text(), evt);
361 }
362
363 void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder& arguments)
364 {
365     if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
366         ASSERT(m_drawingArea);
367         m_drawingArea->didReceiveMessage(connection, messageID, arguments);
368         return;
369     }
370
371     switch (messageID.get<WebPageMessage::Kind>()) {
372         case WebPageMessage::SetActive: {
373             bool active;
374             if (!arguments.decode(active))
375                 return;
376          
377             setActive(active);
378             return;
379         }
380         case WebPageMessage::SetFocused: {
381             bool focused;
382             if (!arguments.decode(focused))
383                 return;
384             
385             setFocused(focused);
386             return;
387         }
388         case WebPageMessage::SetIsInWindow: {
389             bool isInWindow;
390             if (!arguments.decode(isInWindow))
391                 return;
392             
393             setIsInWindow(isInWindow);
394             return;
395         }
396         case WebPageMessage::MouseEvent: {
397             WebMouseEvent event;
398             if (!arguments.decode(event))
399                 return;
400             connection->send(WebPageProxyMessage::DidReceiveEvent, m_pageID, CoreIPC::In((uint32_t)event.type()));
401             PlatformMouseEvent platformEvent = platform(event);
402             mouseEvent(platformEvent);
403             return;
404         }
405         case WebPageMessage::PreferencesDidChange: {
406             WebPreferencesStore store;
407             if (!arguments.decode(store))
408                 return;
409             
410             preferencesDidChange(store);
411             return;
412         }
413         case WebPageMessage::WheelEvent: {
414             WebWheelEvent event;
415             if (!arguments.decode(event))
416                 return;
417             connection->send(WebPageProxyMessage::DidReceiveEvent, m_pageID, CoreIPC::In((uint32_t)event.type()));
418             PlatformWheelEvent platformEvent = platform(event);
419             wheelEvent(platformEvent);
420             return;
421         }
422         case WebPageMessage::KeyEvent: {
423             WebKeyboardEvent event;
424             if (!arguments.decode(event))
425                 return;
426             connection->send(WebPageProxyMessage::DidReceiveEvent, m_pageID, CoreIPC::In((uint32_t)event.type()));
427             PlatformKeyboardEvent platformEvent = platform(event);
428             keyEvent(platformEvent);
429             return;
430         }
431         case WebPageMessage::LoadURL: {
432             String url;
433             if (!arguments.decode(url))
434                 return;
435             
436             loadURL(url);
437             return;
438         }
439         case WebPageMessage::StopLoading:
440             stopLoading();
441             break;
442         case WebPageMessage::Reload: {
443             bool reloadFromOrigin;
444             if (!arguments.decode(CoreIPC::Out(reloadFromOrigin)))
445                 return;
446
447             reload(reloadFromOrigin);
448             return;
449         }
450         case WebPageMessage::GoForward: {
451             uint64_t backForwardItemID;
452             if (!arguments.decode(CoreIPC::Out(backForwardItemID)))
453                 return;
454             goForward(backForwardItemID);
455             return;
456         }
457         case WebPageMessage::GoBack: {
458             uint64_t backForwardItemID;
459             if (!arguments.decode(CoreIPC::Out(backForwardItemID)))
460                 return;
461             goBack(backForwardItemID);
462             return;
463         }
464        case WebPageMessage::GoToBackForwardItem: {
465             uint64_t backForwardItemID;
466             if (!arguments.decode(CoreIPC::Out(backForwardItemID)))
467                 return;
468             goToBackForwardItem(backForwardItemID);
469             return;
470         }
471         case WebPageMessage::DidReceivePolicyDecision: {
472             uint64_t frameID;
473             uint64_t listenerID;
474             uint32_t policyAction;
475             if (!arguments.decode(CoreIPC::Out(frameID, listenerID, policyAction)))
476                 return;
477             didReceivePolicyDecision(webFrame(frameID), listenerID, (WebCore::PolicyAction)policyAction);
478             return;
479         }
480         case WebPageMessage::RunJavaScriptInMainFrame: {
481             String script;
482             uint64_t callbackID;
483             if (!arguments.decode(CoreIPC::Out(script, callbackID)))
484                 return;
485             runJavaScriptInMainFrame(script, callbackID);
486             return;
487         }
488         case WebPageMessage::GetRenderTreeExternalRepresentation: {
489             uint64_t callbackID;
490             if (!arguments.decode(callbackID))
491                 return;
492             getRenderTreeExternalRepresentation(callbackID);
493             return;
494         }
495         case WebPageMessage::Close: {
496             close();
497             return;
498         }
499         case WebPageMessage::TryClose: {
500             tryClose();
501             return;
502         }
503     }
504
505     ASSERT_NOT_REACHED();
506 }
507
508 } // namespace WebKit