--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKit2/WebProcess/WebPage/WebPage.cpp Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "WebPage.h"
+
+#include "Arguments.h"
+#include "DrawingArea.h"
+#include "InjectedBundle.h"
+#include "MessageID.h"
+#include "WebBackForwardControllerClient.h"
+#include "WebBackForwardListProxy.h"
+#include "WebChromeClient.h"
+#include "WebContextMenuClient.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebDragClient.h"
+#include "WebEditorClient.h"
+#include "WebEvent.h"
+#include "WebEventConversion.h"
+#include "WebFrame.h"
+#include "WebInspectorClient.h"
+#include "WebPageMessageKinds.h"
+#include "WebPageProxyMessageKinds.h"
+#include "WebPreferencesStore.h"
+#include "WebProcess.h"
+#include <WebCore/BackForwardList.h>
+#include <WebCore/EventHandler.h>
+#include <WebCore/FocusController.h>
+#include <WebCore/Frame.h>
+#include <WebCore/FrameLoaderTypes.h>
+#include <WebCore/FrameView.h>
+#include <WebCore/HistoryItem.h>
+#include <WebCore/KeyboardEvent.h>
+#include <WebCore/Page.h>
+#include <WebCore/PlatformKeyboardEvent.h>
+#include <WebCore/RenderTreeAsText.h>
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/Settings.h>
+#include <runtime/JSLock.h>
+#include <runtime/JSValue.h>
+
+#ifndef NDEBUG
+#include <wtf/RefCountedLeakCounter.h>
+#endif
+
+using namespace JSC;
+using namespace WebCore;
+
+namespace WebKit {
+
+#ifndef NDEBUG
+static WTF::RefCountedLeakCounter webPageCounter("WebPage");
+#endif
+
+PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, DrawingArea::Type drawingAreaType)
+{
+ return adoptRef(new WebPage(pageID, viewSize, store, drawingAreaType));
+}
+
+WebPage::WebPage(uint64_t pageID, const IntSize& viewSize, const WebPreferencesStore& store, DrawingArea::Type drawingAreaType)
+ : 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)))
+ , m_viewSize(viewSize)
+ , m_drawingArea(DrawingArea::create(drawingAreaType, this))
+ , m_pageID(pageID)
+{
+ ASSERT(m_pageID);
+
+ m_page->settings()->setJavaScriptEnabled(store.javaScriptEnabled);
+ m_page->settings()->setLoadsImagesAutomatically(store.loadsImagesAutomatically);
+ m_page->settings()->setPluginsEnabled(store.pluginsEnabled);
+ m_page->settings()->setOfflineWebApplicationCacheEnabled(store.offlineWebApplicationCacheEnabled);
+ m_page->settings()->setLocalStorageEnabled(store.localStorageEnabled);
+ m_page->settings()->setMinimumFontSize(store.minimumFontSize);
+ m_page->settings()->setMinimumLogicalFontSize(store.minimumLogicalFontSize);
+ m_page->settings()->setDefaultFontSize(store.defaultFontSize);
+ m_page->settings()->setDefaultFixedFontSize(store.defaultFixedFontSize);
+ m_page->settings()->setStandardFontFamily(store.standardFontFamily);
+ m_page->settings()->setCursiveFontFamily(store.cursiveFontFamily);
+ m_page->settings()->setFantasyFontFamily(store.fantasyFontFamily);
+ m_page->settings()->setFixedFontFamily(store.fixedFontFamily);
+ m_page->settings()->setSansSerifFontFamily(store.sansSerifFontFamily);
+ m_page->settings()->setSerifFontFamily(store.serifFontFamily);
+
+ platformInitialize();
+
+ m_mainFrame = WebFrame::createMainFrame(this);
+ WebProcess::shared().connection()->send(WebPageProxyMessage::DidCreateMainFrame, m_pageID, CoreIPC::In(m_mainFrame->frameID()));
+
+ if (WebProcess::shared().injectedBundle())
+ WebProcess::shared().injectedBundle()->didCreatePage(this);
+
+#ifndef NDEBUG
+ webPageCounter.increment();
+#endif
+}
+
+WebPage::~WebPage()
+{
+ ASSERT(!m_page);
+#ifndef NDEBUG
+ webPageCounter.decrement();
+#endif
+}
+
+void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)
+{
+ m_loaderClient.initialize(client);
+}
+
+void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client)
+{
+ m_uiClient.initialize(client);
+}
+
+String WebPage::renderTreeExternalRepresentation() const
+{
+ return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal);
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+void WebPage::changeAcceleratedCompositingMode(WebCore::GraphicsLayer* layer)
+{
+ bool compositing = layer;
+
+ // Tell the UI process that accelerated compositing changed. It may respond by changing
+ // drawing area types.
+ uint32_t newDrawingAreaType;
+ WebProcess::shared().connection()->sendSync(WebPageProxyMessage::DidChangeAcceleratedCompositing,
+ m_pageID, CoreIPC::In(compositing),
+ CoreIPC::Out(newDrawingAreaType),
+ CoreIPC::Connection::NoTimeout);
+
+ DrawingArea::Type newType = static_cast<DrawingArea::Type>(newDrawingAreaType);
+ if (newType != drawingArea()->type()) {
+ m_drawingArea = DrawingArea::create(newType, this);
+ m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize));
+ }
+}
+
+void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer)
+{
+ changeAcceleratedCompositingMode(layer);
+
+#if USE(ACCELERATED_COMPOSITING)
+ m_drawingArea->setRootCompositingLayer(layer);
+#endif
+}
+
+void WebPage::exitAcceleratedCompositingMode()
+{
+ changeAcceleratedCompositingMode(0);
+}
+#endif
+
+WebFrame* WebPage::webFrame(uint64_t frameID) const
+{
+ return m_frameMap.get(frameID);
+}
+
+void WebPage::addWebFrame(uint64_t frameID, WebFrame* frame)
+{
+ m_frameMap.set(frameID, frame);
+}
+
+void WebPage::removeWebFrame(uint64_t frameID)
+{
+ m_frameMap.remove(frameID);
+}
+
+void WebPage::close()
+{
+ if (WebProcess::shared().injectedBundle())
+ WebProcess::shared().injectedBundle()->willDestroyPage(this);
+
+ m_mainFrame->coreFrame()->loader()->detachFromParent();
+
+ delete m_page;
+ m_page = 0;
+
+ WebProcess::shared().removeWebPage(m_pageID);
+}
+
+void WebPage::tryClose()
+{
+ if (!m_mainFrame->coreFrame()->loader()->shouldClose())
+ return;
+
+ WebProcess::shared().connection()->send(WebPageProxyMessage::ClosePage, m_pageID, CoreIPC::In());
+}
+
+void WebPage::loadURL(const String& url)
+{
+ m_mainFrame->coreFrame()->loader()->load(ResourceRequest(KURL(KURL(), url)), false);
+}
+
+void WebPage::stopLoading()
+{
+ m_mainFrame->coreFrame()->loader()->stopForUserCancel();
+}
+
+void WebPage::reload(bool reloadFromOrigin)
+{
+ m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin);
+}
+
+void WebPage::goForward(uint64_t backForwardItemID)
+{
+ HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
+ m_page->goToItem(item, FrameLoadTypeForward);
+}
+
+void WebPage::goBack(uint64_t backForwardItemID)
+{
+ HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
+ m_page->goToItem(item, FrameLoadTypeBack);
+}
+
+void WebPage::goToBackForwardItem(uint64_t backForwardItemID)
+{
+ HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
+ m_page->goToItem(item, FrameLoadTypeIndexedBackForward);
+}
+
+void WebPage::layoutIfNeeded()
+{
+ if (m_mainFrame->coreFrame()->view())
+ m_mainFrame->coreFrame()->view()->layoutIfNeededRecursive();
+}
+
+void WebPage::setSize(const WebCore::IntSize& viewSize)
+{
+ if (m_viewSize == viewSize)
+ return;
+
+ Frame* frame = m_page->mainFrame();
+
+ frame->view()->resize(viewSize);
+ frame->view()->setNeedsLayout();
+ m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize));
+
+ m_viewSize = viewSize;
+}
+
+void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect)
+{
+ graphicsContext.save();
+ graphicsContext.clip(rect);
+ m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect);
+ graphicsContext.restore();
+}
+
+// Events
+
+void WebPage::mouseEvent(const PlatformMouseEvent& event)
+{
+ if (!m_mainFrame->coreFrame()->view())
+ return;
+
+ switch (event.eventType()) {
+ case WebCore::MouseEventPressed:
+ m_mainFrame->coreFrame()->eventHandler()->handleMousePressEvent(event);
+ break;
+ case WebCore::MouseEventReleased:
+ m_mainFrame->coreFrame()->eventHandler()->handleMouseReleaseEvent(event);
+ break;
+ case WebCore::MouseEventMoved:
+ m_mainFrame->coreFrame()->eventHandler()->mouseMoved(event);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+void WebPage::wheelEvent(PlatformWheelEvent& event)
+{
+ if (!m_mainFrame->coreFrame()->view())
+ return;
+
+ m_mainFrame->coreFrame()->eventHandler()->handleWheelEvent(event);
+}
+
+void WebPage::keyEvent(const PlatformKeyboardEvent& event)
+{
+ if (!m_mainFrame->coreFrame()->view())
+ return;
+
+ m_page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(event);
+}
+
+void WebPage::setActive(bool isActive)
+{
+ m_page->focusController()->setActive(isActive);
+}
+
+void WebPage::setFocused(bool isFocused)
+{
+ m_page->focusController()->setFocused(isFocused);
+}
+
+void WebPage::setIsInWindow(bool isInWindow)
+{
+ if (!isInWindow) {
+ m_page->setCanStartMedia(false);
+ m_page->willMoveOffscreen();
+ } else {
+ m_page->setCanStartMedia(true);
+ m_page->didMoveOnscreen();
+ }
+}
+
+void WebPage::didReceivePolicyDecision(WebFrame* frame, uint64_t listenerID, WebCore::PolicyAction policyAction)
+{
+ if (!frame)
+ return;
+ frame->didReceivePolicyDecision(listenerID, policyAction);
+}
+
+void WebPage::show()
+{
+ WebProcess::shared().connection()->send(WebPageProxyMessage::ShowPage, m_pageID, CoreIPC::In());
+}
+
+void WebPage::runJavaScriptInMainFrame(const WebCore::String& script, uint64_t callbackID)
+{
+ // NOTE: We need to be careful when running scripts that the objects we depend on don't
+ // disappear during script execution.
+
+ JSLock lock(SilenceAssertionsOnly);
+ JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue();
+ String resultString = ustringToString(resultValue.toString(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec()));
+
+ WebProcess::shared().connection()->send(WebPageProxyMessage::DidRunJavaScriptInMainFrame, m_pageID, CoreIPC::In(resultString, callbackID));
+}
+
+void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID)
+{
+ String resultString = renderTreeExternalRepresentation();
+ WebProcess::shared().connection()->send(WebPageProxyMessage::DidGetRenderTreeExternalRepresentation, m_pageID, CoreIPC::In(resultString, callbackID));
+}
+
+void WebPage::preferencesDidChange(const WebPreferencesStore& store)
+{
+ m_page->settings()->setJavaScriptEnabled(store.javaScriptEnabled);
+ m_page->settings()->setLoadsImagesAutomatically(store.loadsImagesAutomatically);
+ m_page->settings()->setOfflineWebApplicationCacheEnabled(store.offlineWebApplicationCacheEnabled);
+ m_page->settings()->setLocalStorageEnabled(store.localStorageEnabled);
+}
+
+bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt)
+{
+ Node* node = evt->target()->toNode();
+ ASSERT(node);
+ Frame* frame = node->document()->frame();
+ ASSERT(frame);
+
+ const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
+ if (!keyEvent)
+ return false;
+
+ Editor::Command command = frame->editor()->command(interpretKeyEvent(evt));
+
+ if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
+ // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
+ // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
+ // (e.g. Tab that inserts a Tab character, or Enter).
+ return !command.isTextInsertion() && command.execute(evt);
+ }
+
+ if (command.execute(evt))
+ return true;
+
+ // Don't insert null or control characters as they can result in unexpected behaviour
+ if (evt->charCode() < ' ')
+ return false;
+
+ return frame->editor()->insertText(evt->keyEvent()->text(), evt);
+}
+
+void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder& arguments)
+{
+ if (messageID.is<CoreIPC::MessageClassDrawingArea>()) {
+ ASSERT(m_drawingArea);
+ m_drawingArea->didReceiveMessage(connection, messageID, arguments);
+ return;
+ }
+
+ switch (messageID.get<WebPageMessage::Kind>()) {
+ case WebPageMessage::SetActive: {
+ bool active;
+ if (!arguments.decode(active))
+ return;
+
+ setActive(active);
+ return;
+ }
+ case WebPageMessage::SetFocused: {
+ bool focused;
+ if (!arguments.decode(focused))
+ return;
+
+ setFocused(focused);
+ return;
+ }
+ case WebPageMessage::SetIsInWindow: {
+ bool isInWindow;
+ if (!arguments.decode(isInWindow))
+ return;
+
+ setIsInWindow(isInWindow);
+ return;
+ }
+ case WebPageMessage::MouseEvent: {
+ WebMouseEvent event;
+ if (!arguments.decode(event))
+ return;
+ connection->send(WebPageProxyMessage::DidReceiveEvent, m_pageID, CoreIPC::In((uint32_t)event.type()));
+ PlatformMouseEvent platformEvent = platform(event);
+ mouseEvent(platformEvent);
+ return;
+ }
+ case WebPageMessage::PreferencesDidChange: {
+ WebPreferencesStore store;
+ if (!arguments.decode(store))
+ return;
+
+ preferencesDidChange(store);
+ return;
+ }
+ case WebPageMessage::WheelEvent: {
+ WebWheelEvent event;
+ if (!arguments.decode(event))
+ return;
+ connection->send(WebPageProxyMessage::DidReceiveEvent, m_pageID, CoreIPC::In((uint32_t)event.type()));
+ PlatformWheelEvent platformEvent = platform(event);
+ wheelEvent(platformEvent);
+ return;
+ }
+ case WebPageMessage::KeyEvent: {
+ WebKeyboardEvent event;
+ if (!arguments.decode(event))
+ return;
+ connection->send(WebPageProxyMessage::DidReceiveEvent, m_pageID, CoreIPC::In((uint32_t)event.type()));
+ PlatformKeyboardEvent platformEvent = platform(event);
+ keyEvent(platformEvent);
+ return;
+ }
+ case WebPageMessage::LoadURL: {
+ String url;
+ if (!arguments.decode(url))
+ return;
+
+ loadURL(url);
+ return;
+ }
+ case WebPageMessage::StopLoading:
+ stopLoading();
+ break;
+ case WebPageMessage::Reload: {
+ bool reloadFromOrigin;
+ if (!arguments.decode(CoreIPC::Out(reloadFromOrigin)))
+ return;
+
+ reload(reloadFromOrigin);
+ return;
+ }
+ case WebPageMessage::GoForward: {
+ uint64_t backForwardItemID;
+ if (!arguments.decode(CoreIPC::Out(backForwardItemID)))
+ return;
+ goForward(backForwardItemID);
+ return;
+ }
+ case WebPageMessage::GoBack: {
+ uint64_t backForwardItemID;
+ if (!arguments.decode(CoreIPC::Out(backForwardItemID)))
+ return;
+ goBack(backForwardItemID);
+ return;
+ }
+ case WebPageMessage::GoToBackForwardItem: {
+ uint64_t backForwardItemID;
+ if (!arguments.decode(CoreIPC::Out(backForwardItemID)))
+ return;
+ goToBackForwardItem(backForwardItemID);
+ return;
+ }
+ case WebPageMessage::DidReceivePolicyDecision: {
+ uint64_t frameID;
+ uint64_t listenerID;
+ uint32_t policyAction;
+ if (!arguments.decode(CoreIPC::Out(frameID, listenerID, policyAction)))
+ return;
+ didReceivePolicyDecision(webFrame(frameID), listenerID, (WebCore::PolicyAction)policyAction);
+ return;
+ }
+ case WebPageMessage::RunJavaScriptInMainFrame: {
+ String script;
+ uint64_t callbackID;
+ if (!arguments.decode(CoreIPC::Out(script, callbackID)))
+ return;
+ runJavaScriptInMainFrame(script, callbackID);
+ return;
+ }
+ case WebPageMessage::GetRenderTreeExternalRepresentation: {
+ uint64_t callbackID;
+ if (!arguments.decode(callbackID))
+ return;
+ getRenderTreeExternalRepresentation(callbackID);
+ return;
+ }
+ case WebPageMessage::Close: {
+ close();
+ return;
+ }
+ case WebPageMessage::TryClose: {
+ tryClose();
+ return;
+ }
+ }
+
+ ASSERT_NOT_REACHED();
+}
+
+} // namespace WebKit